diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index f861489d..e981decd 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -76,7 +76,7 @@ extern "C" void ble_store_config_init(void); /** * Singletons for the NimBLEDevice. */ -NimBLEDeviceCallbacks NimBLEDevice::defaultDeviceCallbacks{}; +NimBLEDeviceCallbacks NimBLEDevice::defaultDeviceCallbacks{}; NimBLEDeviceCallbacks* NimBLEDevice::m_pDeviceCallbacks = &defaultDeviceCallbacks; # if defined(CONFIG_BT_NIMBLE_ROLE_OBSERVER) @@ -476,14 +476,14 @@ bool NimBLEDevice::setPower(int8_t dbm, NimBLETxPowerType type) { dbm++; // round up to the next multiple of 3 to be able to target 20dbm } - bool success = false; - esp_power_level_t espPwr = static_cast(dbm / 3 + ESP_PWR_LVL_N0); + bool success = false; + esp_power_level_t espPwr = static_cast(dbm / 3 + ESP_PWR_LVL_N0); if (type == NimBLETxPowerType::All) { success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_ADV); success &= setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_SCAN); success &= setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_DEFAULT); } else if (type == NimBLETxPowerType::Advertise) { - success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_ADV); + success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_ADV); } else if (type == NimBLETxPowerType::Scan) { success = setPowerLevel(espPwr, ESP_BLE_PWR_TYPE_SCAN); } else if (type == NimBLETxPowerType::Connection) { @@ -495,15 +495,13 @@ bool NimBLEDevice::setPower(int8_t dbm, NimBLETxPowerType type) { # else (void)type; // unused NIMBLE_LOGD(LOG_TAG, ">> setPower: %d", dbm); - ble_hci_vs_set_tx_pwr_cp cmd{dbm}; - ble_hci_vs_set_tx_pwr_rp rsp{0}; - int rc = ble_hs_hci_send_vs_cmd(BLE_HCI_OCF_VS_SET_TX_PWR, &cmd, sizeof(cmd), &rsp, sizeof(rsp)); + int rc = ble_phy_tx_power_set(dbm); if (rc) { NIMBLE_LOGE(LOG_TAG, "failed to set TX power, rc: %04x\n", rc); return false; } - NIMBLE_LOGD(LOG_TAG, "TX power set to %d dBm\n", rsp.tx_power); + NIMBLE_LOGD(LOG_TAG, "TX power set to %d dBm\n", dbm); return true; # endif } // setPower @@ -539,7 +537,7 @@ int NimBLEDevice::getPower(NimBLETxPowerType type) { # endif # else (void)type; // unused - return ble_phy_txpwr_get(); + return ble_phy_tx_power_get(); # endif } // getPower @@ -844,7 +842,7 @@ bool NimBLEDevice::init(const std::string& deviceName) { if (!m_initialized) { # ifdef ESP_PLATFORM -# if defined(CONFIG_ENABLE_ARDUINO_DEPENDS) && SOC_BT_SUPPORTED +# if defined(CONFIG_ENABLE_ARDUINO_DEPENDS) && SOC_BT_SUPPORTED // make sure the linker includes esp32-hal-bt.c so Arduino init doesn't release BLE memory. btStarted(); # endif diff --git a/src/nimble/LICENSE b/src/nimble/LICENSE index 08b9b218..960e8257 100644 --- a/src/nimble/LICENSE +++ b/src/nimble/LICENSE @@ -215,3 +215,13 @@ under the following license: This product bundles tinycrypt, which is available under the "3-clause BSD" license. For details, and bundled files see: * ext/tinycrypt/LICENSE + +This product bundles and partly derives from parts of the Nordic nRF52 SDK, +which are available under a BSD style license. Relevant files are: + * babblesim/hw/mcu/nordic/nrf52_bsim/src/system_nrf52.c + +This product bundles additional files from CMSIS-CORE, but these files are +missing licensing information. The BSD license was subsequently added to +these files in later releases. These files are: + * babblesim/hw/mcu/nordic/nrf52_bsim/include/mcu/cmsis_nvic.h + diff --git a/src/nimble/README.md b/src/nimble/README.md index 07a893aa..00cb27c6 100644 --- a/src/nimble/README.md +++ b/src/nimble/README.md @@ -25,7 +25,21 @@ ## Overview -Apache NimBLE is an open-source Bluetooth 5.1 stack (both Host & Controller) + + + + + + + + + + + + +

+ +Apache NimBLE is an open-source Bluetooth 5.4 stack (both Host & Controller) that completely replaces the proprietary SoftDevice on Nordic chipsets. It is part of [Apache Mynewt project](https://github.com/apache/mynewt-core). @@ -41,9 +55,9 @@ Feature highlight: ## Supported hardware -Controller supports Nordic nRF51 and nRF52 chipsets. Host runs on any board -and architecture [supported](https://github.com/apache/mynewt-core#overview) -by Apache Mynewt OS. +Controller supports Nordic nRF51, nRF52 and nRF5340 chipsets as well as DA1469x (cmac) +from Renesas. Host runs on any board and architecture +[supported](https://github.com/apache/mynewt-core#overview) by Apache Mynewt OS. ## Browsing @@ -105,6 +119,16 @@ Implements a simple BLE peripheral that supports the Nordic UART / Serial Port Emulation service (https://developer.nordicsemi.com/nRF5_SDK/nRF51_SDK_v8.x.x/doc/8.0.0/s110/html/a00072.html). +## External projects using NimBLE + +Several other projects provide support for using NimBLE either by [NPL port](https://github.com/apache/mynewt-nimble/tree/master/porting) or forking: + + * [The Espressif ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/bluetooth/nimble/index.html) contains a NimBLE port for ESP-32 devices. + * [The RIOT](https://doc.riot-os.org/group__pkg__nimble.html) operating system contains a package for using NimBLE. + * [The Open IOT SDK](https://gitlab.arm.com/iot/open-iot-sdk/sdk) contains a NimBLE [port](https://gitlab.arm.com/iot/open-iot-sdk/sdk/-/tree/main/components/bluetooth) based on [CMSIS RTOSv2](https://www.keil.com/pack/doc/CMSIS/RTOS2/html/index.html), which is an RTOS interface implemented by either Amazon Freertos, CMSIS RTX or Azure ThreadX. + + If you publish a NimBLE port, please let us know to include it here! + # Getting Help If you are having trouble using or contributing to Apache Mynewt NimBLE, or just @@ -114,7 +138,7 @@ want to talk to a human about what you're working on, you can contact us via the Although not a formal channel, you can also find a number of core developers on the #mynewt channel on Freenode IRC or #general channel on [Mynewt Slack](https://mynewt.slack.com/join/shared_invite/enQtNjA1MTg0NzgyNzg3LTcyMmZiOGQzOGMxM2U4ODFmMTIwNjNmYTE5Y2UwYjQwZWIxNTE0MTUzY2JmMTEzOWFjYWZkNGM0YmM4MzAxNWQ) -Also, be sure to checkout the [Frequently Asked Questions](https://mynewt.apache.org/faq/answers) +Also, be sure to checkout the [Frequently Asked Questions](https://mynewt.apache.org/latest/mynewt_faq) for some help troubleshooting first. # Contributing diff --git a/src/nimble/RELEASE_NOTES.md b/src/nimble/RELEASE_NOTES.md index cde2ce27..afd5e92a 100644 --- a/src/nimble/RELEASE_NOTES.md +++ b/src/nimble/RELEASE_NOTES.md @@ -1,24 +1,20 @@ # RELEASE NOTES -20 April 2022 - Apache NimBLE v1.5.0 +09 August 2023 - Apache NimBLE v1.6.0 For full release notes, please visit the [Apache Mynewt Wiki](https://cwiki.apache.org/confluence/display/MYNEWT/Release+Notes). -Apache NimBLE is an open-source Bluetooth 5.3 stack (both Host & Controller) that completely +Apache NimBLE is an open-source Bluetooth 5.4 stack (both Host & Controller) that completely replaces the proprietary SoftDevice on Nordic chipsets. New features in this version of NimBLE include: -* Fake dual-mode option for controller -* LLCP tracing via HCI events -* Code size optimization for disabled GAP roles -* Support for PA/LNA -* LE Secure Connections Only mode -* Support for Bluetooth Core Specification 5.3 -* Connection subrating -* BabbleSim support -* Various bugfixes and improvements +* Initial support for ISO broacaster +* Support for Bluetooth Core Specification 5.4 +* FEM antenna control +* nRF PHY driver unification +* IPC HCI transport improvements If working on next-generation RTOS and Bluetooth protocol stack sounds exciting to you, get in touch, by sending a mail to the Apache Mynewt diff --git a/src/nimble/esp_port/esp-hci/include/esp_compiler.h b/src/nimble/esp_port/esp-hci/include/esp_compiler.h deleted file mode 100644 index 917c6602..00000000 --- a/src/nimble/esp_port/esp-hci/include/esp_compiler.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD -// -// Licensed 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 -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef __ESP_COMPILER_H -#define __ESP_COMPILER_H - -/* - * The likely and unlikely macro pairs: - * These macros are useful to place when application - * knows the majority ocurrence of a decision paths, - * placing one of these macros can hint the compiler - * to reorder instructions producing more optimized - * code. - */ -#if (CONFIG_COMPILER_OPTIMIZATION_PERF) -#ifndef likely -#define likely(x) __builtin_expect(!!(x), 1) -#endif -#ifndef unlikely -#define unlikely(x) __builtin_expect(!!(x), 0) -#endif -#else -#ifndef likely -#define likely(x) (x) -#endif -#ifndef unlikely -#define unlikely(x) (x) -#endif -#endif - -/* - * Utility macros used for designated initializers, which work differently - * in C99 and C++ standards mainly for aggregate types. - * The member separator, comma, is already part of the macro, please omit the trailing comma. - * Usage example: - * struct config_t { char* pchr; char arr[SIZE]; } config = { - * ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(pchr) - * ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(arr, "Value") - * }; - */ -#ifdef __cplusplus -#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) { .member = value }, -#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member) .member = { }, -#else -#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) .member = value, -#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member) -#endif - -#endif diff --git a/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c b/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c index 01afa969..9d43176e 100644 --- a/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c +++ b/src/nimble/esp_port/esp-hci/src/esp_nimble_hci.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,15 +9,22 @@ #include #include "nimble/porting/nimble/include/sysinit/sysinit.h" #include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/host/include/host/ble_hs.h" +#if CONFIG_BT_NIMBLE_ENABLED +# include "nimble/nimble/host/include/host/ble_hs.h" +#endif //CONFIG_BT_NIMBLE_ENABLED #include "nimble/porting/nimble/include/nimble/nimble_port.h" #include "nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h" -#include "../include/esp_nimble_hci.h" -#include "../../port/include/esp_nimble_mem.h" -//#include "bt_osi_mem.h" -#include -#include -#include "../include/esp_compiler.h" +#include "nimble/esp_port/esp-hci/include/esp_nimble_hci.h" +#include "nimble/esp_port/port/include/esp_nimble_mem.h" +#include "nimble/esp_port/port/include/bt_osi_mem.h" +#if CONFIG_BT_CONTROLLER_ENABLED +#include "esp_bt.h" +#endif +#include "freertos/semphr.h" +#include "esp_compiler.h" +#include "soc/soc_caps.h" +//#include "bt_common.h" +//#include "hci_log/bt_hci_log.h" #define NIMBLE_VHCI_TIMEOUT_MS 2000 #define BLE_HCI_EVENT_HDR_LEN (2) @@ -39,6 +46,7 @@ static void *ble_hci_rx_acl_hs_arg; + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT) + static SemaphoreHandle_t vhci_send_sem; const static char *LOG_TAG = "NimBLE"; @@ -47,9 +55,9 @@ void os_msys_buf_free(void); extern uint8_t ble_hs_enabled_state; void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, - void *cmd_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg) + void *cmd_arg, + ble_hci_trans_rx_acl_fn *acl_cb, + void *acl_arg) { ble_hci_rx_cmd_hs_cb = cmd_cb; ble_hci_rx_cmd_hs_arg = cmd_arg; @@ -57,7 +65,14 @@ void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb, ble_hci_rx_acl_hs_arg = acl_arg; } -/* Modified to use ipc calls in arduino to correct performance issues */ +void esp_vhci_host_send_packet_wrapper(uint8_t *data, uint16_t len) +{ +#if 0 + bt_hci_log_record_hci_data(data[0], &data[1], len - 1); +#endif + esp_vhci_host_send_packet(data, len); +} + int ble_hci_trans_hs_cmd_tx(uint8_t *cmd) { uint16_t len; @@ -71,7 +86,7 @@ int ble_hci_trans_hs_cmd_tx(uint8_t *cmd) } if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) { - esp_vhci_host_send_packet(cmd, len); + esp_vhci_host_send_packet_wrapper(cmd, len); } else { rc = BLE_HS_ETIMEOUT_HCI; } @@ -88,28 +103,27 @@ int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev) return rc; } -/* Modified to use ipc calls in arduino to correct performance issues */ int ble_hci_trans_hs_acl_tx(struct os_mbuf *om) { uint16_t len = 0; - uint8_t data[MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE) + 3], rc = 0; - + uint8_t data[MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE) + 1], rc = 0; /* If this packet is zero length, just free it */ if (OS_MBUF_PKTLEN(om) == 0) { os_mbuf_free_chain(om); return 0; } + data[0] = BLE_HCI_UART_H4_ACL; + len++; if (!esp_vhci_host_check_send_available()) { ESP_LOGD(LOG_TAG, "Controller not ready to receive packets"); } - len = 1 + OS_MBUF_PKTLEN(om); - data[0] = BLE_HCI_UART_H4_ACL; os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &data[1]); + len += OS_MBUF_PKTLEN(om); if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) { - esp_vhci_host_send_packet(data, len); + esp_vhci_host_send_packet_wrapper(data, len); } else { rc = BLE_HS_ETIMEOUT_HCI; } @@ -127,6 +141,8 @@ int ble_hci_trans_ll_acl_tx(struct os_mbuf *om) return rc; } + + int ble_hci_trans_reset(void) { /* No work to do. All allocated buffers are owned by the host or @@ -138,7 +154,7 @@ int ble_hci_trans_reset(void) static void ble_hci_rx_acl(uint8_t *data, uint16_t len) { - struct os_mbuf *m; + struct os_mbuf *m = NULL; int rc; int sr; if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE)) { @@ -149,14 +165,14 @@ static void ble_hci_rx_acl(uint8_t *data, uint16_t len) m = ble_transport_alloc_acl_from_ll(); if (!m) { - ESP_LOGD(LOG_TAG,"Failed to allocate buffer, retrying "); - /* Give some time to free buffer and try again */ - vTaskDelay(1); - } - } while(!m); + esp_rom_printf("Failed to allocate buffer, retrying "); + /* Give some time to free buffer and try again */ + vTaskDelay(1); + } + }while(!m); if ((rc = os_mbuf_append(m, data, len)) != 0) { - ESP_LOGE(LOG_TAG, "%s failed to os_mbuf_append; rc = %d", __func__, rc); + esp_rom_printf("%s failed to os_mbuf_append; rc = %d", __func__, rc); os_mbuf_free_chain(m); return; } @@ -176,14 +192,40 @@ static void controller_rcv_pkt_ready(void) } } +static void dummy_controller_rcv_pkt_ready(void) +{ + /* Dummy function */ +} + +void bt_record_hci_data(uint8_t *data, uint16_t len) +{ +#if 0 + if ((data[0] == BLE_HCI_UART_H4_EVT) && (data[1] == BLE_HCI_EVCODE_LE_META) && ((data[3] == BLE_HCI_LE_SUBEV_ADV_RPT) || (data[3] == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) + || (data[3] == BLE_HCI_LE_SUBEV_EXT_ADV_RPT) || (data[3] == BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT))) { + bt_hci_log_record_hci_adv(HCI_LOG_DATA_TYPE_ADV, &data[2], len - 2); + } else { + uint8_t data_type = ((data[0] == 2) ? HCI_LOG_DATA_TYPE_C2H_ACL : data[0]); + bt_hci_log_record_hci_data(data_type, &data[1], len - 1); + } +#endif // (BT_HCI_LOG_INCLUDED == TRUE) +} + +static int dummy_host_rcv_pkt(uint8_t *data, uint16_t len) +{ + /* Dummy function */ + return 0; +} + /* * @brief: BT controller callback function, to transfer data packet to the host */ static int host_rcv_pkt(uint8_t *data, uint16_t len) { + bt_record_hci_data(data, len); + if(!ble_hs_enabled_state) { /* If host is not enabled, drop the packet */ - ESP_LOGE(LOG_TAG, "Host not enabled. Dropping the packet!"); + esp_rom_printf("Host not enabled. Dropping the packet!"); return 0; } @@ -196,7 +238,7 @@ static int host_rcv_pkt(uint8_t *data, uint16_t len) assert(totlen <= UINT8_MAX + BLE_HCI_EVENT_HDR_LEN); if (totlen > MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE)) { - ESP_LOGE(LOG_TAG, "Received HCI data length at host (%d) exceeds maximum configured HCI event buffer size (%d).", + esp_rom_printf("Received HCI data length at host (%d) exceeds maximum configured HCI event buffer size (%d).", totlen, MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE)); ble_hs_sched_reset(BLE_HS_ECONTROLLER); return 0; @@ -235,6 +277,12 @@ static const esp_vhci_host_callback_t vhci_host_cb = { .notify_host_recv = host_rcv_pkt, }; +static const esp_vhci_host_callback_t dummy_vhci_host_cb = { + .notify_host_send_available = dummy_controller_rcv_pkt_ready, + .notify_host_recv = dummy_host_rcv_pkt, +}; + + extern void ble_transport_init(void); extern esp_err_t ble_buf_alloc(void); extern void ble_buf_free(void); @@ -283,6 +331,8 @@ esp_err_t esp_nimble_hci_deinit(void) } ble_transport_deinit(); + esp_vhci_host_register_callback(&dummy_vhci_host_cb); + ble_buf_free(); #if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) @@ -292,4 +342,4 @@ esp_err_t esp_nimble_hci_deinit(void) return ESP_OK; } -#endif +#endif //ESP_PLATFORM diff --git a/src/nimble/esp_port/port/include/bt_osi_mem.h b/src/nimble/esp_port/port/include/bt_osi_mem.h new file mode 100644 index 00000000..9ab06d0a --- /dev/null +++ b/src/nimble/esp_port/port/include/bt_osi_mem.h @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.h" +#include "esp_attr.h" +#include "esp_heap_caps.h" + +void *bt_osi_mem_malloc(size_t size); + +void *bt_osi_mem_calloc(size_t n, size_t size); + +void *bt_osi_mem_malloc_internal(size_t size); + +void *bt_osi_mem_calloc_internal(size_t n, size_t size); + +void bt_osi_mem_free(void *ptr); diff --git a/src/nimble/esp_port/port/include/esp_nimble_cfg.h b/src/nimble/esp_port/port/include/esp_nimble_cfg.h index e4198010..a81162ee 100644 --- a/src/nimble/esp_port/port/include/esp_nimble_cfg.h +++ b/src/nimble/esp_port/port/include/esp_nimble_cfg.h @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __ESP_NIMBLE_CFG__ #define __ESP_NIMBLE_CFG__ @@ -13,116 +18,318 @@ #define MYNEWT_VAL(x) MYNEWT_VAL_ ## x #define MYNEWT_VAL_CHOICE(_name, _val) MYNEWT_VAL_ ## _name ## __ ## _val +#ifndef IRAM_ATTR_64MCPU +#define IRAM_ATTR_64MCPU IRAM_ATTR +#endif + + +#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 +#define NIMBLE_CFG_CONTROLLER 0 +#else +#define NIMBLE_CFG_CONTROLLER CONFIG_BT_CONTROLLER_ENABLED +#endif + /*** kernel/os */ #ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT #ifdef CONFIG_BT_NIMBLE_MESH -#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT + 8) +#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT + 8) #else -#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT +#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT #endif #endif #ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE -#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292) -#endif - -#ifndef MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT -#define MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT (0) +#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE #endif #ifndef MYNEWT_VAL_MSYS_2_BLOCK_COUNT -#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT (0) +#define MYNEWT_VAL_MSYS_2_BLOCK_COUNT CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT #endif #ifndef MYNEWT_VAL_MSYS_2_BLOCK_SIZE -#define MYNEWT_VAL_MSYS_2_BLOCK_SIZE (0) +#define MYNEWT_VAL_MSYS_2_BLOCK_SIZE CONFIG_BT_NIMBLE_MSYS_2_BLOCK_SIZE #endif #ifndef MYNEWT_VAL_OS_CPUTIME_FREQ -#define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000) +//#define MYNEWT_VAL_OS_CPUTIME_FREQ (1000000) +#define MYNEWT_VAL_OS_CPUTIME_FREQ (32000) #endif #ifndef MYNEWT_VAL_OS_CPUTIME_TIMER_NUM -#define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (0) +#define MYNEWT_VAL_OS_CPUTIME_TIMER_NUM (5) +#endif + +#ifndef MYNEWT_VAL_TIMER_5 +#define MYNEWT_VAL_TIMER_5 1 +#endif + +#ifndef MYNEWT_VAL_BLE_HS_LOG_LVL +#define MYNEWT_VAL_BLE_HS_LOG_LVL CONFIG_BT_NIMBLE_LOG_LEVEL +#endif + +#ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG +#define MYNEWT_VAL_NEWT_FEATURE_LOGCFG 1 +#endif + +#ifndef MYNEWT_VAL_OS_TICKS_PER_SEC +#define MYNEWT_VAL_OS_TICKS_PER_SEC (100) #endif /*** nimble */ -#ifndef MYNEWT_VAL_BLE_EXT_ADV -#define MYNEWT_VAL_BLE_EXT_ADV (CONFIG_BT_NIMBLE_EXT_ADV) +#if CONFIG_BT_NIMBLE_ENABLED +#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__native +#define MYNEWT_VAL_BLE_TRANSPORT_HS__native (1) #endif -#ifndef MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE -#ifdef CONFIG_BT_NIMBLE_EXT_ADV -#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (CONFIG_BT_NIMBLE_MAX_EXT_ADV_DATA_LEN) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__native +#define MYNEWT_VAL_BLE_TRANSPORT_LL__native (0) +#endif + +#ifndef CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT +#define BLE_50_FEATURE_SUPPORT (0) #else -#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (0) +#define BLE_50_FEATURE_SUPPORT (CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT) #endif #endif -#ifndef MYNEWT_VAL_BLE_MAX_CONNECTIONS -#define MYNEWT_VAL_BLE_MAX_CONNECTIONS CONFIG_BT_NIMBLE_MAX_CONNECTIONS +#ifndef CONFIG_BT_NIMBLE_EXT_ADV +#define MYNEWT_VAL_BLE_EXT_ADV (0) +#else +#define MYNEWT_VAL_BLE_EXT_ADV (CONFIG_BT_NIMBLE_EXT_ADV) #endif -#ifndef MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES -#ifdef CONFIG_BT_NIMBLE_EXT_ADV -#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES) +#ifndef CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE +#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (31) #else -#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (0) +#define MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE (CONFIG_BT_NIMBLE_EXT_ADV_MAX_SIZE) #endif + +#ifndef CONFIG_BT_NIMBLE_ENC_ADV_DATA +#define MYNEWT_VAL_ENC_ADV_DATA (0) +#else +#define MYNEWT_VAL_ENC_ADV_DATA (CONFIG_BT_NIMBLE_ENC_ADV_DATA) #endif -#ifndef MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS -#ifdef CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV -#define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#define BLE_SCAN_RSP_DATA_MAX_LEN_N (1650) #else +/* In this case the value will be overwritten by 31 in controller. */ +#define BLE_SCAN_RSP_DATA_MAX_LEN_N (MYNEWT_VAL_BLE_EXT_ADV_MAX_SIZE) +#endif + +#ifndef CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS #define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (0) +#else +#define MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS (CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS) #endif + +#ifndef CONFIG_BT_NIMBLE_MAX_PERIODIC_ADVERTISER_LIST +#define MYNEWT_VAL_BLE_MAX_PERIODIC_ADVERTISER_LIST (0) +#else +#define MYNEWT_VAL_BLE_MAX_PERIODIC_ADVERTISER_LIST (CONFIG_BT_NIMBLE_MAX_PERIODIC_ADVERTISER_LIST) #endif -#ifndef MYNEWT_VAL_BLE_ROLE_BROADCASTER -#ifdef CONFIG_BT_NIMBLE_ROLE_BROADCASTER -#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1) +#ifndef CONFIG_BT_NIMBLE_GATT_CACHING +#define MYNEWT_VAL_BLE_GATT_CACHING (0) #else -#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (0) +#define MYNEWT_VAL_BLE_GATT_CACHING (CONFIG_BT_NIMBLE_GATT_CACHING) + +#ifdef CONFIG_BT_NIMBLE_GATT_CACHING_MAX_CONNS +#define MYNEWT_VAL_BLE_GATT_CACHING_MAX_CONNS (CONFIG_BT_NIMBLE_GATT_CACHING_MAX_CONNS) +#else +#define MYNEWT_VAL_BLE_GATT_CACHING_MAX_CONNS (0) #endif + +#ifdef CONFIG_BT_NIMBLE_GATT_CACHING_MAX_SVCS +#define MYNEWT_VAL_BLE_GATT_CACHING_MAX_SVCS (CONFIG_BT_NIMBLE_GATT_CACHING_MAX_SVCS) +#else +#define MYNEWT_VAL_BLE_GATT_CACHING_MAX_SVCS (0) #endif -#ifndef MYNEWT_VAL_BLE_ROLE_CENTRAL -#ifdef CONFIG_BT_NIMBLE_ROLE_CENTRAL -#define MYNEWT_VAL_BLE_ROLE_CENTRAL (1) +#ifdef CONFIG_BT_NIMBLE_GATT_CACHING_MAX_CHRS +#define MYNEWT_VAL_BLE_GATT_CACHING_MAX_CHRS (CONFIG_BT_NIMBLE_GATT_CACHING_MAX_CHRS) #else -#define MYNEWT_VAL_BLE_ROLE_CENTRAL (0) +#define MYNEWT_VAL_BLE_GATT_CACHING_MAX_CHRS (0) #endif + +#ifdef CONFIG_BT_NIMBLE_GATT_CACHING_MAX_DSCS +#define MYNEWT_VAL_BLE_GATT_CACHING_MAX_DSCS (CONFIG_BT_NIMBLE_GATT_CACHING_MAX_DSCS) +#else +#define MYNEWT_VAL_BLE_GATT_CACHING_MAX_DSCS (0) #endif -#ifndef MYNEWT_VAL_BLE_ROLE_OBSERVER -#ifdef CONFIG_BT_NIMBLE_ROLE_OBSERVER -#define MYNEWT_VAL_BLE_ROLE_OBSERVER (1) +#ifdef CONFIG_BT_NIMBLE_GATT_CACHING_DISABLE_AUTO +#define MYNEWT_VAL_BLE_GATT_CACHING_DISABLE_AUTO (CONFIG_BT_NIMBLE_GATT_CACHING_DISABLE_AUTO) #else -#define MYNEWT_VAL_BLE_ROLE_OBSERVER (0) +#define MYNEWT_VAL_BLE_GATT_CACHING_DISABLE_AUTO (0) +#endif + #endif + +#ifndef MYNEWT_VAL_BLE_GATT_CSFC_SIZE +#define MYNEWT_VAL_BLE_GATT_CSFC_SIZE (1) #endif -#ifndef MYNEWT_VAL_BLE_ROLE_PERIPHERAL -#ifdef CONFIG_BT_NIMBLE_ROLE_PERIPHERAL -#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (1) +#ifndef CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES +#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (1) #else -#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (0) +#define MYNEWT_VAL_BLE_MULTI_ADV_INSTANCES (CONFIG_BT_NIMBLE_MAX_EXT_ADV_INSTANCES) #endif + +#ifndef CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV +#define MYNEWT_VAL_BLE_PERIODIC_ADV (0) +#else +#define MYNEWT_VAL_BLE_PERIODIC_ADV (CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV) +#endif + +#ifndef CONFIG_NIMBLE_MAX_CONNECTIONS +#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (4) +#else +#define MYNEWT_VAL_BLE_MAX_CONNECTIONS (CONFIG_NIMBLE_MAX_CONNECTIONS) +#endif + +#ifndef CONFIG_BT_NIMBLE_ROLE_BROADCASTER +#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (0) +#else +#define MYNEWT_VAL_BLE_ROLE_BROADCASTER (CONFIG_BT_NIMBLE_ROLE_BROADCASTER) +#endif + +#ifndef CONFIG_BT_NIMBLE_ROLE_CENTRAL +#define MYNEWT_VAL_BLE_ROLE_CENTRAL (0) +#else +#define MYNEWT_VAL_BLE_ROLE_CENTRAL (CONFIG_BT_NIMBLE_ROLE_CENTRAL) +#endif + +#ifndef CONFIG_BT_NIMBLE_ROLE_OBSERVER +#define MYNEWT_VAL_BLE_ROLE_OBSERVER (0) +#else +#define MYNEWT_VAL_BLE_ROLE_OBSERVER (CONFIG_BT_NIMBLE_ROLE_OBSERVER) +#endif + +#ifndef CONFIG_BT_NIMBLE_ROLE_PERIPHERAL +#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (0) +#else +#define MYNEWT_VAL_BLE_ROLE_PERIPHERAL (CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) #endif #ifndef MYNEWT_VAL_BLE_WHITELIST #define MYNEWT_VAL_BLE_WHITELIST (1) #endif +#ifndef CONFIG_BT_NIMBLE_53_FEATURE_SUPPORT +#define BLE_53_FEATURE_SUPPORT (0) +#else +#define BLE_53_FEATURE_SUPPORT (CONFIG_BT_NIMBLE_53_FEATURE_SUPPORT) +#endif + +#ifndef CONFIG_BT_NIMBLE_SUBRATE +#define MYNEWT_VAL_BLE_CONN_SUBRATING (0) +#else +#define MYNEWT_VAL_BLE_CONN_SUBRATING (CONFIG_BT_NIMBLE_SUBRATE) +#endif +#ifndef CONFIG_BT_NIMBLE_PERIODIC_ADV_ENH +#define MYNEWT_VAL_BLE_PERIODIC_ADV_ENH (0) +#else +#define MYNEWT_VAL_BLE_PERIODIC_ADV_ENH (CONFIG_BT_NIMBLE_PERIODIC_ADV_ENH) +#endif + /*** @apache-mynewt-nimble/nimble/controller */ +/*** @apache-mynewt-nimble/nimble/controller */ +#ifndef MYNEWT_VAL_BLE_CONTROLLER +#if NIMBLE_CFG_CONTROLLER +#define MYNEWT_VAL_BLE_CONTROLLER (1) +#else +#define MYNEWT_VAL_BLE_CONTROLLER (0) +#endif +#endif + +#ifndef MYNEWT_VAL_BLE_VERSION +#define MYNEWT_VAL_BLE_VERSION (54) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_ADD_STRICT_SCHED_PERIODS +#define MYNEWT_VAL_BLE_LL_ADD_STRICT_SCHED_PERIODS (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_CONN_PARAM_REQ (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_DATA_LEN_EXT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_EXT_SCAN_FILT +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_EXT_SCAN_FILT (0) +#endif + +#ifndef CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY (0) +#else +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY (CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY) +#endif + +#ifndef CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY (0) +#else +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY (CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CSA2 +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CSA2 (1) +#endif + +#ifndef MYNEWT_VAL_BLE_PHY_DBG_TIME_ADDRESS_END_PIN +#define MYNEWT_VAL_BLE_PHY_DBG_TIME_ADDRESS_END_PIN (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_PHY_DBG_TIME_TXRXEN_READY_PIN +#define MYNEWT_VAL_BLE_PHY_DBG_TIME_TXRXEN_READY_PIN (-1) +#endif + +#ifndef MYNEWT_VAL_BLE_PHY_DBG_TIME_WFR_PIN +#define MYNEWT_VAL_BLE_PHY_DBG_TIME_WFR_PIN (-1) +#endif + + #ifndef MYNEWT_VAL_BLE_DEVICE #define MYNEWT_VAL_BLE_DEVICE (0) #endif +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG (1) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_MAX_TX_BYTES +#define MYNEWT_VAL_BLE_LL_CONN_INIT_MAX_TX_BYTES (27) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_MIN_WIN_OFFSET +#define MYNEWT_VAL_BLE_LL_CONN_INIT_MIN_WIN_OFFSET (0) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_INIT_SLOTS +#define MYNEWT_VAL_BLE_LL_CONN_INIT_SLOTS (4) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_DBG_HCI_CMD_PIN +#define MYNEWT_VAL_BLE_LL_DBG_HCI_CMD_PIN (-1) +#endif + /* Overridden by @apache-mynewt-nimble/nimble/controller (defined by @apache-mynewt-nimble/nimble/controller) */ -#ifndef MYNEWT_VAL_BLE_HW_WHITELIST_ENABLE -#define MYNEWT_VAL_BLE_HW_WHITELIST_ENABLE (0) +#ifndef CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION (0) +#else +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_ENCRYPTION (CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION) +#endif + +/* Value copied from BLE_LL_OUR_SCA */ +#ifndef MYNEWT_VAL_BLE_LL_SCA +#define MYNEWT_VAL_BLE_LL_SCA (60) #endif #ifndef MYNEWT_VAL_BLE_LL_ADD_STRICT_SCHED_PERIODS @@ -141,12 +348,34 @@ #define MYNEWT_VAL_BLE_LL_CFG_FEAT_EXT_SCAN_FILT (0) #endif -#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY -#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_2M_PHY (0) +#ifndef MYNEWT_VAL_BLE_LL_STRICT_CONN_SCHEDULING +#define MYNEWT_VAL_BLE_LL_STRICT_CONN_SCHEDULING (0) #endif -#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY -#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LE_CODED_PHY (0) +#ifndef CONFIG_BT_NIMBLE_HCI_UART_BAUD +#define MYNEWT_VAL_BLE_HCI_UART_BAUD (115200) +#else +#define MYNEWT_VAL_BLE_HCI_UART_BAUD (CONFIG_BT_NIMBLE_HCI_UART_BAUD) +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_UART_DATA_BITS +#define MYNEWT_VAL_BLE_HCI_UART_DATA_BITS (8) +#endif + +#ifndef CONFIG_UART_FLOW_CTRL +#define MYNEWT_VAL_BLE_HCI_UART_FLOW_CTRL (1) +#else +#define MYNEWT_VAL_BLE_HCI_UART_FLOW_CTRL (CONFIG_UART_FLOW_CTRL) +#endif + +#ifndef MYNEWT_VAL_BLE_HCI_UART_PARITY +#define MYNEWT_VAL_BLE_HCI_UART_PARITY (0) // HAL_UART_PARITY_NONE +#endif + +#ifndef CONFIG_BT_NIMBLE_HCI_UART_PORT +#define MYNEWT_VAL_BLE_HCI_UART_PORT (0) +#else +#define MYNEWT_VAL_BLE_HCI_UART_PORT (CONFIG_BT_NIMBLE_HCI_UART_PORT) #endif /* Overridden by @apache-mynewt-nimble/nimble/controller (defined by @apache-mynewt-nimble/nimble/controller) */ @@ -166,6 +395,29 @@ #define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_EXT_ADV (MYNEWT_VAL_BLE_EXT_ADV) #endif +/* Value copied from BLE_PERIODIC_ADV */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV (CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV) +#endif + +/* Value copied from BLE_MAX_PERIODIC_SYNCS */ +#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_CNT +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_CNT (MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS) +#endif + + +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_LIST_CNT (MYNEWT_VAL_BLE_MAX_PERIODIC_SYNCS) + +#ifndef CONFIG_BT_NIMBLE_PERIODIC_ADV_SYNC_TRANSFER +#define MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER (0) +#else +#define MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER (CONFIG_BT_NIMBLE_PERIODIC_ADV_SYNC_TRANSFER) +#endif + +/* Value copied from BLE_PERIODIC_ADV_SYNC_TRANSFER */ +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER (CONFIG_BT_NIMBLE_PERIODIC_ADV_SYNC_TRANSFER) + + #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY #define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY (1) #endif @@ -196,29 +448,13 @@ #endif #ifndef MYNEWT_VAL_BLE_LL_MASTER_SCA -#define MYNEWT_VAL_BLE_LL_MASTER_SCA (4) +#define MYNEWT_VAL_BLE_LL_MASTER_SCA (60) #endif #ifndef MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE #define MYNEWT_VAL_BLE_LL_MAX_PKT_SIZE (251) #endif -#ifndef MYNEWT_VAL_BLE_LL_MFRG_ID -#define MYNEWT_VAL_BLE_LL_MFRG_ID (0xFFFF) -#endif - -#ifndef MYNEWT_VAL_BLE_LL_NUM_SCAN_DUP_ADVS -#define MYNEWT_VAL_BLE_LL_NUM_SCAN_DUP_ADVS (8) -#endif - -#ifndef MYNEWT_VAL_BLE_LL_NUM_SCAN_RSP_ADVS -#define MYNEWT_VAL_BLE_LL_NUM_SCAN_RSP_ADVS (8) -#endif - -#ifndef MYNEWT_VAL_BLE_LL_OUR_SCA -#define MYNEWT_VAL_BLE_LL_OUR_SCA (60) -#endif - #ifndef MYNEWT_VAL_BLE_LL_PRIO #define MYNEWT_VAL_BLE_LL_PRIO (0) #endif @@ -260,7 +496,7 @@ #endif #ifndef MYNEWT_VAL_BLE_LL_WHITELIST_SIZE -#define MYNEWT_VAL_BLE_LL_WHITELIST_SIZE (8) +#define MYNEWT_VAL_BLE_LL_WHITELIST_SIZE CONFIG_BT_NIMBLE_WHITELIST_SIZE #endif #ifndef MYNEWT_VAL_BLE_LP_CLOCK @@ -272,7 +508,7 @@ #endif #ifndef MYNEWT_VAL_BLE_PUBLIC_DEV_ADDR -#define MYNEWT_VAL_BLE_PUBLIC_DEV_ADDR ((uint8_t[6]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +#define MYNEWT_VAL_BLE_PUBLIC_DEV_ADDR (((uint8_t[6]){0x01,0x21,0x03,0x66,0x05,0x30})) #endif #ifndef MYNEWT_VAL_BLE_XTAL_SETTLE_TIME @@ -280,28 +516,27 @@ #endif /*** @apache-mynewt-nimble/nimble/host */ -#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU -#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU -#endif -#ifndef MYNEWT_VAL_BLE_HS_LOG_LVL -#define MYNEWT_VAL_BLE_HS_LOG_LVL CONFIG_BT_NIMBLE_LOG_LEVEL +#ifndef MYNEWT_VAL_BLE_L2CAP_COC_SDU_BUFF_COUNT +#define MYNEWT_VAL_BLE_L2CAP_COC_SDU_BUFF_COUNT CONFIG_BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT #endif -#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV -#ifdef CONFIG_BT_NIMBLE_EXT_ADV -#define MYNEWT_VAL_BLE_PERIODIC_ADV (CONFIG_BT_NIMBLE_ENABLE_PERIODIC_ADV) +#if CONFIG_BT_NIMBLE_L2CAP_ENHANCED_COC || CONFIG_BT_NIMBLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC (1) #else -#define MYNEWT_VAL_BLE_PERIODIC_ADV (0) -#endif +#define MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC (0) #endif -#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER -#define MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER (0) +#ifndef MYNEWT_VAL_BLE_DYNAMIC_SERVICE +#ifdef CONFIG_BT_NIMBLE_DYNAMIC_SERVICE +#define MYNEWT_VAL_BLE_DYNAMIC_SERVICE CONFIG_BT_NIMBLE_DYNAMIC_SERVICE +#else +#define MYNEWT_VAL_BLE_DYNAMIC_SERVICE (0) +#endif #endif -#ifndef MYNEWT_VAL_BLE_VERSION -#define MYNEWT_VAL_BLE_VERSION (50) +#ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU +#define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU #endif #ifndef MYNEWT_VAL_BLE_ATT_SVR_FIND_INFO @@ -324,6 +559,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (1) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -348,6 +587,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_MULT_VAR +#define MYNEWT_VAL_BLE_ATT_SVR_READ_MULT_VAR (1) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE #define MYNEWT_VAL_BLE_ATT_SVR_READ_TYPE (1) #endif @@ -364,6 +607,49 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (CONFIG_BT_NIMBLE_EATT_CHAN_NUM) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + +#ifndef MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES + +#if MYNEWT_VAL_BLE_GATT_CACHING +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_ROBUST_CACHING (1) +#else +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_ROBUST_CACHING (0) +#endif //MYNEWT_VAL_BLE_GATT_CACHING + +#if CONFIG_BT_NIMBLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_EATT (2) +#else +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_EATT (0) +#endif //CONFIG_BT_NIMBLE_EATT_CHAN_NUM + +#if MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_NOTIFY_MULTI (4) +#else +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_NOTIFY_MULTI (0) +#endif //MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI + +#define MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES ( \ + MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_ROBUST_CACHING | \ + MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_EATT | \ + MYNEWT_VAL_BLE_CLIENT_SUPPORTED_FEATURES_NOTIFY_MULTI \ + ) +#endif //MYNEWT_VAL_CLIENT_SUPPORTED_FEATURES + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -397,13 +683,17 @@ #endif #ifndef MYNEWT_VAL_BLE_GATT_MAX_PROCS -#define MYNEWT_VAL_BLE_GATT_MAX_PROCS (4) +#define MYNEWT_VAL_BLE_GATT_MAX_PROCS (CONFIG_BT_NIMBLE_GATT_MAX_PROCS) #endif #ifndef MYNEWT_VAL_BLE_GATT_NOTIFY #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif @@ -457,7 +747,7 @@ #endif #ifndef MYNEWT_VAL_BLE_GATT_BLOB_TRANSFER -#define MYNEWT_VAL_BLE_GATT_BLOB_TRANSFER (0) +#define MYNEWT_VAL_BLE_GATT_BLOB_TRANSFER (CONFIG_BT_NIMBLE_BLE_GATT_BLOB_TRANSFER) #endif #ifndef MYNEWT_VAL_BLE_HOST @@ -481,30 +771,28 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS -#ifdef CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS -#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (1) -#else -#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) -#endif +#define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS #endif #ifndef MYNEWT_VAL_BLE_HS_AUTO_START #define MYNEWT_VAL_BLE_HS_AUTO_START (1) #endif -#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL #ifdef CONFIG_BT_NIMBLE_HS_FLOW_CTRL #define MYNEWT_VAL_BLE_HS_FLOW_CTRL (1) #else #define MYNEWT_VAL_BLE_HS_FLOW_CTRL (0) #endif -#endif -#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL +#ifndef CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL (2000) +#else #define MYNEWT_VAL_BLE_HS_FLOW_CTRL_ITVL CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL #endif -#ifndef MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH +#ifndef CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH +#define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH (2) +#else #define MYNEWT_VAL_BLE_HS_FLOW_CTRL_THRESH CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH #endif @@ -532,12 +820,18 @@ #define MYNEWT_VAL_BLE_HS_SYSINIT_STAGE (200) #endif -#ifndef MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM +#if CONFIG_BT_NIMBLE_EATT_CHAN_NUM > CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (CONFIG_BT_NIMBLE_EATT_CHAN_NUM) +#else +#ifndef CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM (2) +#else #define MYNEWT_VAL_BLE_L2CAP_COC_MAX_NUM CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM -#endif +#endif //CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#endif //CONFIG_BT_NIMBLE_EATT_CHAN_NUM #ifndef MYNEWT_VAL_BLE_L2CAP_COC_MPS -#define MYNEWT_VAL_BLE_L2CAP_COC_MPS (MYNEWT_VAL_MSYS_1_BLOCK_SIZE - 8) +#define MYNEWT_VAL_BLE_L2CAP_COC_MPS (MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8) #endif #ifndef MYNEWT_VAL_BLE_L2CAP_JOIN_RX_FRAGS @@ -545,14 +839,18 @@ #endif #ifndef MYNEWT_VAL_BLE_L2CAP_MAX_CHANS -#define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*MYNEWT_VAL_BLE_MAX_CONNECTIONS) +#define MYNEWT_VAL_BLE_L2CAP_MAX_CHANS (3*CONFIG_BT_NIMBLE_MAX_CONNECTIONS) #endif #ifndef MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT #define MYNEWT_VAL_BLE_L2CAP_RX_FRAG_TIMEOUT (30000) #endif -#ifndef MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS +#if CONFIG_BT_NIMBLE_EATT_CHAN_NUM > CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (CONFIG_BT_NIMBLE_EATT_CHAN_NUM) +#elif CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM) +#else #define MYNEWT_VAL_BLE_L2CAP_SIG_MAX_PROCS (1) #endif @@ -656,18 +954,35 @@ #endif #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_LVL -#define MYNEWT_VAL_BLE_SM_SC_LVL (0) + +#ifndef MYNEWT_VAL_BLE_SM_LVL +#ifdef CONFIG_BT_NIMBLE_SM_LVL +#define MYNEWT_VAL_BLE_SM_LVL CONFIG_BT_NIMBLE_SM_LVL +#else +#define MYNEWT_VAL_BLE_SM_LVL (0) +#endif #endif #ifndef MYNEWT_VAL_BLE_SM_SC_ONLY +#ifdef CONFIG_BT_NIMBLE_SM_SC_ONLY +#define MYNEWT_VAL_BLE_SM_SC_ONLY (CONFIG_BT_NIMBLE_SM_SC_ONLY) +#else #define MYNEWT_VAL_BLE_SM_SC_ONLY (0) #endif +#endif #ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST #define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) #endif +#ifndef MYNEWT_VAL_BLE_SMP_ID_RESET +#ifdef CONFIG_BT_NIMBLE_SMP_ID_RESET +#define MYNEWT_VAL_BLE_SMP_ID_RESET CONFIG_BT_NIMBLE_SMP_ID_RESET +#else +#define MYNEWT_VAL_BLE_SMP_ID_RESET (0) +#endif +#endif + #ifndef MYNEWT_VAL_BLE_CRYPTO_STACK_MBEDTLS #define MYNEWT_VAL_BLE_CRYPTO_STACK_MBEDTLS (CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS) #endif @@ -680,50 +995,41 @@ #define MYNEWT_VAL_BLE_STORE_MAX_CCCDS CONFIG_BT_NIMBLE_MAX_CCCDS #endif +#ifndef MYNEWT_VAL_BLE_STORE_MAX_CSFCS +#define MYNEWT_VAL_BLE_STORE_MAX_CSFCS (CONFIG_BT_NIMBLE_MAX_CONNECTIONS) +#endif + #ifdef CONFIG_BT_NIMBLE_MAX_EADS #define MYNEWT_VAL_BLE_STORE_MAX_EADS CONFIG_BT_NIMBLE_MAX_EADS #endif -/*** @apache-mynewt-nimble/nimble/host/mesh */ -#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG -#define MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG (1) +#ifndef MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST +#ifdef CONFIG_BT_NIMBLE_NVS_PERSIST +#define MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST (1) +#else +#define MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST (0) #endif - -#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LOG_LVL -#define MYNEWT_VAL_BLE_MESH_ACCESS_LOG_LVL (1) #endif -#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LOG_MOD -#define MYNEWT_VAL_BLE_MESH_ACCESS_LOG_MOD (10) -#endif -#ifndef MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT -#define MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT (20) +/* Value copied from BLE_TRANSPORT_ACL_COUNT */ +#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_LL_COUNT +#define MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_LL_COUNT CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT #endif -#ifndef MYNEWT_VAL_BLE_MESH_ADV_EXT -#define MYNEWT_VAL_BLE_MESH_ADV_EXT (0) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE +#define MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE CONFIG_BT_NIMBLE_TRANSPORT_ACL_SIZE #endif -#ifndef MYNEWT_VAL_BLE_MESH_ADV_LEGACY -#define MYNEWT_VAL_BLE_MESH_ADV_LEGACY (1) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_COUNT +#define MYNEWT_VAL_BLE_TRANSPORT_EVT_COUNT CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT #endif -#ifndef MYNEWT_VAL_BLE_MESH_ADV_LOG_LVL -#define MYNEWT_VAL_BLE_MESH_ADV_LOG_LVL (1) -#endif -#ifndef MYNEWT_VAL_BLE_MESH_ADV_LOG_MOD -#define MYNEWT_VAL_BLE_MESH_ADV_LOG_MOD (11) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_DISCARDABLE_COUNT +#define MYNEWT_VAL_BLE_TRANSPORT_EVT_DISCARDABLE_COUNT CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT #endif -#ifndef MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST -#ifdef CONFIG_BT_NIMBLE_NVS_PERSIST -#define MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST (1) -#else -#define MYNEWT_VAL_BLE_STORE_CONFIG_PERSIST (0) -#endif -#endif /*** nimble/host/services/ans */ #ifndef MYNEWT_VAL_BLE_SVC_ANS_NEW_ALERT_CAT @@ -737,12 +1043,26 @@ /*** nimble/host/services/bas */ #ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE -#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (1) +#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (CONFIG_BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY) #endif #ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM #define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM (0) #endif + +/*** nimble/host/services/hid */ +#ifndef MYNEWT_VAL_BLE_SVC_HID_SERVICE +#define MYNEWT_VAL_BLE_SVC_HID_SERVICE CONFIG_BT_NIMBLE_HID_SERVICE +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_HID_MAX_RPTS +#define MYNEWT_VAL_BLE_SVC_HID_MAX_RPTS CONFIG_BT_NIMBLE_SVC_HID_MAX_RPTS +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_HID_MAX_SVC_INSTANCES +#define MYNEWT_VAL_BLE_SVC_HID_MAX_SVC_INSTANCES CONFIG_BT_NIMBLE_SVC_HID_MAX_INSTANCES +#endif + #ifndef MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO #define MYNEWT_VAL_BLE_MESH_ADV_TASK_PRIO (9) #endif @@ -757,6 +1077,18 @@ #define MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT (20) #endif +#ifndef MYNEWT_VAL_BLE_MESH_ADV_EXT +#define MYNEWT_VAL_BLE_MESH_ADV_EXT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_ADV_LEGACY +#define MYNEWT_VAL_BLE_MESH_ADV_LEGACY (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT +#define MYNEWT_VAL_BLE_MESH_ADV_BUF_COUNT (20) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT #define MYNEWT_VAL_BLE_MESH_APP_KEY_COUNT (1) #endif @@ -847,22 +1179,6 @@ #define MYNEWT_VAL_BLE_MESH_DEBUG_TRANS (1) #endif -#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_CDB -#define MYNEWT_VAL_BLE_MESH_DEBUG_CDB (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_CFG -#define MYNEWT_VAL_BLE_MESH_DEBUG_CFG (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_DEBUG_USE_ID_ADDR -#define MYNEWT_VAL_BLE_MESH_DEBUG_USE_ID_ADDR (0) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_DEFAULT_TTL -#define MYNEWT_VAL_BLE_MESH_DEFAULT_TTL (7) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_DEVICE_NAME #define MYNEWT_VAL_BLE_MESH_DEVICE_NAME CONFIG_BT_NIMBLE_MESH_DEVICE_NAME #endif @@ -879,10 +1195,6 @@ #endif #endif -#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED -#define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (1) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_FRIEND_LOG_LVL #define MYNEWT_VAL_BLE_MESH_FRIEND_LOG_LVL (1) #endif @@ -919,30 +1231,18 @@ #endif #endif -#ifndef MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED -#define MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_GATT_SERVER -#define MYNEWT_VAL_BLE_MESH_GATT_SERVER (1) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_HEALTH_CLI #define MYNEWT_VAL_BLE_MESH_HEALTH_CLI (0) #endif -#ifndef MYNEWT_VAL_BLE_MESH_HEARTBEAT_LOG_LVL -#define MYNEWT_VAL_BLE_MESH_HEARTBEAT_LOG_LVL (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_HEARTBEAT_LOG_MOD -#define MYNEWT_VAL_BLE_MESH_HEARTBEAT_LOG_MOD (26) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_IVU_DIVIDER #define MYNEWT_VAL_BLE_MESH_IVU_DIVIDER (4) #endif +#ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT +#define MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT (0x800000) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST #define MYNEWT_VAL_BLE_MESH_IV_UPDATE_TEST (0) #endif @@ -959,6 +1259,10 @@ #define MYNEWT_VAL_BLE_MESH_LOG_MOD (9) #endif +#ifndef MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN +#define MYNEWT_VAL_BLE_MESH_PROXY_MSG_LEN (33) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_LOW_POWER #ifdef CONFIG_BT_NIMBLE_MESH_LOW_POWER #define MYNEWT_VAL_BLE_MESH_LOW_POWER (1) @@ -1027,10 +1331,6 @@ #define MYNEWT_VAL_BLE_MESH_LPN_SCAN_LATENCY (10) #endif -#ifndef MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR -#define MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR (0) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_MODEL_EXTENSIONS #define MYNEWT_VAL_BLE_MESH_MODEL_EXTENSIONS (0) #endif @@ -1051,35 +1351,10 @@ #define MYNEWT_VAL_BLE_MESH_MODEL_LOG_MOD (16) #endif -/* Overridden by @apache-mynewt-nimble/porting/targets/linux_blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ -#ifndef MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE -#define MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE (1) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE #define MYNEWT_VAL_BLE_MESH_MSG_CACHE_SIZE (10) #endif -#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT -#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT (2) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL -#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL (20) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE -#define MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE (4) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_NET_KEYS_LOG_LVL -#define MYNEWT_VAL_BLE_MESH_NET_KEYS_LOG_LVL (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_NET_KEYS_LOG_MOD -#define MYNEWT_VAL_BLE_MESH_NET_KEYS_LOG_MOD (23) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_NET_LOG_LVL #define MYNEWT_VAL_BLE_MESH_NET_LOG_LVL (1) #endif @@ -1157,10 +1432,6 @@ #define MYNEWT_VAL_BLE_MESH_PROV_LOG_MOD (18) #endif -#ifndef MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY -#define MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY (0) -#endif - /* Overridden by @apache-mynewt-nimble/nimble/host/mesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_PROXY #ifdef CONFIG_BT_NIMBLE_MESH_PROXY @@ -1171,7 +1442,7 @@ #endif #ifndef MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE -#define MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE (3) +#define MYNEWT_VAL_BLE_MESH_PROXY_FILTER_SIZE (1) #endif #ifndef MYNEWT_VAL_BLE_MESH_PROXY_LOG_LVL @@ -1190,9 +1461,8 @@ #endif #endif -/* Value copied from BLE_MESH_RELAY */ -#ifndef MYNEWT_VAL_BLE_MESH_RELAY_ENABLED -#define MYNEWT_VAL_BLE_MESH_RELAY_ENABLED (1) +#ifndef MYNEWT_VAL_BLE_MESH_RPL_STORE_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_RPL_STORE_TIMEOUT (5) #endif #ifndef MYNEWT_VAL_BLE_MESH_RX_SDU_MAX @@ -1207,14 +1477,11 @@ #define MYNEWT_VAL_BLE_MESH_RX_SEG_MAX (3) #endif + #ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT #define MYNEWT_VAL_BLE_MESH_RX_SEG_MSG_COUNT (2) #endif -#ifndef MYNEWT_VAL_BLE_MESH_SEG_BUFS -#define MYNEWT_VAL_BLE_MESH_SEG_BUFS (64) -#endif - #ifndef MYNEWT_VAL_BLE_MESH_SEG_RETRANSMIT_ATTEMPTS #define MYNEWT_VAL_BLE_MESH_SEG_RETRANSMIT_ATTEMPTS (4) #endif @@ -1223,7 +1490,6 @@ #define MYNEWT_VAL_BLE_MESH_SEQ_STORE_RATE (128) #endif - #ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_COUNT #define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_COUNT (4) #endif @@ -1252,6 +1518,14 @@ #define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL (20) #endif +#ifndef MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE +#define MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE (4) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE +#define MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE (1) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT #define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT (2) #endif @@ -1268,6 +1542,10 @@ #define MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED (1) #endif +#ifndef MYNEWT_VAL_BLE_MESH_GATT_SERVER +#define MYNEWT_VAL_BLE_MESH_GATT_SERVER (1) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED #define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (1) #endif @@ -1280,11 +1558,19 @@ #define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL (20) #endif +#ifndef MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY +#define MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY (0) +#endif + /* Overridden by apps/blemesh (defined by @apache-mynewt-nimble/nimble/host/mesh) */ #ifndef MYNEWT_VAL_BLE_MESH_SETTINGS #define MYNEWT_VAL_BLE_MESH_SETTINGS (0) #endif +#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG +#define MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG (1) +#endif + #ifndef MYNEWT_VAL_BLE_MESH_SETTINGS_LOG_LVL #define MYNEWT_VAL_BLE_MESH_SETTINGS_LOG_LVL (1) #endif @@ -1335,7 +1621,7 @@ #endif #ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT -#define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (1) +#define MYNEWT_VAL_BLE_MESH_TX_SEG_MSG_COUNT (4) #endif #ifndef MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT @@ -1357,7 +1643,7 @@ /*** @apache-mynewt-nimble/nimble/host/services/bas */ #ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE -#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (1) +#define MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE (CONFIG_BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY) #endif #ifndef MYNEWT_VAL_BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM @@ -1374,29 +1660,34 @@ #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_DEFAULT ("0000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION +#define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_FIRMWARE_REVISION_READ_PERM (-1) #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_DEFAULT ("0000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_HARDWARE_REVISION +#define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_HARDWARE_REVISION_READ_PERM (-1) #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_DEFAULT ("espressif") #endif -/* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME +#define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_MANUFACTURER_NAME_READ_PERM (-1) #endif @@ -1409,20 +1700,24 @@ #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_DEFAULT ("0000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_SERIAL_NUMBER +#define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_SERIAL_NUMBER_READ_PERM (-1) #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_DEFAULT ("0000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION +#define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_SOFTWARE_REVISION_READ_PERM (-1) #endif @@ -1431,62 +1726,96 @@ #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT (NULL) -#endif - -#ifndef MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_DEFAULT (NULL) +#define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_DEFAULT ("00000000") #endif /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_SYSTEM_ID +#define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_SYSTEM_ID_READ_PERM (-1) #endif +#ifndef MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_DEFAULT +#define MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_DEFAULT ("000000") +#endif + /* Value copied from BLE_SVC_DIS_DEFAULT_READ_PERM */ -#ifndef MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_READ_PERM +#if CONFIG_BT_NIMBLE_SVC_DIS_PNP_ID +#define MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_READ_PERM (0) +#else #define MYNEWT_VAL_BLE_SVC_DIS_PNP_ID_READ_PERM (-1) #endif +#ifndef MYNEWT_VAL_BLE_SVC_DIS_INCLUDED +#define MYNEWT_VAL_BLE_SVC_DIS_INCLUDED (CONFIG_BT_NIMBLE_SVC_DIS_INCLUDED) +#endif + /*** @apache-mynewt-nimble/nimble/host/services/gap */ #ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE #define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE #endif #ifndef MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM +#if CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM +#define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM ( \ + CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC | \ + CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN | \ + CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR) +#else #define MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM (-1) -#endif +#endif //CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM +#endif //MYNEWT_VAL_BLE_SVC_GAP_APPEARANCE_WRITE_PERM #ifndef MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION -#define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION (-1) +#define MYNEWT_VAL_BLE_SVC_GAP_CENTRAL_ADDRESS_RESOLUTION \ + CONFIG_BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION #endif -#ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME +#ifndef CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME "nimble" +#else #define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME #endif #ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH -#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN // According to the specification, the maximum length should be 248 #endif #ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM +#if CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM ( \ + CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_ENC | \ + CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHEN | \ + CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHOR) +#else #define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM (-1) -#endif +#endif //CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM +#endif //MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_WRITE_PERM #ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL -#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL (0) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL \ + CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL #endif #ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL -#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL (0) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL \ + CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL #endif #ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY -#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY (0) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SLAVE_LATENCY \ + CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY #endif #ifndef MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO -#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO (0) +#define MYNEWT_VAL_BLE_SVC_GAP_PPCP_SUPERVISION_TMO \ + CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO +#endif + +#ifndef MYNEWT_VAL_BLE_SVC_GAP_GATT_SECURITY_LEVEL +#define MYNEWT_VAL_BLE_SVC_GAP_GATT_SECURITY_LEVEL \ + CONFIG_BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL #endif /*** nimble/transport */ @@ -1507,34 +1836,27 @@ #define MYNEWT_VAL_BLE_HCI_TRANSPORT_SOCKET (0) #endif -/* Overridden by targets/porting-nimble (defined by nimble/transport) */ -#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_UART -#define MYNEWT_VAL_BLE_HCI_TRANSPORT_UART (1) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_SIZE +#define MYNEWT_VAL_BLE_TRANSPORT_EVT_SIZE CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE #endif -/*** nimble/transport/uart */ -#ifndef MYNEWT_VAL_BLE_ACL_BUF_COUNT -#define MYNEWT_VAL_BLE_ACL_BUF_COUNT CONFIG_BT_NIMBLE_ACL_BUF_COUNT +#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_HS_COUNT +#define MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_HS_COUNT (0) #endif -#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE -#define MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE CONFIG_BT_NIMBLE_TRANSPORT_ACL_SIZE -#endif -#ifndef MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT -#define MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT (12) +/* Overridden by targets/porting-nimble (defined by nimble/transport) */ +#ifndef MYNEWT_VAL_BLE_HCI_TRANSPORT_UART +#define MYNEWT_VAL_BLE_HCI_TRANSPORT_UART (1) #endif -#ifndef MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE -#define MYNEWT_VAL_BLE_HCI_EVT_BUF_SIZE CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE -#endif -#ifndef MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT -#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT +/*** nimble/transport/uart */ +#ifndef MYNEWT_VAL_BLE_ACL_BU24 #endif -#ifndef MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT -#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT +#ifndef MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT +#define MYNEWT_VAL_BLE_HCI_ACL_OUT_COUNT (20) #endif /* Overridden by targets/porting-nimble (defined by nimble/transport/uart) */ @@ -1563,17 +1885,6 @@ #define MYNEWT_VAL_BLE_HCI_UART_STOP_BITS (1) #endif -#ifndef CONFIG_BLE_TX_CCA_ENABLED -#define MYNEWT_VAL_BLE_TX_CCA_ENABLED (0) -#else -#define MYNEWT_VAL_BLE_TX_CCA_ENABLED (CONFIG_BLE_TX_CCA_ENABLED) -#endif - -#ifndef CONFIG_BLE_CCA_RSSI_THRESH -#define MYNEWT_VAL_BLE_CCA_RSSI_THRESH (50) -#else -#define MYNEWT_VAL_BLE_CCA_RSSI_THRESH (CONFIG_BLE_CCA_RSSI_THRESH) -#endif #ifndef MYNEWT_VAL_NEWT_FEATURE_LOGCFG #define MYNEWT_VAL_NEWT_FEATURE_LOGCFG (1) @@ -1587,135 +1898,117 @@ #endif #endif -#ifndef MYNEWT_VAL_BLE_LL_CONN_PHY_DEFAULT_PREF_MASK -#define MYNEWT_VAL_BLE_LL_CONN_PHY_DEFAULT_PREF_MASK (0x07) -#endif - -#ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_SIZE -#define MYNEWT_VAL_BLE_TRANSPORT_EVT_SIZE (70) -#endif - -/* Value copied from BLE_ROLE_BROADCASTER */ -#ifndef MYNEWT_VAL_BLE_LL_ROLE_BROADCASTER -#define MYNEWT_VAL_BLE_LL_ROLE_BROADCASTER (1) +#ifndef MYNEWT_VAL_BLE_POWER_CONTROL +#ifdef CONFIG_BT_NIMBLE_BLE_POWER_CONTROL +#define MYNEWT_VAL_BLE_POWER_CONTROL CONFIG_BT_NIMBLE_BLE_POWER_CONTROL +#else +#define MYNEWT_VAL_BLE_POWER_CONTROL (0) #endif - -/* Value copied from BLE_ROLE_CENTRAL */ -#ifndef MYNEWT_VAL_BLE_LL_ROLE_CENTRAL -#define MYNEWT_VAL_BLE_LL_ROLE_CENTRAL (1) #endif -/* Value copied from BLE_ROLE_OBSERVER */ -#ifndef MYNEWT_VAL_BLE_LL_ROLE_OBSERVER -#define MYNEWT_VAL_BLE_LL_ROLE_OBSERVER (1) +#ifndef MYNEWT_VAL_BLE_HCI_VS +#define MYNEWT_VAL_BLE_HCI_VS CONFIG_BT_NIMBLE_VS_SUPPORT +#define MYNEWT_VAL_BLE_HCI_VS_OCF_OFFSET (0) +#else +#define MYNEWT_VAL_BLE_HCI_VS (0) #endif -/* Value copied from BLE_ROLE_PERIPHERAL */ -#ifndef MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL -#define MYNEWT_VAL_BLE_LL_ROLE_PERIPHERAL (1) +#ifndef MYNEWT_VAL_OPTIMIZE_MULTI_CONN +#ifdef CONFIG_BT_NIMBLE_OPTIMIZE_MULTI_CONN +#define MYNEWT_VAL_OPTIMIZE_MULTI_CONN CONFIG_BT_NIMBLE_OPTIMIZE_MULTI_CONN +#else +#define MYNEWT_VAL_OPTIMIZE_MULTI_CONN (0) #endif - -/* Value copied from BLE_TRANSPORT_ACL_COUNT */ -#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_HS_COUNT -#define MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_HS_COUNT (10) #endif -#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE -#define MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE (251) +#ifndef MYNEWT_VAL_BLE_HIGH_DUTY_ADV_ITVL +#ifdef CONFIG_BT_NIMBLE_HIGH_DUTY_ADV_ITVL +#define MYNEWT_VAL_BLE_HIGH_DUTY_ADV_ITVL CONFIG_BT_NIMBLE_HIGH_DUTY_ADV_ITVL +#else +#define MYNEWT_VAL_BLE_HIGH_DUTY_ADV_ITVL (0) #endif - -#ifndef MYNEWT_VAL_BLE_LL_NUM_COMP_PKT_ITVL_MS -#define MYNEWT_VAL_BLE_LL_NUM_COMP_PKT_ITVL_MS (2000) #endif -/* Value copied from BLE_LL_OUR_SCA */ -#ifndef MYNEWT_VAL_BLE_LL_SCA -#define MYNEWT_VAL_BLE_LL_SCA (60) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT -#define MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT (5) +#ifndef MYNEWT_VAL_BLE_QUEUE_CONG_CHECK +#ifdef CONFIG_BT_NIMBLE_HOST_QUEUE_CONG_CHECK +#define MYNEWT_VAL_BLE_QUEUE_CONG_CHECK CONFIG_BT_NIMBLE_HOST_QUEUE_CONG_CHECK +#else +#define MYNEWT_VAL_BLE_QUEUE_CONG_CHECK (0) #endif - -#ifndef MYNEWT_VAL_BLE_MESH_CDB -#define MYNEWT_VAL_BLE_MESH_CDB (0) #endif -#ifndef MYNEWT_VAL_BLE_MESH_CDB_APP_KEY_COUNT -#define MYNEWT_VAL_BLE_MESH_CDB_APP_KEY_COUNT (1) +#ifndef MYNEWT_VAL_BLE_ENABLE_CONN_REATTEMPT +#ifdef CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT +#define MYNEWT_VAL_BLE_ENABLE_CONN_REATTEMPT CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT +#else +#define MYNEWT_VAL_BLE_ENABLE_CONN_REATTEMPT (0) #endif - -#ifndef MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT -#define MYNEWT_VAL_BLE_MESH_CDB_NODE_COUNT (8) #endif -#ifndef MYNEWT_VAL_BLE_MESH_CDB_SUBNET_COUNT -#define MYNEWT_VAL_BLE_MESH_CDB_SUBNET_COUNT (1) +#ifndef MYNEWT_VAL_BLE_AOA_AOD +#ifdef CONFIG_BT_NIMBLE_AOA_AOD +#define MYNEWT_VAL_BLE_AOA_AOD CONFIG_BT_NIMBLE_AOA_AOD +#else +#define MYNEWT_VAL_BLE_AOA_AOD (0) #endif - -#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT -#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT (2) #endif -#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL -#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL (20) +#ifndef MYNEWT_VAL_BLE_HOST_ALLOW_CONNECT_WITH_SCAN +#ifdef CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN +#define MYNEWT_VAL_BLE_HOST_ALLOW_CONNECT_WITH_SCAN CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN +#else +#define MYNEWT_VAL_BLE_HOST_ALLOW_CONNECT_WITH_SCAN (0) #endif - -#ifndef MYNEWT_VAL_BLE_MESH_BEACON_ENABLED -#define MYNEWT_VAL_BLE_MESH_BEACON_ENABLED (1) #endif -#ifndef MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS -#define MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS (3) -#endif +// #ifndef MYNEWT_VAL_BT_HCI_LOG_INCLUDED +// #ifdef CONFIG_BT_HCI_LOG_DEBUG_EN +// #define MYNEWT_VAL_BT_HCI_LOG_INCLUDED CONFIG_BT_HCI_LOG_DEBUG_EN +// #else +// #define MYNEWT_VAL_BT_HCI_LOG_INCLUDED (0) +// #endif +// #endif -#ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT -#define MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT (0x800000) +#if CONFIG_BT_CONTROLLER_DISABLED && CONFIG_BT_NIMBLE_TRANSPORT_UART +#ifndef MYNEWT_VAL_BLE_TRANSPORT_UART_PORT +#define MYNEWT_VAL_BLE_TRANSPORT_UART_PORT CONFIG_BT_NIMBLE_TRANSPORT_UART_PORT #endif -#ifndef MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT -#define MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT (500) -#endif - -#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MAX -#define MYNEWT_VAL_BLE_MESH_RX_SEG_MAX (3) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_UART_PARITY__none +#define MYNEWT_VAL_BLE_TRANSPORT_UART_PARITY__none CONFIG_BT_NIMBLE_TRANSPORT_UART_PARITY_NONE #endif -#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST -#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST (400) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_UART_PARITY__odd +#define MYNEWT_VAL_BLE_TRANSPORT_UART_PARITY__odd CONFIG_BT_NIMBLE_TRANSPORT_UART_PARITY_ODD #endif -#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP -#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP (50) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_UART_PARITY__even +#define MYNEWT_VAL_BLE_TRANSPORT_UART_PARITY__even CONFIG_BT_NIMBLE_TRANSPORT_UART_PARITY_EVEN #endif -/* Value copied from BLE_TRANSPORT_ACL_COUNT */ -#ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_LL_COUNT -#define MYNEWT_VAL_BLE_TRANSPORT_ACL_FROM_LL_COUNT (10) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_UART_FLOW_CONTROL__rtscts +#define MYNEWT_VAL_BLE_TRANSPORT_UART_FLOW_CONTROL__rtscts CONFIG_BT_NIMBLE_HCI_UART_FLOW_CTRL #endif -#ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_COUNT -#define MYNEWT_VAL_BLE_TRANSPORT_EVT_COUNT (4) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_UART_BAUDRATE +#define MYNEWT_VAL_BLE_TRANSPORT_UART_BAUDRATE CONFIG_BT_NIMBLE_HCI_UART_BAUDRATE #endif -#ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_DISCARDABLE_COUNT -#define MYNEWT_VAL_BLE_TRANSPORT_EVT_DISCARDABLE_COUNT (16) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_UART_DATA_BITS +#define MYNEWT_VAL_BLE_TRANSPORT_UART_DATA_BITS (3) #endif -#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__native -#define MYNEWT_VAL_BLE_TRANSPORT_LL__native (0) +#ifndef MYNEWT_VAL_BLE_TRANSPORT_UART_STOP_BITS +#define MYNEWT_VAL_BLE_TRANSPORT_UART_STOP_BITS (1) #endif - -#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL -#define MYNEWT_VAL_BLE_TRANSPORT_LL (1) #endif -#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__native -#define MYNEWT_VAL_BLE_TRANSPORT_HS__native (1) +#ifndef MYNEWT_VAL_BLE_PERIODIC_ADV_WITH_RESPONSES +#ifdef CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES +#define MYNEWT_VAL_BLE_PERIODIC_ADV_WITH_RESPONSES (CONFIG_BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES) +#else +#define MYNEWT_VAL_BLE_PERIODIC_ADV_WITH_RESPONSES (0) #endif - -#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS -#define MYNEWT_VAL_BLE_TRANSPORT_HS (1) #endif #endif diff --git a/src/nimble/esp_port/port/include/esp_nimble_mem.h b/src/nimble/esp_port/port/include/esp_nimble_mem.h index 1bd4be7b..f8fdbfef 100644 --- a/src/nimble/esp_port/port/include/esp_nimble_mem.h +++ b/src/nimble/esp_port/port/include/esp_nimble_mem.h @@ -13,14 +13,20 @@ extern "C" { #endif +#if 0 //ESP_IDF_VERSION_MAJOR >= 5 +// #pragma message "This file should be replaced with bt_osi_mem.h, used here for compatibility" + +#include "bt_osi_mem.h" +#define nimble_platform_mem_malloc bt_osi_mem_malloc +#define nimble_platform_mem_calloc bt_osi_mem_calloc +#define nimble_platform_mem_free bt_osi_mem_free + +#else + void *nimble_platform_mem_malloc(size_t size); void *nimble_platform_mem_calloc(size_t n, size_t size); void nimble_platform_mem_free(void *ptr); -#ifndef ESP_PLATFORM -#define nimble_platform_mem_malloc malloc -#define nimble_platform_mem_calloc calloc -#define nimble_platform_mem_free free #endif #ifdef __cplusplus diff --git a/src/nimble/esp_port/port/src/esp_nimble_mem.c b/src/nimble/esp_port/port/src/esp_nimble_mem.c deleted file mode 100644 index 7e1899db..00000000 --- a/src/nimble/esp_port/port/src/esp_nimble_mem.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifdef ESP_PLATFORM - -#include "esp_attr.h" -#include "esp_heap_caps.h" -#include "nimconfig.h" -#include "../include/esp_nimble_mem.h" - -IRAM_ATTR void *nimble_platform_mem_malloc(size_t size) -{ -#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL - return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL - return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); -#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT - return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#else - return malloc(size); -#endif -} - -IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size) -{ -#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL - return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL - return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); -#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT - return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); -#else - return calloc(n, size); -#endif -} - -IRAM_ATTR void nimble_platform_mem_free(void *ptr) -{ - heap_caps_free(ptr); -} -#endif diff --git a/src/nimble/esp_port/port/src/exp_nimble_mem.c b/src/nimble/esp_port/port/src/exp_nimble_mem.c new file mode 100644 index 00000000..384f8aca --- /dev/null +++ b/src/nimble/esp_port/port/src/exp_nimble_mem.c @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #ifdef ESP_PLATFORM + + #include "esp_attr.h" + #include "esp_heap_caps.h" + #include "nimconfig.h" + #include "../include/esp_nimble_mem.h" + + IRAM_ATTR void *nimble_platform_mem_malloc(size_t size) + { + #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL + return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL + return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); + #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT + return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + #else + return malloc(size); + #endif + } + + IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size) + { + #ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL + return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL + return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); + #elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT + return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + #else + return calloc(n, size); + #endif + } + + IRAM_ATTR void nimble_platform_mem_free(void *ptr) + { + heap_caps_free(ptr); + } + #endif diff --git a/src/nimble/esp_port/port/transport/include/esp_hci_driver.h b/src/nimble/esp_port/port/transport/include/esp_hci_driver.h new file mode 100644 index 00000000..09102edf --- /dev/null +++ b/src/nimble/esp_port/port/transport/include/esp_hci_driver.h @@ -0,0 +1,52 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef H_ESP_HCI_DRIVER_ +#define H_ESP_HCI_DRIVER_ +#include + +/** + * @brief Enumeration of HCI transport direction. + */ +typedef enum { + HCI_DRIVER_DIR_C2H = 0x00, ///< From controller to host. + HCI_DRIVER_DIR_H2C, ///< From host to controller. +} hci_driver_direction_t; + +typedef enum { + HCI_DRIVER_TYPE_CMD = 0x01, ///< HCI Command Indicator. + HCI_DRIVER_TYPE_ACL, ///< HCI ACL Data Indicator. + HCI_DRIVER_TYPE_SYNC, ///< HCI Synchronous Data Indicator. + HCI_DRIVER_TYPE_EVT, ///< HCI Event Indicator. + HCI_DRIVER_TYPE_ISO, ///< HCI Isochronous Data Indicator. + HCI_DRIVER_TYPE_VENDOR, ///< HCI Vendor data Indicator. +} hci_driver_data_type_t; + +typedef int hci_driver_forward_fn(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir); + +/** + * @brief Structure of HCI driver operations. + */ +typedef struct hci_driver_ops { + int (*hci_driver_tx)(hci_driver_data_type_t data_type, uint8_t *data, uint32_t length, + hci_driver_direction_t dir); + int (*hci_driver_init)(hci_driver_forward_fn *cb); + void (*hci_driver_deinit)(void); +} hci_driver_ops_t; + + +#if CONFIG_BT_LE_HCI_INTERFACE_USE_RAM +extern hci_driver_ops_t hci_driver_vhci_ops; +#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_RAM + +#if CONFIG_BT_LE_HCI_INTERFACE_USE_UART +extern hci_driver_ops_t hci_driver_uart_ops; +#if CONFIG_BT_LE_UART_HCI_DMA_MODE +extern hci_driver_ops_t hci_driver_uart_dma_ops; +#endif // CONFIG_BT_LE_UART_HCI_DMA_MODE +#endif // CONFIG_BT_LE_HCI_INTERFACE_USE_UART + +#endif // H_ESP_HCI_DRIVER_ diff --git a/src/nimble/esp_port/port/transport/include/esp_hci_internal.h b/src/nimble/esp_port/port/transport/include/esp_hci_internal.h new file mode 100644 index 00000000..2463f636 --- /dev/null +++ b/src/nimble/esp_port/port/transport/include/esp_hci_internal.h @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_ESP_HCI_INTERNAL_ +#define H_ESP_HCI_INTERNAL_ + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "nimble/porting/nimble/include/os/os_mbuf.h" + + +/* The leadingspace in user info header for ACL data */ +#define ESP_HCI_INTERNAL_ACL_MBUF_LEADINGSPCAE (4) + +#define ESP_HCI_INTERNAL_BUF_CMD (3) + +/** + * @brief Define the HCI hardware error code for synchronization loss. + * This error code is used to indicate a loss of synchronization between the controller and the host. + */ +#define ESP_HCI_SYNC_LOSS_ERR (0x1) +/** Callback function types; executed when HCI packets are received. */ +typedef int esp_hci_internal_rx_cmd_fn(uint8_t *cmd, void *arg); +typedef int esp_hci_internal_rx_acl_fn(struct os_mbuf *om, void *arg); + +/** + * Configures the HCI transport to operate with a host. The transport will + * execute specified callbacks upon receiving HCI packets from the controller. + * + * @param evt_cb The callback to execute upon receiving an HCI + * event. + * @param evt_arg Optional argument to pass to the event + * callback. + * @param acl_cb The callback to execute upon receiving ACL + * data. + * @param acl_arg Optional argument to pass to the ACL + * callback. + */ +void r_ble_hci_trans_cfg_hs(esp_hci_internal_rx_cmd_fn *evt_cb, void *evt_arg, + esp_hci_internal_rx_acl_fn *acl_cb, void *acl_arg); +/** + * Sends ACL data from host to controller. + * + * @param om The ACL data packet to send. + * + * @return 0 on success; + * A BLE_ERR_[...] error code on failure. + */ +int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om); + +/** + * Sends an HCI command from the host to the controller. + * + * @param cmd The HCI command to send. This buffer must be + * allocated via ble_hci_trans_buf_alloc(). + * + * @return 0 on success; + * A BLE_ERR_[...] error code on failure. + */ +int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd); + +/** + * Allocates a flat buffer of the specified type. + * + * @param type The type of buffer to allocate; one of the + * BLE_HCI_TRANS_BUF_[...] constants. + * + * @return The allocated buffer on success; + * NULL on buffer exhaustion. + */ +uint8_t * r_ble_hci_trans_buf_alloc(int type); + +/** + * Frees the specified flat buffer. The buffer must have been allocated via + * ble_hci_trans_buf_alloc(). + * + * @param buf The buffer to free. + */ +void r_ble_hci_trans_buf_free(uint8_t *buf); + +/** + * Configures a callback to get executed whenever an ACL data packet is freed. + * The function is called immediately before the free occurs. + * + * @param cb The callback to configure. + * @param arg An optional argument to pass to the callback. + * + * @return 0 on success; + * BLE_ERR_UNSUPPORTED if the transport does not + * support this operation. + */ +int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg); + +/** + * @brief Handle an HCI hardware error event. + * This function processes a hardware error code and generates the appropriate HCI hardware error event. + * + * @param hw_err The hardware error code that needs to be processed. The specific meaning of the error code + * depends on the implementation and the hardware. + * + * @return int Returns 0 on success, or a non-zero error code on failure. + * + * @note This function should be called whenever a hardware error is detected in the HCI Layer. + */ +int r_ble_ll_hci_ev_hw_err(uint8_t hw_err); + +//!TODO: Check what this API is used for +int r_ble_hci_trans_reset(void); + +//!TODO: Should we initialize the hci layer in IDF ? +void esp_ble_hci_trans_init(uint8_t); + +#ifdef __cplusplus +} +#endif +#endif /* H_ESP_HCI_INTERNAL_ */ diff --git a/src/nimble/esp_port/port/transport/include/esp_hci_transport.h b/src/nimble/esp_port/port/transport/include/esp_hci_transport.h new file mode 100644 index 00000000..8cc748fc --- /dev/null +++ b/src/nimble/esp_port/port/transport/include/esp_hci_transport.h @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_ESP_HCI_TRANSPORT_ +#define H_ESP_HCI_TRANSPORT_ + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "esp_hci_driver.h" + +/** + * @brief Enumeration of HCI packet indicators + */ +typedef enum { + HCI_CMD_IND = 0x01, /*!< HCI Command Indicator */ + HCI_ACL_IND, /*!< HCI ACL Data Indicator */ + HCI_SYNC_IND, /*!< HCI Synchronous Data Indicator */ + HCI_EVT_IND, /*!< HCI Event Indicator */ + HCI_ISO_IND, /*!< HCI Isochronous Data Indicator */ + HCI_VENDOR_IND, /*!< HCI Vendor data Indicator */ +} hci_trans_pkt_ind_t; + +/** + * @brief Enumeration of HCI Transport Mode + */ +typedef enum { + HCI_TRANSPORT_VHCI, /*!< VHCI Transport Mode */ + HCI_TRANSPORT_UART_NO_DMA, /*!< UART_NO_DMA Transport Mode */ + HCI_TRANSPORT_UART_UHCI, /*!< UART_UHCI Transport Mode */ + HCI_TRANSPORT_SDIO, /*!< SDIO Transport Mode */ + HCI_TRANSPORT_USB, /*!< USB Transport Mode */ +} hci_trans_mode_t; + +typedef int hci_transport_host_recv_fn(hci_trans_pkt_ind_t type, uint8_t *data, uint16_t len); + +/** + * @brief Initialize the HCI transport layer. + * It should be called before using any other functions in the transport layer. + * + * @param hci_transport_mode The mode in which the HCI transport should operate. + * + * @return int Returns 0 on success, or a non-zero error code on failure. + */ +int hci_transport_init(uint8_t hci_transport_mode); + +/** + * @brief Deinitialize the HCI transport layer for releasing any allocated resources. + */ +void hci_transport_deinit(void); + +/** + * @brief Set the host's HCI callback which will be invoked when receiving ACL/Events from controller. + * @param callback hci_transport_host_recv_fn type variable + * @return int 0 on success, non-zero error code on failure. + */ +int hci_transport_host_callback_register(hci_transport_host_recv_fn *callback); + +/** + * @brief Called to send HCI commands form host to controller. + * @param data Point to the commands data + * @param length Length of data + * @return int 0 on success, non-zero error code on failure. + */ +int hci_transport_host_cmd_tx(uint8_t *data, uint32_t length); + +/** + * @brief Called to send HCI ACL form host to controller. + * @param data Point to the ACL data + * @param length Length of data + * @return int 0 on success, non-zero error code on failure. + */ +int hci_transport_host_acl_tx(uint8_t *data, uint32_t length); + +#ifdef __cplusplus +} +#endif +#endif /* H_ESP_HCI_TRANSPORT_ */ diff --git a/src/nimble/ext/tinycrypt/documentation/tinycrypt.rst b/src/nimble/ext/tinycrypt/documentation/tinycrypt.rst deleted file mode 100644 index 356c099a..00000000 --- a/src/nimble/ext/tinycrypt/documentation/tinycrypt.rst +++ /dev/null @@ -1,352 +0,0 @@ - -TinyCrypt Cryptographic Library -############################### -Copyright (C) 2017 by Intel Corporation, All Rights Reserved. - -Overview -******** -The TinyCrypt Library provides an implementation for targeting constrained devices -with a minimal set of standard cryptography primitives, as listed below. To better -serve applications targeting constrained devices, TinyCrypt implementations differ -from the standard specifications (see the Important Remarks section for some -important differences). Certain cryptographic primitives depend on other -primitives, as mentioned in the list below. - -Aside from the Important Remarks section below, valuable information on the usage, -security and technicalities of each cryptographic primitive are found in the -corresponding header file. - -* SHA-256: - - * Type of primitive: Hash function. - * Standard Specification: NIST FIPS PUB 180-4. - * Requires: -- - -* HMAC-SHA256: - - * Type of primitive: Message authentication code. - * Standard Specification: RFC 2104. - * Requires: SHA-256 - -* HMAC-PRNG: - - * Type of primitive: Pseudo-random number generator (256-bit strength). - * Standard Specification: NIST SP 800-90A. - * Requires: SHA-256 and HMAC-SHA256. - -* AES-128: - - * Type of primitive: Block cipher. - * Standard Specification: NIST FIPS PUB 197. - * Requires: -- - -* AES-CBC mode: - - * Type of primitive: Encryption mode of operation. - * Standard Specification: NIST SP 800-38A. - * Requires: AES-128. - -* AES-CTR mode: - - * Type of primitive: Encryption mode of operation. - * Standard Specification: NIST SP 800-38A. - * Requires: AES-128. - -* AES-CMAC mode: - - * Type of primitive: Message authentication code. - * Standard Specification: NIST SP 800-38B. - * Requires: AES-128. - -* AES-CCM mode: - - * Type of primitive: Authenticated encryption. - * Standard Specification: NIST SP 800-38C. - * Requires: AES-128. - -* CTR-PRNG: - - * Type of primitive: Pseudo-random number generator (128-bit strength). - * Standard Specification: NIST SP 800-90A. - * Requires: AES-128. - -* ECC-DH: - - * Type of primitive: Key exchange based on curve NIST p-256. - * Standard Specification: RFC 6090. - * Requires: ECC auxiliary functions (ecc.h/c). - -* ECC-DSA: - - * Type of primitive: Digital signature based on curve NIST p-256. - * Standard Specification: RFC 6090. - * Requires: ECC auxiliary functions (ecc.h/c). - -Design Goals -************ - -* Minimize the code size of each cryptographic primitive. This means minimize - the size of a platform-independent implementation, as presented in TinyCrypt. - Note that various applications may require further features, optimizations with - respect to other metrics and countermeasures for particular threats. These - peculiarities would increase the code size and thus are not considered here. - -* Minimize the dependencies among the cryptographic primitives. This means - that it is unnecessary to build and allocate object code for more primitives - than the ones strictly required by the intended application. In other words, - one can select and compile only the primitives required by the application. - - -Important Remarks -***************** - -The cryptographic implementations in TinyCrypt library have some limitations. -Some of these limitations are inherent to the cryptographic primitives -themselves, while others are specific to TinyCrypt. These limitations were accepted -in order to meet its design goals (in special, minimal code size) and to better -serve applications targeting constrained devices in general. Some of these -limitations are discussed in-depth below. - -General Remarks -*************** - -* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the - variety of side-channel attacks, many of them only relevant to certain - platforms. In this sense, instead of penalizing all library users with - side-channel countermeasures such as increasing the overall code size, - TinyCrypt only implements certain generic timing-attack countermeasures. - -Specific Remarks -**************** - -* SHA-256: - - * The number of bits_hashed in the state is not checked for overflow. Note - however that this will only be a problem if you intend to hash more than - 2^64 bits, which is an extremely large window. - -* HMAC: - - * The HMAC verification process is assumed to be performed by the application. - This compares the computed tag with some given tag. - Note that conventional memory-comparison methods (such as memcmp function) - might be vulnerable to timing attacks; thus be sure to use a constant-time - memory comparison function (such as compare_constant_time - function provided in lib/utils.c). - - * The tc_hmac_final function, responsible for computing the message tag, - cleans the state context before exiting. Thus, applications do not need to - clean the TCHmacState_t ctx after calling tc_hmac_final. This should not - be changed in future versions of the library as there are applications - currently relying on this good-practice/feature of TinyCrypt. - -* HMAC-PRNG: - - * Before using HMAC-PRNG, you *must* find an entropy source to produce a seed. - PRNGs only stretch the seed into a seemingly random output of arbitrary - length. The security of the output is exactly equal to the - unpredictability of the seed. - - * NIST SP 800-90A requires three items as seed material in the initialization - step: entropy seed, personalization and a nonce (which is not implemented). - TinyCrypt requires the personalization byte array and automatically creates - the entropy seed using a mandatory call to the re-seed function. - -* AES-128: - - * The current implementation does not support other key-lengths (such as 256 - bits). Note that if you need AES-256, it doesn't sound as though your - application is running in a constrained environment. AES-256 requires keys - twice the size as for AES-128, and the key schedule is 40% larger. - -* CTR mode: - - * The AES-CTR mode limits the size of a data message they encrypt to 2^32 - blocks. If you need to encrypt larger data sets, your application would - need to replace the key after 2^32 block encryptions. - -* CTR-PRNG: - - * Before using CTR-PRNG, you *must* find an entropy source to produce a seed. - PRNGs only stretch the seed into a seemingly random output of arbitrary - length. The security of the output is exactly equal to the - unpredictability of the seed. - -* CBC mode: - - * TinyCrypt CBC decryption assumes that the iv and the ciphertext are - contiguous (as produced by TinyCrypt CBC encryption). This allows for a - very efficient decryption algorithm that would not otherwise be possible. - -* CMAC mode: - - * AES128-CMAC mode of operation offers 64 bits of security against collision - attacks. Note however that an external attacker cannot generate the tags - him/herself without knowing the MAC key. In this sense, to attack the - collision property of AES128-CMAC, an external attacker would need the - cooperation of the legal user to produce an exponentially high number of - tags (e.g. 2^64) to finally be able to look for collisions and benefit - from them. As an extra precaution, the current implementation allows to at - most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup - (allowing a new key to be set), as suggested in Appendix B of SP 800-38B. - -* CCM mode: - - * There are a few tradeoffs for the selection of the parameters of CCM mode. - In special, there is a tradeoff between the maximum number of invocations - of CCM under a given key and the maximum payload length for those - invocations. Both things are related to the parameter 'q' of CCM mode. The - maximum number of invocations of CCM under a given key is determined by - the nonce size, which is: 15-q bytes. The maximum payload length for those - invocations is defined as 2^(8q) bytes. - - To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2, - which is a quite reasonable choice for constrained applications. The - implications of this choice are: - - The nonce size is: 13 bytes. - - The maximum payload length is: 2^16 bytes = 65 KB. - - The mac size parameter is an important parameter to estimate the security - against collision attacks (that aim at finding different messages that - produce the same authentication tag). TinyCrypt CCM implementation - accepts any even integer between 4 and 16, as suggested in SP 800-38C. - - * TinyCrypt CCM implementation accepts associated data of any length between - 0 and (2^16 - 2^8) = 65280 bytes. - - * TinyCrypt CCM implementation accepts: - - * Both non-empty payload and associated data (it encrypts and - authenticates the payload and only authenticates the associated data); - - * Non-empty payload and empty associated data (it encrypts and - authenticates the payload); - - * Non-empty associated data and empty payload (it degenerates to an - authentication-only mode on the associated data). - - * RFC-3610, which also specifies CCM, presents a few relevant security - suggestions, such as: it is recommended for most applications to use a - mac size greater than 8. Besides, it is emphasized that the usage of the - same nonce for two different messages which are encrypted with the same - key obviously destroys the security properties of CCM mode. - -* ECC-DH and ECC-DSA: - - * TinyCrypt ECC implementation is based on micro-ecc (see - https://github.com/kmackay/micro-ecc). In the original micro-ecc - documentation, there is an important remark about the way integers are - represented: - - "Integer representation: To reduce code size, all large integers are - represented using little-endian words - so the least significant word is - first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()' - functions to convert between the native integer representation and the - standardized octet representation." - - Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32}, - {95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli) - consisting of 4 unsigned integers (as an example). - - * A cryptographically-secure PRNG function must be set (using uECC_set_rng()) - before calling uECC_make_key() or uECC_sign(). - -Examples of Applications -************************ -It is possible to do useful cryptography with only the given small set of -primitives. With this list of primitives it becomes feasible to support a range -of cryptography usages: - - * Measurement of code, data structures, and other digital artifacts (SHA256); - - * Generate commitments (SHA256); - - * Construct keys (HMAC-SHA256); - - * Extract entropy from strings containing some randomness (HMAC-SHA256); - - * Construct random mappings (HMAC-SHA256); - - * Construct nonces and challenges (HMAC-PRNG, CTR-PRNG); - - * Authenticate using a shared secret (HMAC-SHA256); - - * Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG); - - * Authenticated encryption (AES-128 + AES-CCM); - - * Key-exchange (EC-DH); - - * Digital signature (EC-DSA); - -Test Vectors -************ - -The library provides a test program for each cryptographic primitive (see 'test' -folder). Besides illustrating how to use the primitives, these tests evaluate -the correctness of the implementations by checking the results against -well-known publicly validated test vectors. - -For the case of the HMAC-PRNG, due to the necessity of performing an extensive -battery test to produce meaningful conclusions, we suggest the user to evaluate -the unpredictability of the implementation by using the NIST Statistical Test -Suite (see References). - -For the case of the EC-DH and EC-DSA implementations, most of the test vectors -were obtained from the site of the NIST Cryptographic Algorithm Validation -Program (CAVP), see References. - -References -********** - -* `NIST FIPS PUB 180-4 (SHA-256)`_ - -.. _NIST FIPS PUB 180-4 (SHA-256): - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - -* `NIST FIPS PUB 197 (AES-128)`_ - -.. _NIST FIPS PUB 197 (AES-128): - http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - -* `NIST SP800-90A (HMAC-PRNG)`_ - -.. _NIST SP800-90A (HMAC-PRNG): - http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf - -* `NIST SP 800-38A (AES-CBC and AES-CTR)`_ - -.. _NIST SP 800-38A (AES-CBC and AES-CTR): - http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - -* `NIST SP 800-38B (AES-CMAC)`_ - -.. _NIST SP 800-38B (AES-CMAC): - http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf - -* `NIST SP 800-38C (AES-CCM)`_ - -.. _NIST SP 800-38C (AES-CCM): - http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf - -* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_ - -.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG): - http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html - -* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_ - -.. _NIST Cryptographic Algorithm Validation Program (CAVP) site: - http://csrc.nist.gov/groups/STM/cavp/ - -* `RFC 2104 (HMAC-SHA256)`_ - -.. _RFC 2104 (HMAC-SHA256): - https://www.ietf.org/rfc/rfc2104.txt - -* `RFC 6090 (ECC-DH and ECC-DSA)`_ - -.. _RFC 6090 (ECC-DH and ECC-DSA): - https://www.ietf.org/rfc/rfc6090.txt diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h b/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h index a53318ee..d857505c 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/cbc_mode.h @@ -74,7 +74,7 @@ #ifndef __TC_CBC_MODE_H__ #define __TC_CBC_MODE_H__ -#include "aes.h" +#include #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h b/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h index c22ac08d..31a85b09 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h @@ -74,7 +74,7 @@ #ifndef __TC_CCM_MODE_H__ #define __TC_CCM_MODE_H__ -#include "aes.h" +#include #include #ifdef __cplusplus diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h b/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h index 32709702..9a943cad 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h @@ -97,7 +97,7 @@ #ifndef __TC_CMAC_MODE_H__ #define __TC_CMAC_MODE_H__ -#include "aes.h" +#include #include diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h b/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h index e2da5b43..68cc8567 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_mode.h @@ -67,8 +67,8 @@ #ifndef __TC_CTR_MODE_H__ #define __TC_CTR_MODE_H__ -#include "aes.h" -#include "constants.h" +#include +#include #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h b/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h index bff7f972..b809ac86 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/ctr_prng.h @@ -59,7 +59,7 @@ #ifndef __TC_CTR_PRNG_H__ #define __TC_CTR_PRNG_H__ -#include "aes.h" +#include #define TC_CTR_PRNG_RESEED_REQ -1 diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h b/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h index 930e9162..f1f9efb9 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h @@ -69,7 +69,7 @@ #ifndef __TC_ECC_DH_H__ #define __TC_ECC_DH_H__ -#include "ecc.h" +#include #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h b/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h index 8cb421b7..1bb209e1 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/ecc_dsa.h @@ -78,7 +78,7 @@ #ifndef __TC_ECC_DSA_H__ #define __TC_ECC_DSA_H__ -#include "ecc.h" +#include #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h b/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h index cfa7d38c..9a796bd3 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/hmac.h @@ -63,7 +63,7 @@ #ifndef __TC_HMAC_H__ #define __TC_HMAC_H__ -#include "sha256.h" +#include #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h b/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h index 24f417e6..976816dd 100644 --- a/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h +++ b/src/nimble/ext/tinycrypt/include/tinycrypt/hmac_prng.h @@ -68,8 +68,8 @@ #ifndef __TC_HMAC_PRNG_H__ #define __TC_HMAC_PRNG_H__ -#include "sha256.h" -#include "hmac.h" +#include +#include #ifdef __cplusplus extern "C" { diff --git a/src/nimble/ext/tinycrypt/src/aes_decrypt.c b/src/nimble/ext/tinycrypt/src/aes_decrypt.c index 0bab6e28..2944af9d 100644 --- a/src/nimble/ext/tinycrypt/src/aes_decrypt.c +++ b/src/nimble/ext/tinycrypt/src/aes_decrypt.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/aes.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include static const uint8_t inv_sbox[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, diff --git a/src/nimble/ext/tinycrypt/src/aes_encrypt.c b/src/nimble/ext/tinycrypt/src/aes_encrypt.c index bdc434bc..877c4354 100644 --- a/src/nimble/ext/tinycrypt/src/aes_encrypt.c +++ b/src/nimble/ext/tinycrypt/src/aes_encrypt.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/aes.h" -#include "../include/tinycrypt/utils.h" -#include "../include/tinycrypt/constants.h" +#include +#include +#include static const uint8_t sbox[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, diff --git a/src/nimble/ext/tinycrypt/src/cbc_mode.c b/src/nimble/ext/tinycrypt/src/cbc_mode.c index b743878a..5264eb48 100644 --- a/src/nimble/ext/tinycrypt/src/cbc_mode.c +++ b/src/nimble/ext/tinycrypt/src/cbc_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/cbc_mode.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in, unsigned int inlen, const uint8_t *iv, diff --git a/src/nimble/ext/tinycrypt/src/ccm_mode.c b/src/nimble/ext/tinycrypt/src/ccm_mode.c index 59853125..d291a839 100644 --- a/src/nimble/ext/tinycrypt/src/ccm_mode.c +++ b/src/nimble/ext/tinycrypt/src/ccm_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/ccm_mode.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include #include diff --git a/src/nimble/ext/tinycrypt/src/cmac_mode.c b/src/nimble/ext/tinycrypt/src/cmac_mode.c index dff28cf0..603de204 100644 --- a/src/nimble/ext/tinycrypt/src/cmac_mode.c +++ b/src/nimble/ext/tinycrypt/src/cmac_mode.c @@ -30,13 +30,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/aes.h" -#include "../include/tinycrypt/cmac_mode.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include +#include /* max number of calls until change the key (2^48).*/ -const static uint64_t MAX_CALLS = ((uint64_t)1 << 48); +static const uint64_t MAX_CALLS = ((uint64_t)1 << 48); /* * gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte diff --git a/src/nimble/ext/tinycrypt/src/ctr_mode.c b/src/nimble/ext/tinycrypt/src/ctr_mode.c index 6653afc5..2b5f45c8 100644 --- a/src/nimble/ext/tinycrypt/src/ctr_mode.c +++ b/src/nimble/ext/tinycrypt/src/ctr_mode.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/ctr_mode.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in, unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched) diff --git a/src/nimble/ext/tinycrypt/src/ctr_prng.c b/src/nimble/ext/tinycrypt/src/ctr_prng.c index f908932e..da90b830 100644 --- a/src/nimble/ext/tinycrypt/src/ctr_prng.c +++ b/src/nimble/ext/tinycrypt/src/ctr_prng.c @@ -27,9 +27,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/ctr_prng.h" -#include "../include/tinycrypt/utils.h" -#include "../include/tinycrypt/constants.h" +#include +#include +#include #include /* diff --git a/src/nimble/ext/tinycrypt/src/ecc.c b/src/nimble/ext/tinycrypt/src/ecc.c index e7fce278..81f0fd88 100644 --- a/src/nimble/ext/tinycrypt/src/ecc.c +++ b/src/nimble/ext/tinycrypt/src/ecc.c @@ -52,8 +52,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/ecc.h" -#include "../include/tinycrypt/ecc_platform_specific.h" +#include +#include #include /* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform diff --git a/src/nimble/ext/tinycrypt/src/ecc_dh.c b/src/nimble/ext/tinycrypt/src/ecc_dh.c index 5cd6a2e2..c33f8a61 100644 --- a/src/nimble/ext/tinycrypt/src/ecc_dh.c +++ b/src/nimble/ext/tinycrypt/src/ecc_dh.c @@ -54,9 +54,9 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/ecc.h" -#include "../include/tinycrypt/ecc_dh.h" +#include +#include +#include #include #if default_RNG_defined diff --git a/src/nimble/ext/tinycrypt/src/ecc_dsa.c b/src/nimble/ext/tinycrypt/src/ecc_dsa.c index 31046c86..7068363b 100644 --- a/src/nimble/ext/tinycrypt/src/ecc_dsa.c +++ b/src/nimble/ext/tinycrypt/src/ecc_dsa.c @@ -53,9 +53,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/ecc.h" -#include "../include/tinycrypt/ecc_dsa.h" +#include +#include +#include #if default_RNG_defined static uECC_RNG_Function g_rng_function = &default_CSPRNG; diff --git a/src/nimble/ext/tinycrypt/src/hmac.c b/src/nimble/ext/tinycrypt/src/hmac.c index c86fd35a..f9ef8d64 100644 --- a/src/nimble/ext/tinycrypt/src/hmac.c +++ b/src/nimble/ext/tinycrypt/src/hmac.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/hmac.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size) { diff --git a/src/nimble/ext/tinycrypt/src/hmac_prng.c b/src/nimble/ext/tinycrypt/src/hmac_prng.c index a41ea43d..fd14f70e 100644 --- a/src/nimble/ext/tinycrypt/src/hmac_prng.c +++ b/src/nimble/ext/tinycrypt/src/hmac_prng.c @@ -30,10 +30,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/hmac_prng.h" -#include "../include/tinycrypt/hmac.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include +#include /* * min bytes in the seed string. diff --git a/src/nimble/ext/tinycrypt/src/sha256.c b/src/nimble/ext/tinycrypt/src/sha256.c index b7e0bba5..ab2170c2 100644 --- a/src/nimble/ext/tinycrypt/src/sha256.c +++ b/src/nimble/ext/tinycrypt/src/sha256.c @@ -30,9 +30,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/sha256.h" -#include "../include/tinycrypt/constants.h" -#include "../include/tinycrypt/utils.h" +#include +#include +#include static void compress(unsigned int *iv, const uint8_t *data); diff --git a/src/nimble/ext/tinycrypt/src/utils.c b/src/nimble/ext/tinycrypt/src/utils.c index 792a7817..d0015594 100644 --- a/src/nimble/ext/tinycrypt/src/utils.c +++ b/src/nimble/ext/tinycrypt/src/utils.c @@ -30,8 +30,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "../include/tinycrypt/utils.h" -#include "../include/tinycrypt/constants.h" +#include +#include #include diff --git a/src/nimble/nimble/controller/include/controller/ble_fem.h b/src/nimble/nimble/controller/include/controller/ble_fem.h new file mode 100644 index 00000000..31466f26 --- /dev/null +++ b/src/nimble/nimble/controller/include/controller/ble_fem.h @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_FEM_ +#define H_BLE_FEM_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nimble/porting/nimble/include/syscfg/syscfg.h" + +#if MYNEWT_VAL(BLE_FEM_PA) +void ble_fem_pa_init(void); +void ble_fem_pa_enable(void); +void ble_fem_pa_disable(void); +#if MYNEWT_VAL(BLE_FEM_PA_GAIN_TUNABLE) +/* Configures FEM to selected TX power and returns expected PHY TX power */ +int ble_fem_pa_tx_power_set(int tx_power); + +/* returns rounded FEM TX power */ +int ble_fem_pa_tx_power_round(int tx_power); +#endif +#endif + +#if MYNEWT_VAL(BLE_FEM_LNA) +void ble_fem_lna_init(void); +void ble_fem_lna_enable(void); +void ble_fem_lna_disable(void); + +#if MYNEWT_VAL(BLE_FEM_LNA_GAIN_TUNABLE) +/* Return current value of FEM LNA RX gain (in dBm) */ +int ble_fem_lna_rx_gain(void); +#endif + +#endif + +#if MYNEWT_VAL(BLE_FEM_ANTENNA) +/* 0 sets default antenna, any other value is FEM specific */ +int ble_fem_antenna(uint8_t antenna); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_FEM_ */ diff --git a/src/nimble/nimble/controller/include/controller/ble_ll.h b/src/nimble/nimble/controller/include/controller/ble_ll.h index 4d8c9e92..4bed7924 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll.h @@ -23,14 +23,14 @@ #include "nimble/porting/nimble/include/stats/stats.h" #include "nimble/nimble/include/nimble/nimble_opt.h" #include "nimble/nimble/include/nimble/nimble_npl.h" -#include "ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" #ifdef MYNEWT -#include "./ble_ll_ctrl.h" -#include "hal/hal_system.h" +#include "nimble/nimble/controller/include/controller/ble_ll_ctrl.h" +#include "nimble/porting/nimble/include/hal/hal_system.h" #endif #ifdef RIOT_VERSION -#include "hal/hal_timer.h" +#include "nimble/porting/nimble/include/hal/hal_timer.h" #endif #ifdef __cplusplus @@ -50,10 +50,8 @@ void ble_ll_assert(const char *file, unsigned line) __attribute((noreturn)); } #endif #else -#ifndef BLE_LL_ASSERT #define BLE_LL_ASSERT(cond) assert(cond) #endif -#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) #define BLE_LL_BT5_PHY_SUPPORTED (1) @@ -109,8 +107,8 @@ struct ble_ll_obj uint8_t ll_state; /* Global channel map */ - uint8_t chan_map_num_used; uint8_t chan_map[BLE_LL_CHAN_MAP_LEN]; + uint8_t chan_map_used; #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) /* Number of ACL data packets supported */ @@ -120,6 +118,11 @@ struct ble_ll_obj uint16_t ll_acl_pkt_size; #endif +#if MYNEWT_VAL(BLE_LL_ISO) + uint8_t ll_num_iso_pkts; + uint16_t ll_iso_pkt_size; +#endif + /* Preferred PHY's */ uint8_t ll_pref_tx_phys; uint8_t ll_pref_rx_phys; @@ -239,6 +242,12 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; #if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) && MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) #define BLE_LL_STATE_SCAN_AUX (7) #endif +#if MYNEWT_VAL(BLE_LL_EXT) +#define BLE_LL_STATE_EXTERNAL (8) +#endif +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) +#define BLE_LL_STATE_BIG (9) +#endif /* LL Features */ #define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000001) @@ -291,11 +300,16 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats; #define BLE_LL_CONN_CLEAR_FEATURE(connsm, feature) (connsm->conn_features &= ~(feature)) /* All the features which can be controlled by the Host */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) #define BLE_LL_HOST_CONTROLLED_FEATURES (BLE_LL_FEAT_CONN_SUBRATING_HOST) +#else +#define BLE_LL_HOST_CONTROLLED_FEATURES (0) +#endif /* LL timing */ #define BLE_LL_IFS (150) /* usecs */ #define BLE_LL_MAFS (300) /* usecs */ +#define BLE_LL_MSS (150) /* usecs */ /* * BLE LL device address. Note that element 0 of the array is the LSB and @@ -330,6 +344,27 @@ struct ble_dev_addr #define BLE_LL_MAX_PDU_LEN ((BLE_LL_PDU_HDR_LEN) + (BLE_LL_MAX_PAYLOAD_LEN)) #define BLE_LL_CRCINIT_ADV (0x555555) +#define BLE_LL_CONN_HANDLE(t, h) ((((t) << 8) & BLE_LL_CONN_HANDLE_TYPE_MASK) | \ + ((h) & BLE_LL_CONN_HANDLE_IDX_MASK)) +#define BLE_LL_CONN_HANDLE_TYPE_MASK (0x0700) +#define BLE_LL_CONN_HANDLE_IDX_MASK (0x00ff) +#define BLE_LL_CONN_HANDLE_TYPE(conn_h) (((conn_h) & BLE_LL_CONN_HANDLE_TYPE_MASK) >> 8) +#define BLE_LL_CONN_HANDLE_IDX(conn_h) ((conn_h) & BLE_LL_CONN_HANDLE_IDX_MASK) + +#define BLE_LL_CONN_HANDLE_TYPE_ACL (0x00) +#define BLE_LL_CONN_HANDLE_TYPE_CIS (0x01) +#define BLE_LL_CONN_HANDLE_TYPE_BIS (0x02) +#define BLE_LL_CONN_HANDLE_TYPE_BIS_SYNC (0x03) + +#define BLE_LL_CONN_HANDLE_IS_ACL(ch) \ + (BLE_LL_CONN_HANDLE_TYPE(ch) == BLE_LL_CONN_HANDLE_TYPE_ACL) +#define BLE_LL_CONN_HANDLE_IS_CIS(ch) \ + (BLE_LL_CONN_HANDLE_TYPE(ch) == BLE_LL_CONN_HANDLE_TYPE_CIS) +#define BLE_LL_CONN_HANDLE_IS_BIS(ch) \ + (BLE_LL_CONN_HANDLE_TYPE(ch) == BLE_LL_CONN_HANDLE_TYPE_BIS) +#define BLE_LL_CONN_HANDLE_IS_BIS_SYNC(ch) \ + (BLE_LL_CONN_HANDLE_TYPE(ch) == BLE_LL_CONN_HANDLE_TYPE_BIS_SYNC) + /* Access address for advertising channels */ #define BLE_ACCESS_ADDR_ADV (0x8E89BED6) @@ -470,6 +505,7 @@ struct ble_dev_addr /* ACAD data types */ #define BLE_LL_ACAD_CHANNEL_MAP_UPDATE_IND 0x28 +#define BLE_LL_ACAD_BIGINFO 0x2C struct ble_ll_acad_channel_map_update_ind { uint8_t map[5]; @@ -490,10 +526,6 @@ int ble_ll_is_valid_random_addr(const uint8_t *addr); int ble_ll_is_valid_own_addr_type(uint8_t own_addr_type, const uint8_t *random_addr); -/* Calculate the amount of time in microseconds a PDU with payload length of - * 'payload_len' will take to transmit on a PHY 'phy_mode'. */ -uint32_t ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode); - /* Calculate maximum octets of PDU payload which can be transmitted during * 'usecs' on a PHY 'phy_mode'. */ uint16_t ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode); @@ -561,8 +593,11 @@ void ble_ll_state_set(uint8_t ll_state); /* Get the link layer state */ uint8_t ble_ll_state_get(void); -/* Send an event to LL task */ -void ble_ll_event_send(struct ble_npl_event *ev); +/* Add an event to LL task */ +void ble_ll_event_add(struct ble_npl_event *ev); + +/* Remove an event from LL task */ +void ble_ll_event_remove(struct ble_npl_event *ev); /* Hand received pdu's to LL task */ void ble_ll_rx_pdu_in(struct os_mbuf *rxpdu); @@ -591,10 +626,6 @@ int ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len); /* Read set of states supported by the Link Layer */ uint64_t ble_ll_read_supp_states(void); -/* Check if octets and time are valid. Returns 0 if not valid */ -int ble_ll_chk_txrx_octets(uint16_t octets); -int ble_ll_chk_txrx_time(uint16_t time); - /* Random numbers */ int ble_ll_rand_init(void); void ble_ll_rand_sample(uint8_t rnum); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_adv.h b/src/nimble/nimble/controller/include/controller/ble_ll_adv.h index eee07cbf..7ff6d350 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_adv.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_adv.h @@ -199,6 +199,20 @@ int ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len); int ble_ll_adv_periodic_set_info_transfer(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); +/* Get advertising instance with periodic advertising configured */ +struct ble_ll_adv_sm *ble_ll_adv_sync_get(uint8_t handle); + +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) +struct ble_ll_iso_big; + +/* Add BIG to periodic advertising instance */ +int ble_ll_adv_sync_big_add(struct ble_ll_adv_sm *advsm, + struct ble_ll_iso_big *big); +/* Remove BIG from periodic advertising instance */ +int ble_ll_adv_sync_big_remove(struct ble_ll_adv_sm *advsm, + struct ble_ll_iso_big *big); +#endif /* BLE_LL_ISO_BROADCASTER */ + /* Called to notify adv code about RPA rotation */ void ble_ll_adv_rpa_timeout(void); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_conn.h b/src/nimble/nimble/controller/include/controller/ble_ll_conn.h index b6698837..8fabc0bc 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_conn.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_conn.h @@ -24,10 +24,10 @@ #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/hci_common.h" #include "nimble/nimble/include/nimble/nimble_npl.h" -#include "ble_ll.h" -#include "ble_ll_sched.h" -#include "ble_ll_ctrl.h" -#include "ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_ctrl.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" #ifdef __cplusplus extern "C" { @@ -98,44 +98,44 @@ struct ble_ll_conn_enc_data #endif /* Connection state machine flags. */ -union ble_ll_conn_sm_flags { - struct { - uint32_t pkt_rxd:1; - uint32_t terminate_ind_txd:1; - uint32_t terminate_ind_rxd:1; - uint32_t terminate_ind_rxd_acked:1; - uint32_t allow_periph_latency:1; - uint32_t periph_set_last_anchor:1; - uint32_t awaiting_host_reply:1; - uint32_t terminate_started:1; - uint32_t conn_update_sched:1; - uint32_t host_expects_upd_event:1; - uint32_t version_ind_sent:1; - uint32_t rxd_version_ind:1; - uint32_t chanmap_update_scheduled:1; - uint32_t conn_empty_pdu_txd:1; - uint32_t last_txd_md:1; - uint32_t conn_req_txd:1; - uint32_t send_ltk_req:1; - uint32_t encrypted:1; - uint32_t encrypt_chg_sent:1; - uint32_t le_ping_supp:1; - uint32_t csa2_supp:1; - uint32_t host_phy_update: 1; - uint32_t phy_update_sched: 1; - uint32_t ctrlr_phy_update: 1; - uint32_t phy_update_event: 1; - uint32_t peer_phy_update: 1; /* XXX:combine with ctrlr udpate bit? */ - uint32_t aux_conn_req: 1; - uint32_t rxd_features:1; - uint32_t pending_hci_rd_features:1; - uint32_t pending_initiate_dle:1; - uint32_t subrate_trans:1; - uint32_t subrate_ind_txd:1; - uint32_t subrate_host_req:1; - } cfbit; - uint32_t conn_flags; -} __attribute__((packed)); +struct ble_ll_conn_sm_flags { + uint32_t pkt_rxd : 1; + uint32_t last_txd_md : 1; + uint32_t empty_pdu_txd : 1; + uint32_t periph_use_latency : 1; + uint32_t periph_set_last_anchor : 1; + uint32_t csa2 : 1; + uint32_t encrypted : 1; + uint32_t encrypt_ltk_req : 1; + uint32_t encrypt_event_sent : 1; + uint32_t version_ind_txd : 1; + uint32_t version_ind_rxd : 1; + uint32_t features_rxd : 1; + uint32_t features_host_req : 1; + uint32_t terminate_started : 1; + uint32_t terminate_ind_txd : 1; + uint32_t terminate_ind_rxd : 1; + uint32_t terminate_ind_rxd_acked : 1; + uint32_t conn_update_sched : 1; + uint32_t conn_update_use_cp : 1; + uint32_t conn_update_host_w4reply : 1; + uint32_t conn_update_host_w4event : 1; + uint32_t chanmap_update_sched : 1; + uint32_t phy_update_sched : 1; + uint32_t phy_update_self_initiated : 1; + uint32_t phy_update_peer_initiated : 1; + uint32_t phy_update_host_initiated : 1; + uint32_t phy_update_host_w4event : 1; + uint32_t le_ping_supp : 1; +#if MYNEWT_VAL(BLE_LL_CONN_INIT_AUTO_DLE) + uint32_t pending_initiate_dle : 1; +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) + uint8_t subrate_trans : 1; + uint8_t subrate_ind_txd : 1; + uint8_t subrate_host_req : 1; +#endif +}; /** * Structure used for PHY data inside a connection. @@ -204,7 +204,7 @@ struct ble_ll_conn_subrate_req_params { struct ble_ll_conn_sm { /* Connection state machine flags */ - union ble_ll_conn_sm_flags csmflags; + struct ble_ll_conn_sm_flags flags; /* Current connection handle, state and role */ uint16_t conn_handle; @@ -227,8 +227,10 @@ struct ble_ll_conn_sm uint16_t rem_max_rx_time; uint16_t eff_max_tx_time; uint16_t eff_max_rx_time; + uint16_t ota_max_rx_time; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) uint16_t host_req_max_tx_time; + uint16_t host_req_max_rx_time; #endif #if (BLE_LL_BT5_PHY_SUPPORTED == 1) @@ -238,14 +240,14 @@ struct ble_ll_conn_sm #endif /* Used to calculate data channel index for connection */ - uint8_t chanmap[BLE_LL_CHAN_MAP_LEN]; + uint8_t chan_map[BLE_LL_CHAN_MAP_LEN]; uint8_t req_chanmap[BLE_LL_CHAN_MAP_LEN]; uint16_t chanmap_instant; uint16_t channel_id; /* TODO could be union with hop and last chan used */ uint8_t hop_inc; uint8_t data_chan_index; uint8_t last_unmapped_chan; - uint8_t num_used_chans; + uint8_t chan_map_used; /* Ack/Flow Control */ uint8_t tx_seqnum; /* note: can be 1 bit */ @@ -287,8 +289,7 @@ struct ble_ll_conn_sm /* Connection timing */ uint16_t conn_itvl; uint16_t supervision_tmo; - uint16_t min_ce_len; - uint16_t max_ce_len; + uint32_t max_ce_len_ticks; uint16_t tx_win_off; uint32_t anchor_point; uint8_t anchor_point_usecs; /* XXX: can this be uint8_t ?*/ @@ -310,7 +311,8 @@ struct ble_ll_conn_sm uint16_t subrate_base_event; uint16_t subrate_factor; uint16_t cont_num; - uint16_t last_pdu_event; + uint16_t cont_num_left; + uint8_t has_nonempty_pdu; union { struct ble_ll_conn_subrate_params subrate_trans; @@ -377,6 +379,7 @@ struct ble_ll_conn_sm /* For connection update procedure */ struct ble_ll_conn_upd_req conn_update_req; + uint16_t conn_update_anchor_offset_req; /* XXX: for now, just store them all */ struct ble_ll_conn_params conn_cp; @@ -388,29 +391,13 @@ struct ble_ll_conn_sm #endif #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + SLIST_ENTRY(ble_ll_conn_sm) css_sle; uint16_t css_slot_idx; uint16_t css_slot_idx_pending; uint8_t css_period_idx; #endif }; -/* Flags */ -#define CONN_F_UPDATE_SCHED(csm) ((csm)->csmflags.cfbit.conn_update_sched) -#define CONN_F_EMPTY_PDU_TXD(csm) ((csm)->csmflags.cfbit.conn_empty_pdu_txd) -#define CONN_F_LAST_TXD_MD(csm) ((csm)->csmflags.cfbit.last_txd_md) -#define CONN_F_CONN_REQ_TXD(csm) ((csm)->csmflags.cfbit.conn_req_txd) -#define CONN_F_ENCRYPTED(csm) ((csm)->csmflags.cfbit.encrypted) -#define CONN_F_ENC_CHANGE_SENT(csm) ((csm)->csmflags.cfbit.encrypt_chg_sent) -#define CONN_F_LE_PING_SUPP(csm) ((csm)->csmflags.cfbit.le_ping_supp) -#define CONN_F_TERMINATE_STARTED(csm) ((csm)->csmflags.cfbit.terminate_started) -#define CONN_F_CSA2_SUPP(csm) ((csm)->csmflags.cfbit.csa2_supp) -#define CONN_F_HOST_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.host_phy_update) -#define CONN_F_PHY_UPDATE_SCHED(csm) ((csm)->csmflags.cfbit.phy_update_sched) -#define CONN_F_CTRLR_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.ctrlr_phy_update) -#define CONN_F_PHY_UPDATE_EVENT(csm) ((csm)->csmflags.cfbit.phy_update_event) -#define CONN_F_PEER_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.peer_phy_update) -#define CONN_F_AUX_CONN_REQ(csm) ((csm)->csmflags.cfbit.aux_conn_req) - /* Role */ #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define CONN_IS_CENTRAL(csm) (csm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) @@ -454,6 +441,9 @@ struct ble_ll_conn_sm *ble_ll_conn_find_by_handle(uint16_t handle); struct ble_ll_conn_sm *ble_ll_conn_find_by_peer_addr(const uint8_t* addr, uint8_t addr_type); +/* Perform channel map update on all connections (applies to central role) */ +void ble_ll_conn_chan_map_update(void); + /* required for unit testing */ uint8_t ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency); diff --git a/src/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h b/src/nimble/nimble/controller/include/controller/ble_ll_crypto.h similarity index 55% rename from src/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h rename to src/nimble/nimble/controller/include/controller/ble_ll_crypto.h index 26c18d01..4514b0b1 100644 --- a/src/nimble/nimble/host/services/ias/include/services/ias/ble_svc_ias.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_crypto.h @@ -1,4 +1,4 @@ -/** +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,22 +17,34 @@ * under the License. */ -#ifndef H_BLE_IAS_TPS_ -#define H_BLE_IAS_TPS_ +#ifndef H_BLE_LL_CRYPTO_ +#define H_BLE_LL_CRYPTO_ -#define BLE_SVC_IAS_UUID16 0x1802 -#define BLE_SVC_IAS_CHR_UUID16_ALERT_LEVEL 0x2a06 +#ifdef __cplusplus +extern "C" { +#endif -/* Alert level definitions */ -#define BLE_SVC_IAS_ALERT_LEVEL_NO_ALERT 0 -#define BLE_SVC_IAS_ALERT_LEVEL_MILD_ALERT 1 -#define BLE_SVC_IAS_ALERT_LEVEL_HIGH_ALERT 2 +int +ble_ll_crypto_cmac(const uint8_t *key, const uint8_t *in, int len, + uint8_t *out); -typedef int ble_svc_ias_event_fn(uint8_t alert_level); +static inline int +ble_ll_crypto_h6(const uint8_t *w, const uint8_t *key_id, uint8_t *out) +{ + return ble_ll_crypto_cmac(w, key_id, 4, out); +} -void ble_svc_ias_set_cb(ble_svc_ias_event_fn *cb); -void ble_svc_ias_init(void); +static inline int +ble_ll_crypto_h7(const uint8_t *salt, const uint8_t *w, uint8_t *out) +{ + return ble_ll_crypto_cmac(salt, w, 16, out); +} -#endif +int ble_ll_crypto_h8(const uint8_t *k, const uint8_t *s, const uint8_t *key_id, + uint8_t *out); +#ifdef __cplusplus +} +#endif +#endif /* H_BLE_LL_CRYPTO_ */ diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h b/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h index 379960ec..89502a45 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_ctrl.h @@ -333,8 +333,9 @@ void ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle, int ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status); void ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm); void ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm); -void ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm); +void ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm, bool initial); void ble_ll_hci_ev_send_vs_assert(const char *file, uint32_t line); +void ble_ll_hci_ev_send_vs_printf(uint8_t id, const char *fmt, ...); void ble_ll_hci_ev_send_vs_llcp_trace(uint8_t type, uint16_t handle, uint16_t count, void *pdu, size_t length); @@ -350,6 +351,11 @@ void ble_ll_hci_ev_sca_update(struct ble_ll_conn_sm *connsm, void ble_ll_hci_ev_subrate_change(struct ble_ll_conn_sm *connsm, uint8_t status); #endif +#if MYNEWT_VAL(BLE_LL_HCI_VS_CONN_STRICT_SCHED) +void ble_ll_hci_ev_send_vs_css_slot_changed(uint16_t conn_handle, + uint16_t slot_idx); +#endif + #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_ext.h b/src/nimble/nimble/controller/include/controller/ble_ll_ext.h new file mode 100644 index 00000000..5b3bb376 --- /dev/null +++ b/src/nimble/nimble/controller/include/controller/ble_ll_ext.h @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_EXT_ +#define H_BLE_LL_EXT_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MYNEWT_VAL(BLE_LL_EXT) + +/* Quickstart guide: + * - create scheduling item with sched_type set to BLE_LL_SCHED_EXTERNAL + * - use sched_ext_type to differentiate between different types of custom items + * - insert into scheduler using ble_ll_sched_insert() + * - set LL state to BLE_LL_STATE_EXTERNAL when item is being executed + * - set LL state back to BLE_LL_STATE_IDLE when item is done + */ + +struct ble_ll_sched_item; + +/* Called when LL package is initialized (before ll_task is started) */ +void ble_ll_ext_init(void); +/* Called when LL is reset (i.e. HCI_Reset) */ +void ble_ll_ext_reset(void); +/* Called when LL is in "external" state and PHY starts to receive a PDU */ +int ble_ll_ext_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr); +/* Called when LL is in "external" state and PHY finished to receive a PDU */ +int ble_ll_ext_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); +/* Called when PDU received in "external" state reaches LL */ +void ble_ll_ext_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr); +/* Called when LL is in "external" state and was preempted */ +void ble_ll_ext_halt(void); +/* Called when LL is in "external" state and PHY failed to receive a PDU */ +void ble_ll_ext_wfr_timer_exp(void); +/* Called when an "external" scheduling item was removed from scheduler queue */ +void ble_ll_ext_sched_removed(struct ble_ll_sched_item *sch); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_EXT_ */ diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_hci.h b/src/nimble/nimble/controller/include/controller/ble_ll_hci.h index 8daf066f..e011f909 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_hci.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_hci.h @@ -27,10 +27,6 @@ extern "C" { #include "nimble/nimble/include/nimble/hci_common.h" #include "nimble/nimble/transport/include/nimble/transport.h" -/* For supported commands */ -#define BLE_LL_SUPP_CMD_LEN (47) -extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN]; - /* The largest event the controller will send. */ #define BLE_LL_MAX_EVT_LEN MYNEWT_VAL(BLE_TRANSPORT_EVT_SIZE) @@ -42,7 +38,7 @@ extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN]; */ #define BLE_LL_CFG_NUM_HCI_CMD_PKTS (1) -typedef void (*ble_ll_hci_post_cmd_complete_cb)(void); +typedef void (*ble_ll_hci_post_cmd_complete_cb)(void *user_data); #if MYNEWT_VAL(BLE_LL_HCI_VS) typedef int (* ble_ll_hci_vs_cb_t)(uint16_t ocf, @@ -61,6 +57,10 @@ struct ble_ll_hci_vs_cmd { /* Initialize LL HCI */ void ble_ll_hci_init(void); +int ble_ll_hci_cmd_rx(uint8_t *cmdbuf); +int ble_ll_hci_acl_rx(struct os_mbuf *om); +int ble_ll_hci_iso_rx(struct os_mbuf *om); + /* Used to determine if the LE event is enabled/disabled */ bool ble_ll_hci_is_le_event_enabled(unsigned int subev); @@ -80,8 +80,13 @@ int ble_ll_hci_chk_phy_masks(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys, /* Returns true if Extended Advertising HCI commands are in use */ bool ble_ll_hci_adv_mode_ext(void); -/* Get TX power compensation rounded to integer dB */ -int8_t ble_ll_get_tx_pwr_compensation(void); +/* Check if max octets/time are within allowed range */ +int ble_ll_hci_check_dle(uint16_t max_octets, uint16_t max_time); + +void ble_ll_hci_supp_cmd_get(uint8_t *buf); + +/* Used to set post HCI command hook */ +void ble_ll_hci_post_cmd_cb_set(ble_ll_hci_post_cmd_complete_cb cb, void *user_data); #if MYNEWT_VAL(BLE_LL_HCI_VS) void ble_ll_hci_vs_register(struct ble_ll_hci_vs_cmd *cmds, uint32_t num_cmds); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_iso_big.h b/src/nimble/nimble/controller/include/controller/ble_ll_iso_big.h new file mode 100644 index 00000000..30cf1b46 --- /dev/null +++ b/src/nimble/nimble/controller/include/controller/ble_ll_iso_big.h @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_ISO_BIG_ +#define H_BLE_LL_ISO_BIG_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + +struct ble_ll_iso_big; +struct ble_ll_iso_bis; + +int ble_ll_iso_big_biginfo_copy(struct ble_ll_iso_big *big, uint8_t *dptr, + uint32_t base_ticks, uint8_t base_rem_us); +int ble_ll_iso_big_biginfo_len(struct ble_ll_iso_big *big); + +struct ble_ll_iso_bis *ble_ll_iso_big_find_bis_by_handle(uint16_t conn_handle); +struct ble_ll_isoal_mux *ble_ll_iso_big_find_mux_by_handle(uint16_t conn_handle); +int ble_ll_iso_big_last_tx_timestamp_get(struct ble_ll_iso_bis *bis, + uint16_t *packet_seq_num, + uint32_t *timestamp); + +void ble_ll_iso_big_chan_map_update(void); + +void ble_ll_iso_big_halt(void); + +int ble_ll_iso_big_hci_create(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_big_hci_create_test(const uint8_t *cmdbuf, uint8_t len); +int ble_ll_iso_big_hci_terminate(const uint8_t *cmdbuf, uint8_t len); +void ble_ll_iso_big_hci_evt_complete(void); + +void ble_ll_iso_big_init(void); +void ble_ll_iso_big_reset(void); + +#endif /* BLE_LL_ISO_BROADCASTER */ + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_ISO_BIG_ */ diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_isoal.h b/src/nimble/nimble/controller/include/controller/ble_ll_isoal.h new file mode 100644 index 00000000..5104ea97 --- /dev/null +++ b/src/nimble/nimble/controller/include/controller/ble_ll_isoal.h @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_LL_ISOAL_ +#define H_BLE_LL_ISOAL_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MYNEWT_VAL(BLE_LL_ISO) + +struct ble_ll_isoal_mux { + /* Max PDU length */ + uint8_t max_pdu; + /* Number of expected SDUs per ISO interval */ + uint8_t sdu_per_interval; + /* Number of expected PDUs per SDU */ + uint8_t pdu_per_sdu; + /* Number of SDUs required to fill complete BIG/CIG event (i.e. with pt) */ + uint8_t sdu_per_event; + /* Number of SDUs available for current event */ + uint8_t sdu_in_event; + + STAILQ_HEAD(, os_mbuf_pkthdr) sdu_q; + + struct os_mbuf *frag; + + uint32_t sdu_counter; + + uint32_t event_tx_timestamp; + uint32_t last_tx_timestamp; + uint16_t last_tx_packet_seq_num; +}; + +void +ble_ll_isoal_mux_init(struct ble_ll_isoal_mux *mux, uint8_t max_pdu, + uint32_t iso_interval_us, uint32_t sdu_interval_us, + uint8_t bn, uint8_t pte); +void ble_ll_isoal_mux_free(struct ble_ll_isoal_mux *mux); + +int ble_ll_isoal_mux_event_start(struct ble_ll_isoal_mux *mux, + uint32_t timestamp); +int ble_ll_isoal_mux_event_done(struct ble_ll_isoal_mux *mux); + +int +ble_ll_isoal_mux_unframed_get(struct ble_ll_isoal_mux *mux, uint8_t idx, + uint8_t *llid, void *dptr); + +/* HCI command handlers */ +int ble_ll_isoal_hci_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_isoal_hci_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen); +int ble_ll_isoal_hci_read_tx_sync(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen); + +void ble_ll_isoal_init(void); +void ble_ll_isoal_reset(void); +int ble_ll_isoal_data_in(struct os_mbuf *om); + +#endif /* BLE_LL_ISO */ + +#ifdef __cplusplus +} +#endif + +#endif /* H_BLE_LL_ISOAL_ */ diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_test.h b/src/nimble/nimble/controller/include/controller/ble_ll_pdu.h similarity index 60% rename from src/nimble/nimble/controller/include/controller/ble_ll_test.h rename to src/nimble/nimble/controller/include/controller/ble_ll_pdu.h index 32984c6b..b18db944 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_test.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_pdu.h @@ -17,19 +17,31 @@ * under the License. */ -#ifndef H_LL_TEST_ -#define H_LL_TEST_ +#ifndef H_BLE_LL_PDU_ +#define H_BLE_LL_PDU_ -#include +#include #ifdef __cplusplus extern "C" { #endif -int ble_ll_csa2_test_all(void); +/* Header mask for keystream generation */ +#define BLE_LL_PDU_HEADERMASK_DATA (0xe3) +#define BLE_LL_PDU_HEADERMASK_BIS (0xc3) +#define BLE_LL_PDU_HEADERMASK_CIS (0xa3) + +#define BLE_LL_PDU_PREAMBLE_1M_LEN (1) +#define BLE_LL_PDU_PREAMBLE_2M_LEN (2) +#define BLE_LL_PDU_AA_LEN (4) +#define BLE_LL_PDU_HEADER_LEN (2) +#define BLE_LL_PDU_CRC_LEN (3) + +uint32_t ble_ll_pdu_syncword_us(uint8_t phy_mode); +uint32_t ble_ll_pdu_us(uint8_t payload_len, uint8_t phy_mode); #ifdef __cplusplus } #endif -#endif +#endif /* H_BLE_LL_PDU_ */ diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h b/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h index 727b9cfe..20bce1be 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h @@ -24,7 +24,7 @@ extern "C" { #endif -#include "ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" void ble_ll_rfmgmt_init(void); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_scan.h b/src/nimble/nimble/controller/include/controller/ble_ll_scan.h index 15016996..7a8640cb 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_scan.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_scan.h @@ -20,8 +20,8 @@ #ifndef H_BLE_LL_SCAN_ #define H_BLE_LL_SCAN_ -#include "ble_ll_sched.h" -#include "ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/nimble/include/nimble/nimble_npl.h" @@ -235,11 +235,6 @@ void ble_ll_scan_wfr_timer_exp(void); /* Called when scan could be interrupted */ void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -/* Called to parse extended advertising*/ -void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data); -#endif - /* Called to halt currently running scan */ void ble_ll_scan_halt(void); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_scan_aux.h b/src/nimble/nimble/controller/include/controller/ble_ll_scan_aux.h index c7d63b84..b1d6c9ca 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_scan_aux.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_scan_aux.h @@ -29,8 +29,8 @@ extern "C" { struct ble_ll_scan_aux_data; void ble_ll_scan_aux_init(void); -int ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_time, - uint8_t pdu_time_rem, uint32_t aux_ptr); +int ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_ticks, + uint8_t pdu_rem_us, uint32_t aux_ptr); int ble_ll_scan_aux_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr); int ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok); void ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_sched.h b/src/nimble/nimble/controller/include/controller/ble_ll_sched.h index a65b5d43..cceb96ce 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_sched.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_sched.h @@ -70,6 +70,10 @@ extern uint8_t g_ble_ll_sched_offset_ticks; #define BLE_LL_SCHED_TYPE_PERIODIC (6) #define BLE_LL_SCHED_TYPE_SYNC (7) #define BLE_LL_SCHED_TYPE_SCAN_AUX (8) +#define BLE_LL_SCHED_TYPE_BIG (9) +#if MYNEWT_VAL(BLE_LL_EXT) +#define BLE_LL_SCHED_TYPE_EXTERNAL (255) +#endif /* Return values for schedule callback. */ #define BLE_LL_SCHED_STATE_RUNNING (0) @@ -80,6 +84,10 @@ struct ble_ll_sched_item; typedef int (*sched_cb_func)(struct ble_ll_sched_item *sch); typedef void (*sched_remove_cb_func)(struct ble_ll_sched_item *sch); +typedef int (* ble_ll_sched_preempt_cb_t)(struct ble_ll_sched_item *sch, + struct ble_ll_sched_item *item); + + /* * Schedule item * sched_type: This is the type of the schedule item. @@ -91,6 +99,9 @@ typedef void (*sched_remove_cb_func)(struct ble_ll_sched_item *sch); struct ble_ll_sched_item { uint8_t sched_type; +#if MYNEWT_VAL(BLE_LL_EXT) + uint8_t sched_ext_type; +#endif uint8_t enqueued; uint8_t remainder; uint32_t start_time; @@ -103,6 +114,10 @@ struct ble_ll_sched_item /* Initialize the scheduler */ int ble_ll_sched_init(void); +int ble_ll_sched_insert(struct ble_ll_sched_item *sch, uint32_t max_delay, + ble_ll_sched_preempt_cb_t preempt_cb); +void ble_ll_sched_restart(void); + /* Remove item(s) from schedule */ int ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch); @@ -127,13 +142,8 @@ int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch, /* Schedule periodic advertising event */ int ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, bool first_event); -int ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, - uint32_t anchor_point, - uint8_t anchor_point_usecs, - uint32_t window_widening, int8_t phy_mode); -int ble_ll_sched_sync(struct ble_ll_sched_item *sch, - uint32_t beg_cputime, uint32_t rem_usecs, uint32_t offset, - int8_t phy_mode); +int ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, uint32_t ww_us); +int ble_ll_sched_sync(struct ble_ll_sched_item *sch); /* Reschedule an advertising event */ int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, @@ -158,14 +168,7 @@ int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm * connsm); int ble_ll_sched_next_time(uint32_t *next_event_time); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -struct ble_ll_scan_sm; -struct ble_ll_aux_data; -int ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr, - struct ble_ll_scan_sm *scansm, - struct ble_ll_aux_data *aux_scan); - -int ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, - uint8_t pdu_time_rem, uint32_t offset_us); +int ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch); #endif /* Stop the scheduler */ @@ -179,8 +182,16 @@ int ble_ll_sched_dtm(struct ble_ll_sched_item *sch); #if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED) void ble_ll_sched_css_set_params(uint32_t slot_us, uint32_t period_slots); #endif +void ble_ll_sched_css_set_enabled(uint8_t enabled); +void ble_ll_sched_css_update_anchor(struct ble_ll_conn_sm *connsm); void ble_ll_sched_css_set_conn_anchor(struct ble_ll_conn_sm *connsm); #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED) +static inline bool +ble_ll_sched_css_is_enabled(void) +{ + return true; +} + static inline uint32_t ble_ll_sched_css_get_slot_us(void) { @@ -200,12 +211,17 @@ ble_ll_sched_css_get_conn_interval_us(void) ble_ll_sched_css_get_slot_us() / 1250; } #else +bool ble_ll_sched_css_is_enabled(void); uint32_t ble_ll_sched_css_get_slot_us(void); uint32_t ble_ll_sched_css_get_period_slots(void); uint32_t ble_ll_sched_css_get_conn_interval_us(void); #endif #endif +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) +int ble_ll_sched_iso_big(struct ble_ll_sched_item *sch, int first); +#endif /* BLE_LL_ISO_BROADCASTER */ + #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_sync.h b/src/nimble/nimble/controller/include/controller/ble_ll_sync.h index 033d9b10..9817a67e 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_sync.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_sync.h @@ -23,8 +23,8 @@ #include #include "nimble/nimble/include/nimble/ble.h" -#include "ble_ll_hci.h" -#include "ble_ll_conn.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_conn.h" #ifdef __cplusplus extern "C" { @@ -34,7 +34,7 @@ struct ble_ll_scan_addr_data; struct ble_ll_sync_sm; int ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len); -int ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb); +int ble_ll_sync_cancel(void); int ble_ll_sync_terminate(const uint8_t *cmdbuf, uint8_t len); int ble_ll_sync_list_add(const uint8_t *cmdbuf, uint8_t len); int ble_ll_sync_list_remove(const uint8_t *cmdbuf, uint8_t len); diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_tmr.h b/src/nimble/nimble/controller/include/controller/ble_ll_tmr.h index 1796eb77..2dbe8a0e 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_tmr.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_tmr.h @@ -21,7 +21,7 @@ #define H_BLE_LL_TMR_ #include "nimble/porting/nimble/include/os/os_cputime.h" -#include "ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_utils.h b/src/nimble/nimble/controller/include/controller/ble_ll_utils.h index 16b91a0c..291872bf 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_utils.h +++ b/src/nimble/nimble/controller/include/controller/ble_ll_utils.h @@ -23,17 +23,28 @@ #define INT16_LT(_a, _b) ((int16_t)((_a) - (_b)) < 0) #define INT16_LTE(_a, _b) ((int16_t)((_a) - (_b)) <= 0) -uint32_t ble_ll_utils_calc_access_addr(void); -uint8_t ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap); +#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b)) +#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) +#define CLAMP(_n, _min, _max) (MAX(_min, MIN(_n, _max))) +#define IN_RANGE(_n, _min, _max) (((_n) >= (_min)) && ((_n) <= (_max))) + +int ble_ll_utils_verify_aa(uint32_t aa); +uint32_t ble_ll_utils_calc_aa(void); +uint32_t ble_ll_utils_calc_seed_aa(void); +uint32_t ble_ll_utils_calc_big_aa(uint32_t seed_aa, uint32_t n); + +uint8_t ble_ll_utils_chan_map_remap(const uint8_t *chan_map, uint8_t remap_index); +uint8_t ble_ll_utils_chan_map_used_get(const uint8_t *chan_map); + uint8_t ble_ll_utils_dci_csa2(uint16_t counter, uint16_t chan_id, uint8_t num_used_chans, const uint8_t *chan_map); uint16_t ble_ll_utils_dci_iso_event(uint16_t counter, uint16_t chan_id, - uint16_t *prn_sub_lu, uint8_t num_used_chans, + uint16_t *prn_sub_lu, uint8_t chan_map_used, const uint8_t *chan_map, uint16_t *remap_idx); uint16_t ble_ll_utils_dci_iso_subevent(uint16_t chan_id, uint16_t *prn_sub_lu, - uint8_t num_used_chans, const uint8_t *chan_map, + uint8_t chan_map_used, const uint8_t *chan_map, uint16_t *remap_idx); -uint8_t ble_ll_utils_calc_num_used_chans(const uint8_t *chan_map); + uint32_t ble_ll_utils_calc_window_widening(uint32_t anchor_point, uint32_t last_anchor_point, uint8_t central_sca); diff --git a/src/nimble/nimble/controller/include/controller/ble_phy.h b/src/nimble/nimble/controller/include/controller/ble_phy.h index fe8f7265..8864231a 100644 --- a/src/nimble/nimble/controller/include/controller/ble_phy.h +++ b/src/nimble/nimble/controller/include/controller/ble_phy.h @@ -65,6 +65,7 @@ struct os_mbuf; #define BLE_PHY_TRANSITION_NONE (0) #define BLE_PHY_TRANSITION_RX_TX (1) #define BLE_PHY_TRANSITION_TX_RX (2) +#define BLE_PHY_TRANSITION_TX_TX (3) /* PHY error codes */ #define BLE_PHY_ERR_RADIO_STATE (1) @@ -85,6 +86,16 @@ int ble_phy_init(void); /* Set the PHY channel */ int ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit); +uint8_t ble_phy_chan_get(void); + +#if MYNEWT_VAL(BLE_PHY_VARIABLE_TIFS) +/* Set T_ifs time for next transition */ +void ble_phy_tifs_set(uint16_t tifs); +#endif + +/* Set T_ifs for tx-tx transitions. Anchor is 0 for start of previous PDU, + * non-zero for end of PDU */ +void ble_phy_tifs_txtx_set(uint16_t usecs, uint8_t anchor); /* Set transmit start time */ int ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs); @@ -101,23 +112,17 @@ typedef uint8_t (*ble_phy_tx_pducb_t)(uint8_t *dptr, void *pducb_arg, /* Place the PHY into transmit mode */ int ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans); -/* Place the PHY into receive mode */ -int ble_phy_rx(void); - /* Copies the received PHY buffer into the allocated pdu */ void ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu); /* Set the transmit power */ -int ble_phy_txpwr_set(int dbm); +int ble_phy_tx_power_set(int dbm); /* Get highest allowed power from range */ -int ble_phy_txpower_round(int dbm); +int ble_phy_tx_power_round(int dbm); /* Get the transmit power */ -int ble_phy_txpwr_get(void); - -/* Set RX path power compensation value rounded to integer dB */ -void ble_phy_set_rx_pwr_compensation(int8_t compensation); +int ble_phy_tx_power_get(void); /* Disable the PHY */ void ble_phy_disable(void); @@ -160,15 +165,16 @@ uint8_t ble_phy_max_data_pdu_pyld(void); uint32_t ble_phy_access_addr_get(void); /* Enable encryption */ -void ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, - uint8_t is_central); - +void ble_phy_encrypt_enable(const uint8_t *key); +/* Set mask for PDU header (see Core 5.3, Vol 6, Part E, 2.2) */ +void ble_phy_encrypt_header_mask_set(uint8_t mask); +/* Set encryption IV */ +void ble_phy_encrypt_iv_set(const uint8_t *iv); +/* Set encryption packet counter and direction bit */ +void ble_phy_encrypt_counter_set(uint64_t counter, uint8_t dir_bit); /* Disable encryption */ void ble_phy_encrypt_disable(void); -/* Set the packet counters and dir used by LE encyption */ -void ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir); - /* Enable phy resolving list */ void ble_phy_resolv_list_enable(void); @@ -205,14 +211,9 @@ void ble_phy_resolv_list_disable(void); #define BLE_PHY_IDX_CODED (2) #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)) -uint32_t ble_phy_mode_pdu_start_off(int phy); void ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode); -#else -#define ble_phy_mode_pdu_start_off(phy) (40) - #endif -int ble_phy_get_cur_phy(void); static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options) { int phy_mode; diff --git a/src/nimble/nimble/controller/src/ble_ll.c b/src/nimble/nimble/controller/src/ble_ll.c index b872e90f..d0bf53f6 100644 --- a/src/nimble/nimble/controller/src/ble_ll.c +++ b/src/nimble/nimble/controller/src/ble_ll.c @@ -30,35 +30,39 @@ #include "nimble/nimble/include/nimble/nimble_opt.h" #include "nimble/nimble/include/nimble/hci_common.h" #include "nimble/nimble/transport/include/nimble/transport.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_phy_trace.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_scan_aux.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_ll_sync.h" -#include "../include/controller/ble_ll_plna.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_phy_trace.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_pdu.h" +#include "nimble/nimble/controller/include/controller/ble_ll_adv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan_aux.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_whitelist.h" +#include "nimble/nimble/controller/include/controller/ble_ll_resolv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h" +#include "nimble/nimble/controller/include/controller/ble_ll_trace.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sync.h" +#include "nimble/nimble/controller/include/controller/ble_fem.h" +#include "nimble/nimble/controller/include/controller/ble_ll_isoal.h" +#include "nimble/nimble/controller/include/controller/ble_ll_iso_big.h" +#if MYNEWT_VAL(BLE_LL_EXT) +#include "nimble/nimble/controller/include/controller/ble_ll_ext.h" +#endif #include "ble_ll_conn_priv.h" #include "ble_ll_hci_priv.h" #include "ble_ll_priv.h" +#include "nimble/porting/nimble/include/hal/hal_system.h" #if MYNEWT_VAL(BLE_LL_DTM) #include "ble_ll_dtm_priv.h" #endif -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) +#if MYNEWT_VAL(BLE_LL_EXT) +#include #endif /* XXX: @@ -73,7 +77,11 @@ * right thing to do. */ -int8_t g_ble_ll_tx_power = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); +/* This is TX power on PHY (or FEM PA if enabled) */ +int8_t g_ble_ll_tx_power; +static int8_t g_ble_ll_tx_power_phy_current; +int8_t g_ble_ll_tx_power_compensation; +int8_t g_ble_ll_rx_power_compensation; /* Supported states */ #if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) @@ -210,17 +218,13 @@ int8_t g_ble_ll_tx_power = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); #define BLE_LL_S_CA_INIT ((uint64_t)1 << 32) #define BLE_LL_S_HDCA_INIT ((uint64_t)1 << 33) #define BLE_LL_S_LDCA_INIT ((uint64_t)1 << 34) -#else -#define BLE_LL_S_CA_INIT ((uint64_t)0 << 32) -#define BLE_LL_S_HDCA_INIT ((uint64_t)0 << 33) -#define BLE_LL_S_LDCA_INIT ((uint64_t)0 << 34) -#endif - -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #define BLE_LL_S_CA_CENTRAL ((uint64_t)1 << 35) #define BLE_LL_S_HDCA_CENTRAL ((uint64_t)1 << 36) #define BLE_LL_S_LDCA_CENTRAL ((uint64_t)1 << 37) #else +#define BLE_LL_S_CA_INIT ((uint64_t)0 << 32) +#define BLE_LL_S_HDCA_INIT ((uint64_t)0 << 33) +#define BLE_LL_S_LDCA_INIT ((uint64_t)0 << 34) #define BLE_LL_S_CA_CENTRAL ((uint64_t)0 << 35) #define BLE_LL_S_HDCA_CENTRAL ((uint64_t)0 << 36) #define BLE_LL_S_LDCA_CENTRAL ((uint64_t)0 << 37) @@ -365,22 +369,11 @@ static void ble_ll_event_tx_pkt(struct ble_npl_event *ev); static void ble_ll_event_dbuf_overflow(struct ble_npl_event *ev); #endif -#if MYNEWT - -#if BABBLESIM -#define BLE_LL_STACK_SIZE (4000) -#else +#ifdef MYNEWT /* The BLE LL task data structure */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#define BLE_LL_STACK_SIZE (120) -#else -#define BLE_LL_STACK_SIZE (90) -#endif -#endif - struct os_task g_ble_ll_task; -OS_TASK_STACK_DEFINE(g_ble_ll_stack, BLE_LL_STACK_SIZE); +OS_TASK_STACK_DEFINE(g_ble_ll_stack, MYNEWT_VAL(BLE_LL_STACK_SIZE)); #endif /* MYNEWT */ @@ -390,25 +383,6 @@ uint8_t g_dev_addr[BLE_DEV_ADDR_LEN]; /** Our random address */ uint8_t g_random_addr[BLE_DEV_ADDR_LEN]; -static const uint16_t g_ble_ll_pdu_header_tx_time[BLE_PHY_NUM_MODE] = -{ - [BLE_PHY_MODE_1M] = - (BLE_LL_PREAMBLE_LEN + BLE_LL_ACC_ADDR_LEN + BLE_LL_CRC_LEN + - BLE_LL_PDU_HDR_LEN) << 3, - [BLE_PHY_MODE_2M] = - (BLE_LL_PREAMBLE_LEN * 2 + BLE_LL_ACC_ADDR_LEN + BLE_LL_CRC_LEN + - BLE_LL_PDU_HDR_LEN) << 2, - /* For Coded PHY we have exact TX times provided by specification: - * - Preamble, Access Address, CI, TERM1 (always coded as S=8) - * - PDU, CRC, TERM2 (coded as S=2 or S=8) - * (Vol 6, Part B, 2.2). - */ - [BLE_PHY_MODE_CODED_125KBPS] = - (80 + 256 + 16 + 24 + 8 * (BLE_LL_PDU_HDR_LEN * 8 + 24 + 3)), - [BLE_PHY_MODE_CODED_500KBPS] = - (80 + 256 + 16 + 24 + 2 * (BLE_LL_PDU_HDR_LEN * 8 + 24 + 3)), -}; - /** * Counts the number of advertising PDU's received, by type. For advertising * PDU's that contain a destination address, we still count these packets even @@ -526,36 +500,6 @@ ble_ll_rxpdu_alloc(uint16_t len) return NULL; } -int -ble_ll_chk_txrx_octets(uint16_t octets) -{ - int rc; - - if ((octets < BLE_LL_CONN_SUPP_BYTES_MIN) || - (octets > BLE_LL_CONN_SUPP_BYTES_MAX)) { - rc = 0; - } else { - rc = 1; - } - - return rc; -} - -int -ble_ll_chk_txrx_time(uint16_t time) -{ - int rc; - - if ((time < BLE_LL_CONN_SUPP_TIME_MIN) || - (time > BLE_LL_CONN_SUPP_TIME_MAX)) { - rc = 0; - } else { - rc = 1; - } - - return rc; -} - /** * Checks to see if the address is a resolvable private address. * @@ -850,6 +794,11 @@ ble_ll_wfr_timer_exp(void *arg) case BLE_LL_STATE_DTM: ble_ll_dtm_wfr_timer_exp(); break; +#endif +#if MYNEWT_VAL(BLE_LL_EXT) + case BLE_LL_STATE_EXTERNAL: + ble_ll_ext_wfr_timer_exp(); + break; #endif default: break; @@ -1025,6 +974,11 @@ ble_ll_rx_pkt_in(void) case BLE_LL_STATE_DTM: ble_ll_dtm_rx_pkt_in(m, ble_hdr); break; +#endif +#if MYNEWT_VAL(BLE_LL_EXT) + case BLE_LL_STATE_EXTERNAL: + ble_ll_ext_rx_pkt_in(m, ble_hdr); + break; #endif default: /* Any other state should never occur */ @@ -1050,7 +1004,7 @@ ble_ll_rx_pdu_in(struct os_mbuf *rxpdu) pkthdr = OS_MBUF_PKTHDR(rxpdu); STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_rx_pkt_q, pkthdr, omp_next); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_rx_pkt_ev); + ble_ll_event_add(&g_ble_ll_data.ll_rx_pkt_ev); } #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) @@ -1069,7 +1023,7 @@ ble_ll_acl_data_in(struct os_mbuf *txpkt) OS_ENTER_CRITICAL(sr); STAILQ_INSERT_TAIL(&g_ble_ll_data.ll_tx_pkt_q, pkthdr, omp_next); OS_EXIT_CRITICAL(sr); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_tx_pkt_ev); + ble_ll_event_add(&g_ble_ll_data.ll_tx_pkt_ev); } /** @@ -1082,7 +1036,7 @@ ble_ll_acl_data_in(struct os_mbuf *txpkt) void ble_ll_data_buffer_overflow(void) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_dbuf_overflow_ev); + ble_ll_event_add(&g_ble_ll_data.ll_dbuf_overflow_ev); } #endif @@ -1102,8 +1056,6 @@ ble_ll_hw_error(void) * * @param arg */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-function" static void ble_ll_hw_err_timer_cb(struct ble_npl_event *ev) { @@ -1117,7 +1069,6 @@ ble_ll_hw_err_timer_cb(struct ble_npl_event *ev) ble_npl_time_ms_to_ticks32(50)); } } -#pragma GCC diagnostic pop /** * Called upon start of received PDU @@ -1174,6 +1125,11 @@ ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr) case BLE_LL_STATE_DTM: rc = ble_ll_dtm_rx_isr_start(rxhdr, ble_phy_access_addr_get()); break; +#endif +#if MYNEWT_VAL(BLE_LL_EXT) + case BLE_LL_STATE_EXTERNAL: + rc = ble_ll_ext_rx_isr_start(pdu_type, rxhdr); + break; #endif default: /* Should not be in this state! */ @@ -1218,6 +1174,13 @@ ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) ble_ll_trace_u32x3(BLE_LL_TRACE_ID_RX_END, pdu_type, len, rxhdr->rxinfo.flags); +#if MYNEWT_VAL(BLE_LL_EXT) + if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_EXTERNAL) { + rc = ble_ll_ext_rx_isr_end(rxbuf, rxhdr); + return rc; + } +#endif + #if MYNEWT_VAL(BLE_LL_DTM) if (BLE_MBUF_HDR_RX_STATE(rxhdr) == BLE_LL_STATE_DTM) { rc = ble_ll_dtm_rx_isr_end(rxbuf, rxhdr); @@ -1403,8 +1366,10 @@ ble_ll_task(void *arg) /* Init ble phy */ ble_phy_init(); - /* Set output power to 1mW (0 dBm) */ - ble_phy_txpwr_set(g_ble_ll_tx_power); + /* Set output power to default */ + g_ble_ll_tx_power = ble_ll_tx_power_round(MIN(MYNEWT_VAL(BLE_LL_TX_PWR_DBM), + MYNEWT_VAL(BLE_LL_TX_PWR_MAX_DBM))); + g_ble_ll_tx_power_phy_current = INT8_MAX; /* Tell the host that we are ready to receive packets */ ble_ll_hci_send_noop(); @@ -1453,16 +1418,29 @@ ble_ll_state_get(void) /** * ble ll event send * - * Send an event to the Link Layer task + * Add an event to the Link Layer task * * @param ev Event to add to the Link Layer event queue. */ void -ble_ll_event_send(struct ble_npl_event *ev) +ble_ll_event_add(struct ble_npl_event *ev) { ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev); } +/** + * ble ll event remove + * + * Remove an event from the Link Layer task + * + * @param ev Event to remove from the Link Layer event queue. + */ +void +ble_ll_event_remove(struct ble_npl_event *ev) +{ + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, ev); +} + /** * Returns the features supported by the link layer * @@ -1493,7 +1471,7 @@ ble_ll_read_supp_features(void) int ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len) { - const struct ble_hci_le_set_host_feat_cp *cmd = (const void *) cmdbuf; + const struct ble_hci_le_set_host_feature_cp *cmd = (const void *) cmdbuf; uint64_t mask; if (len != sizeof(*cmd)) { @@ -1506,7 +1484,7 @@ ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len) } #endif - if ((cmd->bit_num > 0x3F) || (cmd->val > 1)) { + if ((cmd->bit_num > 0x3F) || (cmd->bit_val > 1)) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -1515,7 +1493,7 @@ ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_UNSUPPORTED; } - if (cmd->val == 0) { + if (cmd->bit_val == 0) { g_ble_ll_data.ll_supp_features &= ~(mask); } else { g_ble_ll_data.ll_supp_features |= mask; @@ -1618,6 +1596,10 @@ ble_ll_reset(void) ble_ll_rfmgmt_reset(); OS_EXIT_CRITICAL(sr); +#if MYNEWT_VAL(BLE_LL_EXT) + ble_ll_ext_reset(); +#endif + #if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) /* Stop any advertising */ ble_ll_adv_reset(); @@ -1632,6 +1614,15 @@ ble_ll_reset(void) ble_ll_sync_reset(); #endif + /* reset power compensation */ + g_ble_ll_tx_power_compensation = 0; + g_ble_ll_rx_power_compensation = 0; + + /* Set output power to default */ + g_ble_ll_tx_power = ble_ll_tx_power_round(MIN(MYNEWT_VAL(BLE_LL_TX_PWR_DBM), + MYNEWT_VAL(BLE_LL_TX_PWR_MAX_DBM))); + g_ble_ll_tx_power_phy_current = INT8_MAX; + /* FLush all packets from Link layer queues */ ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_tx_pkt_q); ble_ll_flush_pkt_queue(&g_ble_ll_data.ll_rx_pkt_q); @@ -1653,7 +1644,7 @@ ble_ll_reset(void) g_ble_ll_data.ll_pref_rx_phys = phy_mask; /* Enable all channels in channel map */ - g_ble_ll_data.chan_map_num_used = BLE_PHY_NUM_DATA_CHANS; + g_ble_ll_data.chan_map_used = BLE_PHY_NUM_DATA_CHANS; memset(g_ble_ll_data.chan_map, 0xff, BLE_LL_CHAN_MAP_LEN - 1); g_ble_ll_data.chan_map[4] = 0x1f; @@ -1683,11 +1674,18 @@ ble_ll_reset(void) #endif -#if MYNEWT_VAL(BLE_LL_PA) - ble_ll_plna_pa_init(); +#if MYNEWT_VAL(BLE_FEM_PA) + ble_fem_pa_init(); +#endif +#if MYNEWT_VAL(BLE_FEM_LNA) + ble_fem_lna_init(); +#endif + +#if MYNEWT_VAL(BLE_LL_ISO) + ble_ll_isoal_reset(); #endif -#if MYNEWT_VAL(BLE_LL_LNA) - ble_ll_plna_lna_init(); +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + ble_ll_iso_big_reset(); #endif /* Re-initialize the PHY */ @@ -1696,37 +1694,6 @@ ble_ll_reset(void) return rc; } -uint32_t -ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode) -{ - uint32_t usecs; - -#if (BLE_LL_BT5_PHY_SUPPORTED) - if (phy_mode == BLE_PHY_MODE_1M) { - /* 8 usecs per byte */ - usecs = payload_len << 3; - } else if (phy_mode == BLE_PHY_MODE_2M) { - /* 4 usecs per byte */ - usecs = payload_len << 2; - } else if (phy_mode == BLE_PHY_MODE_CODED_125KBPS) { - /* S=8 => 8 * 8 = 64 usecs per byte */ - usecs = payload_len << 6; - } else if (phy_mode == BLE_PHY_MODE_CODED_500KBPS) { - /* S=2 => 2 * 8 = 16 usecs per byte */ - usecs = payload_len << 4; - } else { - BLE_LL_ASSERT(0); - } - - usecs += g_ble_ll_pdu_header_tx_time[phy_mode]; -#else - usecs = (((payload_len) + BLE_LL_PDU_HDR_LEN + BLE_LL_ACC_ADDR_LEN - + BLE_LL_PREAMBLE_LEN + BLE_LL_CRC_LEN) << 3); -#endif - - return usecs; -} - uint16_t ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode) { @@ -1735,14 +1702,14 @@ ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode) BLE_LL_ASSERT(phy_mode < BLE_PHY_NUM_MODE); - header_tx_time = g_ble_ll_pdu_header_tx_time[phy_mode]; + header_tx_time = ble_ll_pdu_us(0, phy_mode); /* * Current conn max tx time can be too short to even send a packet header * and this can happen if we changed connection form uncoded to coded phy. * However, the lower bound for conn max tx time (all of them) depends on * current phy (uncoded/coded) but it always allows to send at least 27 - * bytes of payload thus we alwyas return at least 27 from here. + * bytes of payload thus we always return at least 27 from here. * * Reference: * Core v5.0, Vol 6, Part B, section 4.5.10 @@ -1772,7 +1739,7 @@ ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode) } /* see comment at the beginning */ - return max(27, octets); + return MAX(27, octets); } static inline bool @@ -1785,10 +1752,10 @@ ble_ll_is_addr_empty(const uint8_t *addr) void ble_ll_assert(const char *file, unsigned line) { + ble_ll_hci_ev_send_vs_assert(file, line); + if (hal_debugger_connected()) { __BKPT(0); - } else { - ble_ll_hci_ev_send_vs_assert(file, line); \ } while (1); @@ -1849,6 +1816,11 @@ ble_ll_init(void) lldata->ll_acl_pkt_size = MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE); #endif +#if MYNEWT_VAL(BLE_LL_ISO) + lldata->ll_num_iso_pkts = MYNEWT_VAL(BLE_TRANSPORT_ISO_FROM_HS_COUNT); + lldata->ll_iso_pkt_size = MYNEWT_VAL(BLE_TRANSPORT_ISO_SIZE); +#endif + /* Initialize eventq */ ble_npl_eventq_init(&lldata->ll_evq); @@ -1869,13 +1841,10 @@ ble_ll_init(void) #endif /* Initialize the HW error timer */ - /* NOT USED WITH RAM HCI - * Commented out to prevent creating an unnecessary timer ble_npl_callout_init(&g_ble_ll_data.ll_hw_err_timer, &g_ble_ll_data.ll_evq, ble_ll_hw_err_timer_cb, NULL); - */ /* Initialize LL HCI */ ble_ll_hci_init(); @@ -1959,8 +1928,11 @@ ble_ll_init(void) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) features |= BLE_LL_FEAT_CIS_CENTRAL; features |= BLE_LL_FEAT_CIS_PERIPH; + features |= BLE_LL_FEAT_CIS_HOST; +#endif + +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) features |= BLE_LL_FEAT_ISO_BROADCASTER; - features |= BLE_LL_FEAT_ISO_HOST_SUPPORT; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) @@ -1988,11 +1960,22 @@ ble_ll_init(void) ble_ll_hci_vs_init(); #endif -#if MYNEWT +#if MYNEWT_VAL(BLE_LL_ISO) + ble_ll_isoal_init(); +#endif +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + ble_ll_iso_big_init(); +#endif + +#if MYNEWT_VAL(BLE_LL_EXT) + ble_ll_ext_init(); +#endif + +#ifdef MYNEWT /* Initialize the LL task */ os_task_init(&g_ble_ll_task, "ble_ll", ble_ll_task, NULL, MYNEWT_VAL(BLE_LL_PRIO), OS_WAIT_FOREVER, g_ble_ll_stack, - BLE_LL_STACK_SIZE); + MYNEWT_VAL(BLE_LL_STACK_SIZE)); #else /* @@ -2008,13 +1991,19 @@ ble_ll_init(void) int ble_transport_to_ll_cmd_impl(void *buf) { - return ble_ll_hci_cmd_rx(buf, NULL); + return ble_ll_hci_cmd_rx(buf); } int ble_transport_to_ll_acl_impl(struct os_mbuf *om) { - return ble_ll_hci_acl_rx(om, NULL); + return ble_ll_hci_acl_rx(om); +} + +int +ble_transport_to_ll_iso_impl(struct os_mbuf *om) +{ + return ble_ll_hci_iso_rx(om); } void @@ -2023,4 +2012,95 @@ ble_transport_ll_init(void) ble_ll_init(); } +int +ble_ll_tx_power_round(int tx_power) +{ +#if MYNEWT_VAL(BLE_FEM_PA) +#if MYNEWT_VAL(BLE_FEM_PA_GAIN_TUNABLE) + tx_power = ble_fem_pa_tx_power_round(tx_power); +#else + tx_power = ble_phy_tx_power_round(tx_power); + tx_power += MYNEWT_VAL(BLE_FEM_PA_GAIN); +#endif +#else + tx_power = ble_phy_tx_power_round(tx_power); +#endif + + return tx_power; +} + +void +ble_ll_tx_power_set(int tx_power) +{ +#if MYNEWT_VAL(BLE_FEM_PA) +#if MYNEWT_VAL(BLE_FEM_PA_GAIN_TUNABLE) + /* TODO should rounding be in assert only? or just skip it and assume + * power is already rounded? + */ + tx_power = ble_fem_pa_tx_power_round(tx_power); + tx_power = ble_fem_pa_tx_power_set(tx_power); +#else + tx_power -= MYNEWT_VAL(BLE_FEM_PA_GAIN); +#endif +#endif + + /* If current TX power configuration matches requested one we don't need + * to update PHY tx power. + */ + if (g_ble_ll_tx_power_phy_current == tx_power) { + return; + } + + g_ble_ll_tx_power_phy_current = tx_power; + ble_phy_tx_power_set(tx_power); +} + +int +ble_ll_is_busy(unsigned int flags) +{ +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + struct ble_ll_conn_sm *cur; + int i = 0; +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + if (ble_ll_sync_enabled()) { + return 1; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + if (ble_ll_adv_enabled()) { + return 1; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + if (ble_ll_scan_enabled()) { + return 1; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + if (g_ble_ll_conn_create_sm.connsm) { + return 1; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + if (!(flags & BLE_LL_BUSY_EXCLUDE_CONNECTIONS)) { + STAILQ_FOREACH(cur, &g_ble_ll_conn_free_list, free_stqe) { + i++; + } + + /* check if all connection objects are free */ + if (i < MYNEWT_VAL(BLE_MAX_CONNECTIONS)) { + return 1; + } + } #endif + + return 0; +} + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_adv.c b/src/nimble/nimble/controller/src/ble_ll_adv.c index a1bb2b6f..d3ba63eb 100644 --- a/src/nimble/nimble/controller/src/ble_ll_adv.c +++ b/src/nimble/nimble/controller/src/ble_ll_adv.c @@ -16,51 +16,40 @@ * specific language governing permissions and limitations * under the License. */ + #ifndef ESP_PLATFORM +#include #include #include #include #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os.h" - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) #include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" -#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) -#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" -#endif - #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" #include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_tmr.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_ll_utils.h" -#include "../include/controller/ble_ll_rfmgmt.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_pdu.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_adv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_ll_whitelist.h" +#include "nimble/nimble/controller/include/controller/ble_ll_resolv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_ll_trace.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h" +#include "nimble/nimble/controller/include/controller/ble_ll_iso_big.h" #include "ble_ll_conn_priv.h" #include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(array) \ - (sizeof(array) / sizeof((array)[0])) -#endif - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - /* XXX: TODO * 1) Need to look at advertising and scan request PDUs. Do I allocate these * once? Do I use a different pool for smaller ones? Do I statically declare @@ -75,22 +64,27 @@ struct ble_ll_adv_aux { struct ble_ll_sched_item sch; uint32_t start_time; - uint16_t aux_data_offset; + uint16_t data_offset; uint8_t chan; - uint8_t ext_hdr; - uint8_t aux_data_len; + uint8_t ext_hdr_flags; + uint8_t data_len; uint8_t payload_len; + uint8_t auxptr_zero; }; /* Scheduling data for sync PDUs */ struct ble_ll_adv_sync { struct ble_ll_sched_item sch; uint32_t start_time; - uint16_t sync_data_offset; + uint16_t data_offset; uint8_t chan; - uint8_t ext_hdr; - uint8_t sync_data_len; + uint8_t ext_hdr_flags; + uint8_t data_len; uint8_t payload_len; + uint8_t auxptr_zero; +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + struct ble_ll_iso_big *big; +#endif }; /* @@ -120,11 +114,9 @@ struct ble_ll_adv_sm uint8_t adv_chan; uint8_t adv_pdu_len; int8_t adv_rpa_index; - int8_t adv_txpwr; + int8_t tx_power; uint16_t flags; uint16_t props; - uint16_t adv_itvl_min; - uint16_t adv_itvl_max; uint32_t adv_itvl_usecs; uint32_t adv_event_start_time; uint32_t adv_pdu_start_time; @@ -190,6 +182,11 @@ struct ble_ll_adv_sm uint16_t periodic_event_cntr_last_sent; #endif #endif + +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + struct ble_ll_iso_big *big; +#endif /* BLE_LL_ISO_BROADCASTER */ + #endif }; @@ -207,21 +204,26 @@ struct ble_ll_adv_sm #define BLE_LL_ADV_SM_FLAG_PERIODIC_DATA_INCOMPLETE 0x1000 #define BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING 0x2000 #define BLE_LL_ADV_SM_FLAG_PERIODIC_NEW_DATA 0x4000 +#define BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD_ERR 0x8000 #define ADV_DATA_LEN(_advsm) \ - ((_advsm->adv_data) ? OS_MBUF_PKTLEN(advsm->adv_data) : 0) + (((_advsm)->adv_data) ? OS_MBUF_PKTLEN((_advsm)->adv_data) : 0) #define SCAN_RSP_DATA_LEN(_advsm) \ - ((_advsm->scan_rsp_data) ? OS_MBUF_PKTLEN(advsm->scan_rsp_data) : 0) -#define AUX_DATA_LEN(_advsm) \ - (*(_advsm->aux_data) ? OS_MBUF_PKTLEN(*advsm->aux_data) : 0) + (((_advsm)->scan_rsp_data) ? OS_MBUF_PKTLEN((_advsm)->scan_rsp_data) : 0) -#define AUX_CURRENT(_advsm) (&(_advsm->aux[_advsm->aux_index])) -#define AUX_NEXT(_advsm) (&(_advsm->aux[_advsm->aux_index ^ 1])) +#define AUX_CURRENT(_advsm) \ + (&((_advsm)->aux[(_advsm)->aux_index])) +#define AUX_NEXT(_advsm) \ + (&((_advsm)->aux[(_advsm)->aux_index ^ 1])) +#define AUX_DATA_LEN(_advsm) \ + (*((_advsm)->aux_data) ? OS_MBUF_PKTLEN(*(_advsm)->aux_data) : 0) -#define SYNC_CURRENT(_advsm) (&(_advsm->periodic_sync[_advsm->periodic_sync_index])) -#define SYNC_NEXT(_advsm) (&(_advsm->periodic_sync[_advsm->periodic_sync_index ^ 1])) +#define SYNC_CURRENT(_advsm) \ + (&((_advsm)->periodic_sync[(_advsm)->periodic_sync_index])) +#define SYNC_NEXT(_advsm) \ + (&((_advsm)->periodic_sync[(_advsm)->periodic_sync_index ^ 1])) #define SYNC_DATA_LEN(_advsm) \ - (_advsm->periodic_adv_data ? OS_MBUF_PKTLEN(advsm->periodic_adv_data) : 0) + ((_advsm)->periodic_adv_data ? OS_MBUF_PKTLEN((_advsm)->periodic_adv_data) : 0) /* The advertising state machine global object */ struct ble_ll_adv_sm g_ble_ll_adv_sm[BLE_ADV_INSTANCES]; @@ -233,7 +235,7 @@ static struct ble_ll_adv_sm * ble_ll_adv_sm_find_configured(uint8_t instance) { struct ble_ll_adv_sm *advsm; - int i; + unsigned int i; /* in legacy mode we only allow instance 0 */ if (!ble_ll_hci_adv_mode_ext()) { @@ -746,17 +748,17 @@ ble_ll_adv_aux_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) adv_mode |= BLE_LL_EXT_ADV_MODE_CONN; } - ext_hdr_len = aux->payload_len - BLE_LL_EXT_ADV_HDR_LEN - aux->aux_data_len; + ext_hdr_len = aux->payload_len - BLE_LL_EXT_ADV_HDR_LEN - aux->data_len; dptr[0] = (adv_mode << 6) | ext_hdr_len; dptr += 1; /* only put flags if needed */ - if (aux->ext_hdr) { - dptr[0] = aux->ext_hdr; + if (aux->ext_hdr_flags) { + dptr[0] = aux->ext_hdr_flags; dptr += 1; } - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { + if (aux->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_ADVA_BIT)) { /* Set TxAdd to random if needed. */ if (advsm->flags & BLE_LL_ADV_SM_FLAG_TX_ADD) { @@ -767,7 +769,7 @@ ble_ll_adv_aux_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) dptr += BLE_LL_EXT_ADV_ADVA_SIZE; } - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { + if (aux->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TARGETA_BIT)) { memcpy(dptr, advsm->initiator_addr, BLE_LL_EXT_ADV_TARGETA_SIZE); dptr += BLE_LL_EXT_ADV_TARGETA_SIZE; @@ -777,13 +779,13 @@ ble_ll_adv_aux_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) } } - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { + if (aux->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT)) { dptr[0] = advsm->adi & 0x00ff; dptr[1] = advsm->adi >> 8; dptr += BLE_LL_EXT_ADV_DATA_INFO_SIZE; } - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + if (aux->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { if (!AUX_NEXT(advsm)->sch.enqueued) { /* * Trim data here in case we do not have next aux scheduled. This @@ -793,11 +795,13 @@ ble_ll_adv_aux_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) offset = 0; } else if (advsm->rx_ble_hdr) { offset = ble_ll_tmr_t2u(AUX_NEXT(advsm)->start_time - advsm->rx_ble_hdr->beg_cputime); - offset -= (advsm->rx_ble_hdr->rem_usecs + ble_ll_pdu_tx_time_get(12, advsm->sec_phy) + BLE_LL_IFS); + offset -= (advsm->rx_ble_hdr->rem_usecs + ble_ll_pdu_us(12, advsm->sec_phy) + BLE_LL_IFS); } else { offset = ble_ll_tmr_t2u(AUX_NEXT(advsm)->start_time - aux->start_time); } + aux->auxptr_zero = offset == 0; + ble_ll_adv_put_aux_ptr(AUX_NEXT(advsm)->chan, advsm->sec_phy, offset, dptr); @@ -805,20 +809,20 @@ ble_ll_adv_aux_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { + if (aux->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT)) { ble_ll_adv_put_syncinfo(advsm, NULL, NULL, dptr); dptr += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; } #endif - if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { - dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation(); + if (aux->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { + dptr[0] = advsm->tx_power + g_ble_ll_tx_power_compensation; dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; } - if (aux->aux_data_len) { - os_mbuf_copydata(*advsm->aux_data, aux->aux_data_offset, - aux->aux_data_len, dptr); + if (aux->data_len) { + os_mbuf_copydata(*advsm->aux_data, aux->data_offset, + aux->data_len, dptr); } *hdr_byte = pdu_type; @@ -889,7 +893,7 @@ ble_ll_adv_aux_scannable_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_b if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) { *ext_hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; *ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); - dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation(); + dptr[0] = advsm->tx_power + g_ble_ll_tx_power_compensation; dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; } @@ -1039,9 +1043,6 @@ ble_ll_adv_tx_done(void *arg) { struct ble_ll_adv_sm *advsm; - /* reset power to max after advertising */ - ble_phy_txpwr_set(g_ble_ll_tx_power); - advsm = (struct ble_ll_adv_sm *)arg; ble_ll_trace_u32x2(BLE_LL_TRACE_ID_ADV_TXDONE, advsm->adv_instance, @@ -1049,14 +1050,14 @@ ble_ll_adv_tx_done(void *arg) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (ble_ll_adv_active_chanset_is_pri(advsm)) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + ble_ll_event_add(&advsm->adv_txdone_ev); } else if (ble_ll_adv_active_chanset_is_sec(advsm)) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); + ble_ll_event_add(&advsm->adv_sec_txdone_ev); } else { BLE_LL_ASSERT(0); } #else - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + ble_ll_event_add(&advsm->adv_txdone_ev); #endif ble_ll_state_set(BLE_LL_STATE_STANDBY); @@ -1085,7 +1086,7 @@ ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm) void ble_ll_adv_periodic_rmvd_from_sched(struct ble_ll_adv_sm *advsm) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_periodic_txdone_ev); + ble_ll_event_add(&advsm->adv_periodic_txdone_ev); } #endif @@ -1120,9 +1121,6 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) goto adv_tx_done; } - /* Set the power */ - ble_phy_txpwr_set(advsm->adv_txpwr); - /* Set channel */ rc = ble_phy_setchan(advsm->adv_chan, BLE_ACCESS_ADDR_ADV, BLE_LL_CRCINIT_ADV); BLE_LL_ASSERT(rc == 0); @@ -1140,6 +1138,9 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch) #endif #endif + /* Set the power */ + ble_ll_tx_power_set(advsm->tx_power); + /* Set transmit start time. */ txstart = sch->start_time + g_ble_ll_sched_offset_ticks; rc = ble_phy_tx_set_start_time(txstart, sch->remainder); @@ -1216,7 +1217,7 @@ ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm) /* Set end time to maximum time this schedule item may take */ #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) { - max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); + max_usecs = ble_ll_pdu_us(advsm->adv_pdu_len, BLE_PHY_MODE_1M); if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS; @@ -1228,10 +1229,10 @@ ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm) * In ADV_EXT_IND we always set only ADI and AUX so the payload length * is always 7 bytes. */ - max_usecs = ble_ll_pdu_tx_time_get(7, advsm->pri_phy); + max_usecs = ble_ll_pdu_us(7, advsm->pri_phy); } #else - max_usecs = ble_ll_pdu_tx_time_get(advsm->adv_pdu_len, BLE_PHY_MODE_1M); + max_usecs = ble_ll_pdu_us(advsm->adv_pdu_len, BLE_PHY_MODE_1M); if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) { max_usecs += BLE_LL_SCHED_DIRECT_ADV_MAX_USECS; @@ -1264,9 +1265,6 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) ble_ll_adv_active_chanset_set_sec(advsm); - /* Set the power */ - ble_phy_txpwr_set(advsm->adv_txpwr); - /* Set channel */ aux = AUX_CURRENT(advsm); rc = ble_phy_setchan(aux->chan, BLE_ACCESS_ADDR_ADV, @@ -1278,6 +1276,9 @@ ble_ll_adv_secondary_tx_start_cb(struct ble_ll_sched_item *sch) ble_phy_mode_set(advsm->sec_phy, advsm->sec_phy); #endif + /* Set the power */ + ble_ll_tx_power_set(advsm->tx_power); + /* Set transmit start time. */ txstart = sch->start_time + g_ble_ll_sched_offset_ticks; rc = ble_phy_tx_set_start_time(txstart, sch->remainder); @@ -1369,117 +1370,173 @@ ble_ll_adv_aux_scannable_pdu_payload_len(struct ble_ll_adv_sm *advsm) return len; } -static void -ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm, - struct ble_ll_adv_aux *aux, uint16_t aux_data_offset) +static uint16_t +ble_ll_adv_aux_calculate_payload(struct ble_ll_adv_sm *advsm, uint16_t props, + struct os_mbuf *data, uint32_t data_offset, + uint8_t *data_len_o, uint8_t *ext_hdr_flags_o) { - uint16_t rem_aux_data_len; - uint8_t hdr_len; + uint16_t rem_data_len; + uint8_t data_len; + uint8_t ext_hdr_flags; + uint8_t ext_hdr_len; bool chainable; + bool first_pdu; - BLE_LL_ASSERT(!aux->sch.enqueued); - BLE_LL_ASSERT((AUX_DATA_LEN(advsm) > aux_data_offset) || - (AUX_DATA_LEN(advsm) == 0 && aux_data_offset == 0)); + /* Note: advsm shall only be used to check if periodic advertising is + * enabled, other parameters in advsm may have different values than + * those we want to check (e.g. when reconfiguring instance). + */ - aux->aux_data_offset = aux_data_offset; - aux->aux_data_len = 0; - aux->payload_len = 0; - aux->ext_hdr = 0; + rem_data_len = (data ? OS_MBUF_PKTLEN(data) : 0) - data_offset; + BLE_LL_ASSERT((int16_t)rem_data_len >= 0); -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - aux->chan = ble_ll_utils_dci_csa2(advsm->event_cntr++, - advsm->channel_id, - g_ble_ll_data.chan_map_num_used, - g_ble_ll_data.chan_map); -#else - aux->chan = ble_ll_utils_remapped_channel(ble_ll_rand() % BLE_PHY_NUM_DATA_CHANS, - g_ble_ll_conn_params.central_chan_map); -#endif + first_pdu = (data_offset == 0); + chainable = !(props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE); - rem_aux_data_len = AUX_DATA_LEN(advsm) - aux_data_offset; - chainable = !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE); + ext_hdr_flags = 0; + ext_hdr_len = BLE_LL_EXT_ADV_HDR_LEN; - hdr_len = BLE_LL_EXT_ADV_HDR_LEN; - - if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { - /* ADI */ - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT); - hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE; + /* ADI for anything but scannable */ + if (!(props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_DATA_INFO_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_DATA_INFO_SIZE; } - /* AdvA for 1st PDU in chain (i.e. AUX_ADV_IND or AUX_SCAN_RSP) */ - if (aux_data_offset == 0 && - !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_ADVA_BIT); - hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE; + /* AdvA in 1st PDU, except for anonymous */ + if (first_pdu && + !(props & BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV)) { + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_ADVA_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_ADVA_SIZE; } - /* Note: this function does not calculate AUX_ADV_IND when advertising is - * scannable. Instead it is calculated in ble_ll_adv_aux_schedule_first(). - * - * However this function calculates length of AUX_SCAN_RSP and according - * to BT 5.0 Vol 6 Part B, 2.3.2.3, TargetA shall not be include there. + /* TargetA in 1st PDU, if directed * - * This is why TargetA is added to all directed advertising here unless it - * is scannable one. - * - * Note. TargetA shall not be also in AUX_CHAIN_IND + * Note that for scannable this calculates AUX_SCAN_RSP which shall not + * include TargetA (see: Core 5.3, Vol 6, Part B, 2.3.2.3). For scannable + * TargetA is included in AUX_ADV_IND which is in that case calculated in + * ble_ll_adv_aux_schedule_first(). */ - if (aux_data_offset == 0 && - (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) && - !(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT); - hdr_len += BLE_LL_EXT_ADV_TARGETA_SIZE; + if (first_pdu && + (props & BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED) && + !(props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE)) { + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_TARGETA_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_TARGETA_SIZE; } - /* TxPower if configured. - * Note: TxPower should not be be present in AUX_CHAIN_IND - */ - if (aux_data_offset == 0 && - (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR)) { - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); - hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; + /* TxPower in 1st PDU, if configured */ + if (first_pdu && + (props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR)) { + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) - /* SyncInfo for 1st PDU in chain (i.e. AUX_ADV_IND only) if periodic - * advertising is enabled - */ - if (aux_data_offset == 0 && advsm->periodic_adv_active) { - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT); - hdr_len += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; + /* SyncInfo in 1st PDU, if periodic advertising is enabled */ + if (first_pdu && advsm->periodic_adv_active) { + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_SYNC_INFO_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_SYNC_INFO_SIZE; } #endif - /* if we have any fields in ext header we need to add flags, note that Aux - * PTR is handled later and it will account for flags if needed + /* Flags, if any field is present in header + * + * Note that this does not account for AuxPtr which is added later if + * remaining data does not fit in single PDU. */ - if (aux->ext_hdr) { - hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + if (ext_hdr_flags) { + ext_hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; } - /* AdvData always */ - aux->aux_data_len = min(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_aux_data_len); + /* AdvData */ + data_len = MIN(BLE_LL_MAX_PAYLOAD_LEN - ext_hdr_len, rem_data_len); /* AuxPtr if there are more AdvData remaining that we can fit here */ - if (chainable && (rem_aux_data_len > aux->aux_data_len)) { - /* adjust for flags that needs to be added if AuxPtr is only field - * in Extended Header - */ - if (!aux->ext_hdr) { - hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; - aux->aux_data_len -= BLE_LL_EXT_ADV_FLAGS_SIZE; - } + if (chainable && (rem_data_len > data_len)) { + /* Add flags if not already added */ + if (!ext_hdr_flags) { + ext_hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + data_len -= BLE_LL_EXT_ADV_FLAGS_SIZE; + } - aux->ext_hdr |= (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); - hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - aux->aux_data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE; + ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - /* PDU payload should be full if chained */ - BLE_LL_ASSERT(hdr_len + aux->aux_data_len == BLE_LL_MAX_PAYLOAD_LEN); + data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE; + + /* PDU payload should be full if adding AuxPtr */ + BLE_LL_ASSERT(ext_hdr_len + data_len == BLE_LL_MAX_PAYLOAD_LEN); } - aux->payload_len = hdr_len + aux->aux_data_len; + *data_len_o = data_len; + *ext_hdr_flags_o = ext_hdr_flags; + + return ext_hdr_len + data_len; +} + +static void +ble_ll_adv_aux_calculate(struct ble_ll_adv_sm *advsm, + struct ble_ll_adv_aux *aux, uint16_t data_offset) +{ + BLE_LL_ASSERT(!aux->sch.enqueued); + BLE_LL_ASSERT((AUX_DATA_LEN(advsm) > data_offset) || + (AUX_DATA_LEN(advsm) == 0 && data_offset == 0)); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) + aux->chan = ble_ll_utils_dci_csa2(advsm->event_cntr++, + advsm->channel_id, + g_ble_ll_data.chan_map_used, + g_ble_ll_data.chan_map); +#else + aux->chan = ble_ll_utils_remapped_channel(ble_ll_rand() % BLE_PHY_NUM_DATA_CHANS, + g_ble_ll_data.chan_map); +#endif + + aux->data_offset = data_offset; + aux->payload_len = ble_ll_adv_aux_calculate_payload(advsm, advsm->props, + *advsm->aux_data, + data_offset, + &aux->data_len, + &aux->ext_hdr_flags); +} + +static bool +ble_ll_adv_aux_check_data_itvl(struct ble_ll_adv_sm *advsm, uint16_t props, + uint8_t pri_phy, uint8_t sec_phy, + struct os_mbuf *data, uint32_t interval_us) +{ + uint32_t max_usecs; + uint16_t data_offset; + uint16_t pdu_len; + uint8_t data_len; + uint8_t ext_hdr_flags; + + /* FIXME: + * We should include PDUs on primary channel when calculating advertising + * event duration, but the actual time varies a bit in our case due to + * scheduling. For now let's assume we always schedule all PDUs 300us apart + * and we use shortest possible payload (ADI+AuxPtr, no AdvA). + * + * Note that calculations below do not take channel map and max skip into + * account, but we do not support max skip anyway for now. + */ + + max_usecs = 3 * (ble_ll_pdu_us(7, pri_phy) + 300) + + BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_MAFS_DELAY); + + data_offset = 0; + + do { + pdu_len = ble_ll_adv_aux_calculate_payload(advsm, props, data, data_offset, + &data_len, &ext_hdr_flags); + + max_usecs += ble_ll_pdu_us(pdu_len, sec_phy); + max_usecs += BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY); + + data_offset += data_len; + + } while (ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)); + + return max_usecs < interval_us; } static void @@ -1497,8 +1554,8 @@ ble_ll_adv_aux_schedule_next(struct ble_ll_adv_sm *advsm) struct ble_ll_adv_aux *aux; struct ble_ll_adv_aux *aux_next; struct ble_ll_sched_item *sch; - uint16_t rem_aux_data_len; - uint16_t next_aux_data_offset; + uint16_t rem_data_len; + uint16_t next_data_offset; uint32_t max_usecs; BLE_LL_ASSERT(advsm->aux_active); @@ -1520,19 +1577,19 @@ ble_ll_adv_aux_schedule_next(struct ble_ll_adv_sm *advsm) * Do not schedule next aux if current aux does not have AuxPtr in extended * header as this means we do not need subsequent ADV_CHAIN_IND to be sent. */ - if (!(aux->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT))) { + if (!(aux->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT))) { return; } - next_aux_data_offset = aux->aux_data_offset + aux->aux_data_len; + next_data_offset = aux->data_offset + aux->data_len; - BLE_LL_ASSERT(AUX_DATA_LEN(advsm) >= next_aux_data_offset); + BLE_LL_ASSERT(AUX_DATA_LEN(advsm) >= next_data_offset); - rem_aux_data_len = AUX_DATA_LEN(advsm) - next_aux_data_offset; - BLE_LL_ASSERT(rem_aux_data_len > 0); + rem_data_len = AUX_DATA_LEN(advsm) - next_data_offset; + BLE_LL_ASSERT(rem_data_len > 0); - ble_ll_adv_aux_calculate(advsm, aux_next, next_aux_data_offset); - max_usecs = ble_ll_pdu_tx_time_get(aux_next->payload_len, advsm->sec_phy); + ble_ll_adv_aux_calculate(advsm, aux_next, next_data_offset); + max_usecs = ble_ll_pdu_us(aux_next->payload_len, advsm->sec_phy); aux_next->start_time = aux->sch.end_time + ble_ll_tmr_u2t_up(BLE_LL_MAFS + @@ -1544,13 +1601,12 @@ ble_ll_adv_aux_schedule_next(struct ble_ll_adv_sm *advsm) sch->end_time = aux_next->start_time + ble_ll_tmr_u2t_up(max_usecs); ble_ll_sched_adv_new(&aux_next->sch, ble_ll_adv_aux_scheduled, aux_next); - /* - * In case duration is set for advertising set we need to check if newly - * scheduled aux will fit inside duration. If not, remove it from scheduler - * so advertising will stop after current aux. + /* Remove aux if previous one was already sent with zero offset or new one + * is scheduled past advertising duration (if set). */ - if (advsm->duration && - LL_TMR_GT(aux_next->sch.end_time, advsm->adv_end_time)) { + if (aux->auxptr_zero || + (advsm->duration && LL_TMR_GT(aux_next->sch.end_time, + advsm->adv_end_time))) { ble_ll_sched_rmv_elem(&aux_next->sch); } } @@ -1573,17 +1629,18 @@ ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm) advsm->aux_dropped = 0; aux = AUX_CURRENT(advsm); + aux->auxptr_zero = 0; ble_ll_adv_aux_calculate(advsm, aux, 0); /* Set end time to maximum time this schedule item may take */ if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE) { - max_usecs = ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy) + + max_usecs = ble_ll_pdu_us(aux->payload_len, advsm->sec_phy) + BLE_LL_IFS + /* AUX_CONN_REQ */ - ble_ll_pdu_tx_time_get(34 + 14, advsm->sec_phy) + + ble_ll_pdu_us(34 + 14, advsm->sec_phy) + BLE_LL_IFS + /* AUX_CONN_RSP */ - ble_ll_pdu_tx_time_get(14, advsm->sec_phy); + ble_ll_pdu_us(14, advsm->sec_phy); } else if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE) { /* For scannable advertising we need to calculate how much time we * need for AUX_ADV_IND along with AUX_SCAN_REQ, AUX_SCAN_RSP and @@ -1595,16 +1652,16 @@ ble_ll_adv_aux_schedule_first(struct ble_ll_adv_sm *advsm) * 2. length of AUX_ADV_IND is calculated by special function: * ble_ll_adv_aux_scannable_pdu_payload_len() */ - max_usecs = ble_ll_pdu_tx_time_get(ble_ll_adv_aux_scannable_pdu_payload_len(advsm), + max_usecs = ble_ll_pdu_us(ble_ll_adv_aux_scannable_pdu_payload_len(advsm), advsm->sec_phy) + BLE_LL_IFS + /* AUX_SCAN_REQ */ - ble_ll_pdu_tx_time_get(12, advsm->sec_phy) + + ble_ll_pdu_us(12, advsm->sec_phy) + BLE_LL_IFS + /* AUX_SCAN_RSP */ - ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy); + ble_ll_pdu_us(aux->payload_len, advsm->sec_phy); } else { - max_usecs = ble_ll_pdu_tx_time_get(aux->payload_len, advsm->sec_phy); + max_usecs = ble_ll_pdu_us(aux->payload_len, advsm->sec_phy); } sch = &aux->sch; @@ -1632,28 +1689,18 @@ ble_ll_adv_aux_set_start_time(struct ble_ll_adv_sm *advsm) chans = bits[advsm->adv_chanmask]; - /* - * We want to schedule auxiliary packet as soon as possible after the end - * of advertising event, but no sooner than T_MAFS. The interval between - * advertising packets is 250 usecs (8.19 ticks) on LE Coded and a bit less - * on 1M, but it can vary a bit due to scheduling which we can't really - * control. Since we round ticks up for both interval and T_MAFS, we still - * have some margin here. The worst thing that can happen is that we skip - * last advertising packet which is not a bit problem so leave it as-is, no - * need to make code more complicated. - */ - - /* - * XXX: this could be improved if phy has TX-TX transition with controlled - * or predefined interval, but since it makes advertising code even - * more complicated let's skip it for now... - */ - adv_pdu_dur = (int32_t)(sched->end_time - sched->start_time) - g_ble_ll_sched_offset_ticks; - /* 9 is 8.19 ticks rounded up - see comment above */ - adv_event_dur = (adv_pdu_dur * chans) + (9 * (chans - 1)); + /* The interval between advertising PDUs may vary due to scheduling, but in + * general we reserve 3 ticks for end-to-schedule time and add scheduler + * offset. That should be more that enough to make sure there's at least + * T_mafs delay between last advertising PDU and auxiliary PDU. + * + * TODO we can make this much more efficient with TX-TX transition + */ + adv_event_dur = (adv_pdu_dur * chans) + + ((3 + g_ble_ll_sched_offset_ticks) * (chans - 1)); advsm->aux[0].start_time = advsm->adv_event_start_time + adv_event_dur + ble_ll_tmr_u2t_up(BLE_LL_MAFS + @@ -1704,24 +1751,21 @@ ble_ll_adv_halt(void) ble_ll_trace_u32(BLE_LL_TRACE_ID_ADV_HALT, advsm->adv_instance); - ble_phy_txpwr_set(g_ble_ll_tx_power); - #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) if (advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING) { ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, - &advsm->adv_periodic_txdone_ev); + ble_ll_event_add(&advsm->adv_periodic_txdone_ev); ble_ll_state_set(BLE_LL_STATE_STANDBY); g_ble_ll_cur_adv_sm = NULL; return; } #endif - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + ble_ll_event_add(&advsm->adv_txdone_ev); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY)) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); + ble_ll_event_add(&advsm->adv_sec_txdone_ev); } #endif @@ -1751,6 +1795,7 @@ ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len) uint8_t adv_filter_policy; uint16_t adv_itvl_min; uint16_t adv_itvl_max; + uint32_t adv_itvl_usecs; uint16_t props; if (len != sizeof(*cmd)) { @@ -1822,7 +1867,7 @@ ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } - advsm->adv_txpwr = g_ble_ll_tx_power; + advsm->tx_power = ble_ll_tx_power_round(g_ble_ll_tx_power - g_ble_ll_tx_power_compensation); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) if (cmd->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) { @@ -1846,13 +1891,20 @@ ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } + /* Determine the advertising interval we will use */ + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + /* Set it to max. allowed for high duty cycle advertising */ + adv_itvl_usecs = BLE_LL_ADV_PDU_ITVL_HD_MS_MAX; + } else { + adv_itvl_usecs = adv_itvl_max * BLE_LL_ADV_ITVL; + } + /* Fill out rest of advertising state machine */ advsm->own_addr_type = cmd->own_addr_type; advsm->peer_addr_type = cmd->peer_addr_type; advsm->adv_filter_policy = adv_filter_policy; advsm->adv_chanmask = cmd->chan_map; - advsm->adv_itvl_min = adv_itvl_min; - advsm->adv_itvl_max = adv_itvl_max; + advsm->adv_itvl_usecs = adv_itvl_usecs; advsm->props = props; return 0; @@ -1955,9 +2007,9 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm) #endif OS_EXIT_CRITICAL(sr); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + ble_ll_event_remove(&advsm->adv_txdone_ev); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); + ble_ll_event_remove(&advsm->adv_sec_txdone_ev); #endif #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) @@ -2068,6 +2120,9 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) uint8_t adv_mode; uint8_t pdu_type; uint8_t ext_hdr_len; +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + uint8_t biginfo_len; +#endif uint32_t offset; advsm = pducb_arg; @@ -2082,17 +2137,24 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) /* non-connectable and non-scannable */ adv_mode = 0; - ext_hdr_len = sync->payload_len - BLE_LL_EXT_ADV_HDR_LEN - sync->sync_data_len; + ext_hdr_len = sync->payload_len - BLE_LL_EXT_ADV_HDR_LEN - sync->data_len; dptr[0] = (adv_mode << 6) | ext_hdr_len; dptr += 1; /* only put flags if needed */ - if (sync->ext_hdr) { - dptr[0] = sync->ext_hdr; +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + if (sync->ext_hdr_flags || sync->big) { + dptr[0] = sync->ext_hdr_flags; dptr += 1; } +#else + if (sync->ext_hdr_flags) { + dptr[0] = sync->ext_hdr_flags; + dptr += 1; + } +#endif - if (sync->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { + if (sync->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT)) { if (!SYNC_NEXT(advsm)->sch.enqueued) { /* * Trim data here in case we do not have next sync scheduled. This @@ -2105,20 +2167,34 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) sync->start_time); } + sync->auxptr_zero = offset == 0; + ble_ll_adv_put_aux_ptr(SYNC_NEXT(advsm)->chan, advsm->sec_phy, offset, dptr); dptr += BLE_LL_EXT_ADV_AUX_PTR_SIZE; } - if (sync->ext_hdr & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { - dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation(); + if (sync->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) { + dptr[0] = advsm->tx_power + g_ble_ll_tx_power_compensation; dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE; } - if (sync->sync_data_len) { - os_mbuf_copydata(advsm->periodic_adv_data, sync->sync_data_offset, - sync->sync_data_len, dptr); +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + if (advsm->big) { + biginfo_len = ble_ll_iso_big_biginfo_copy(advsm->big, dptr, + sync->sch.start_time + + g_ble_ll_sched_offset_ticks, + sync->sch.remainder); + BLE_LL_ASSERT(biginfo_len > 0); + + dptr += biginfo_len; + } +#endif + + if (sync->data_len) { + os_mbuf_copydata(advsm->periodic_adv_data, sync->data_offset, + sync->data_len, dptr); } *hdr_byte = pdu_type; @@ -2130,16 +2206,13 @@ ble_ll_adv_sync_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte) static void ble_ll_adv_sync_tx_done(struct ble_ll_adv_sm *advsm) { - /* reset power to default after advertising */ - ble_phy_txpwr_set(g_ble_ll_tx_power); - /* for sync we trace a no pri nor sec set */ ble_ll_trace_u32x2(BLE_LL_TRACE_ID_ADV_TXDONE, advsm->adv_instance, 0); BLE_LL_ASSERT(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); BLE_LL_ASSERT(!ble_ll_adv_active_chanset_is_sec(advsm)); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_periodic_txdone_ev); + ble_ll_event_add(&advsm->adv_periodic_txdone_ev); ble_ll_state_set(BLE_LL_STATE_STANDBY); ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); @@ -2186,9 +2259,6 @@ ble_ll_adv_sync_tx_start_cb(struct ble_ll_sched_item *sch) ble_ll_adv_active_chanset_clear(advsm); ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); - /* Set the power */ - ble_phy_txpwr_set(advsm->adv_txpwr); - /* Set channel */ sync = SYNC_CURRENT(advsm); rc = ble_phy_setchan(sync->chan, advsm->periodic_access_addr, @@ -2201,6 +2271,9 @@ ble_ll_adv_sync_tx_start_cb(struct ble_ll_sched_item *sch) ble_phy_mode_set(advsm->sec_phy, advsm->sec_phy); #endif + /* Set the power */ + ble_ll_tx_power_set(advsm->tx_power); + /* Set transmit start time. */ txstart = sch->start_time + g_ble_ll_sched_offset_ticks; rc = ble_phy_tx_set_start_time(txstart, sch->remainder); @@ -2242,34 +2315,33 @@ ble_ll_adv_sync_tx_start_cb(struct ble_ll_sched_item *sch) static void ble_ll_adv_sync_calculate(struct ble_ll_adv_sm *advsm, - struct ble_ll_adv_sync *sync, - uint16_t sync_data_offset, + struct ble_ll_adv_sync *sync, uint16_t data_offset, uint8_t chan) { - uint16_t rem_sync_data_len; - uint8_t hdr_len; + uint16_t rem_data_len; + uint8_t ext_hdr_len; BLE_LL_ASSERT(!sync->sch.enqueued); - BLE_LL_ASSERT((SYNC_DATA_LEN(advsm) > sync_data_offset) || - (SYNC_DATA_LEN(advsm) == 0 && sync_data_offset == 0)); + BLE_LL_ASSERT((SYNC_DATA_LEN(advsm) > data_offset) || + (SYNC_DATA_LEN(advsm) == 0 && data_offset == 0)); - sync->sync_data_offset = sync_data_offset; - sync->sync_data_len = 0; + sync->data_offset = data_offset; + sync->data_len = 0; sync->payload_len = 0; - sync->ext_hdr = 0; + sync->ext_hdr_flags = 0; sync->chan = chan; - rem_sync_data_len = SYNC_DATA_LEN(advsm) - sync_data_offset; + rem_data_len = SYNC_DATA_LEN(advsm) - data_offset; - hdr_len = BLE_LL_EXT_ADV_HDR_LEN; + ext_hdr_len = BLE_LL_EXT_ADV_HDR_LEN; /* TxPower if configured * Note: TxPower shall not be present in chain PDU for SYNC */ - if (sync_data_offset == 0 && + if (data_offset == 0 && (advsm->periodic_adv_props & BLE_HCI_LE_SET_PERIODIC_ADV_PROP_INC_TX_PWR)) { - sync->ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); - hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; + sync->ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE; } /* if we have any fields in ext header we need to add flags, note that Aux @@ -2279,32 +2351,48 @@ ble_ll_adv_sync_calculate(struct ble_ll_adv_sm *advsm, * how Aux calculate works and this also make it easier to add more fields * into flags if needed in future */ - if (sync->ext_hdr) { - hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + sync->big = advsm->big; + /* If BIG is present flags will always be also present even if none is set + * to indicate ACAD is present. + */ + if (sync->ext_hdr_flags || sync->big) { + ext_hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + } +#else + if (sync->ext_hdr_flags) { + ext_hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + } +#endif + +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + if (advsm->big) { + ext_hdr_len += ble_ll_iso_big_biginfo_len(advsm->big); } +#endif /* AdvData always */ - sync->sync_data_len = min(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_sync_data_len); + sync->data_len = MIN(BLE_LL_MAX_PAYLOAD_LEN - ext_hdr_len, rem_data_len); /* AuxPtr if there are more AdvData remaining that we can fit here */ - if ((rem_sync_data_len > sync->sync_data_len)) { - /* adjust for flags that needs to be added if AuxPtr is only field - * in Extended Header - */ - if (!sync->ext_hdr) { - hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; - sync->sync_data_len -= BLE_LL_EXT_ADV_FLAGS_SIZE; - } + if ((rem_data_len > sync->data_len)) { + /* adjust for flags that needs to be added if AuxPtr is only field + * in Extended Header + */ + if (!sync->ext_hdr_flags) { + ext_hdr_len += BLE_LL_EXT_ADV_FLAGS_SIZE; + sync->data_len -= BLE_LL_EXT_ADV_FLAGS_SIZE; + } - sync->ext_hdr |= (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); - hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; - sync->sync_data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE; + sync->ext_hdr_flags |= (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT); + ext_hdr_len += BLE_LL_EXT_ADV_AUX_PTR_SIZE; + sync->data_len -= BLE_LL_EXT_ADV_AUX_PTR_SIZE; - /* PDU payload should be full if chained */ - BLE_LL_ASSERT(hdr_len + sync->sync_data_len == BLE_LL_MAX_PAYLOAD_LEN); + /* PDU payload should be full if chained */ + BLE_LL_ASSERT(ext_hdr_len + sync->data_len == BLE_LL_MAX_PAYLOAD_LEN); } - sync->payload_len = hdr_len + sync->sync_data_len; + sync->payload_len = ext_hdr_len + sync->data_len; } static void @@ -2325,6 +2413,7 @@ ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, advsm->periodic_sync_index = 0; sync = SYNC_CURRENT(advsm); + sync->auxptr_zero = 0; /* For first SYNC packet in chain we use separate CSA#2 state to maintain * freq hopping as advertised in SyncInfo @@ -2340,7 +2429,7 @@ ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, ble_ll_adv_sync_calculate(advsm, sync, 0, chan); /* sync is always non-connectable and non-scannable*/ - max_usecs = ble_ll_pdu_tx_time_get(sync->payload_len, advsm->sec_phy); + max_usecs = ble_ll_pdu_us(sync->payload_len, advsm->sec_phy); sch = &sync->sch; @@ -2356,8 +2445,7 @@ ble_ll_adv_periodic_schedule_first(struct ble_ll_adv_sm *advsm, rc = ble_ll_sched_periodic_adv(sch, first_pdu); if (rc) { STATS_INC(ble_ll_stats, periodic_adv_drop_event); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, - &advsm->adv_periodic_txdone_ev); + ble_ll_event_add(&advsm->adv_periodic_txdone_ev); return; } @@ -2385,8 +2473,8 @@ ble_ll_adv_periodic_schedule_next(struct ble_ll_adv_sm *advsm) struct ble_ll_adv_sync *sync; struct ble_ll_adv_sync *sync_next; struct ble_ll_sched_item *sch; - uint16_t rem_sync_data_len; - uint16_t next_sync_data_offset; + uint16_t rem_data_len; + uint16_t next_data_offset; uint32_t max_usecs; uint8_t chan; @@ -2409,16 +2497,16 @@ ble_ll_adv_periodic_schedule_next(struct ble_ll_adv_sm *advsm) * Do not schedule next sync if current sync does not have AuxPtr in extended * header as this means we do not need subsequent ADV_CHAIN_IND to be sent. */ - if (!(sync->ext_hdr & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT))) { + if (!(sync->ext_hdr_flags & (1 << BLE_LL_EXT_ADV_AUX_PTR_BIT))) { return; } - next_sync_data_offset = sync->sync_data_offset + sync->sync_data_len; + next_data_offset = sync->data_offset + sync->data_len; - BLE_LL_ASSERT(SYNC_DATA_LEN(advsm) >= next_sync_data_offset); + BLE_LL_ASSERT(SYNC_DATA_LEN(advsm) >= next_data_offset); - rem_sync_data_len = SYNC_DATA_LEN(advsm) - next_sync_data_offset; - BLE_LL_ASSERT(rem_sync_data_len > 0); + rem_data_len = SYNC_DATA_LEN(advsm) - next_data_offset; + BLE_LL_ASSERT(rem_data_len > 0); /* we use separate counter for chaining */ chan = ble_ll_utils_dci_csa2(advsm->periodic_chain_event_cntr++, @@ -2426,8 +2514,8 @@ ble_ll_adv_periodic_schedule_next(struct ble_ll_adv_sm *advsm) advsm->periodic_num_used_chans, advsm->periodic_chanmap); - ble_ll_adv_sync_calculate(advsm, sync_next, next_sync_data_offset, chan); - max_usecs = ble_ll_pdu_tx_time_get(sync_next->payload_len, advsm->sec_phy); + ble_ll_adv_sync_calculate(advsm, sync_next, next_data_offset, chan); + max_usecs = ble_ll_pdu_us(sync_next->payload_len, advsm->sec_phy); sync_next->start_time = sync->sch.end_time + ble_ll_tmr_u2t_up(BLE_LL_MAFS + @@ -2444,13 +2532,14 @@ ble_ll_adv_periodic_schedule_next(struct ble_ll_adv_sm *advsm) ble_ll_sched_adv_new(&sync_next->sch, ble_ll_adv_sync_next_scheduled, sync_next); - /* if we are pass advertising interval, drop chain */ - if (LL_TMR_GT(sch->end_time, advsm->periodic_adv_event_start_time + - advsm->periodic_adv_itvl_ticks)) { + /* Remove aux if previous one was already sent with zero offset or new one + * is scheduled past advertising interval. + */ + if (sync->auxptr_zero || + (LL_TMR_GT(sch->end_time, advsm->periodic_adv_event_start_time + + advsm->periodic_adv_itvl_ticks))) { STATS_INC(ble_ll_stats, periodic_chain_drop_event); ble_ll_sched_rmv_elem(&sync->sch); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, - &advsm->adv_periodic_txdone_ev); } } @@ -2520,7 +2609,7 @@ ble_ll_adv_periodic_done(struct ble_ll_adv_sm *advsm) /* Remove anything else scheduled for periodic */ ble_ll_sched_rmv_elem(&sync->sch); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_periodic_txdone_ev); + ble_ll_event_remove(&advsm->adv_periodic_txdone_ev); /* If we have next SYNC scheduled, try to schedule another one */ if (sync_next->sch.enqueued) { @@ -2563,11 +2652,11 @@ ble_ll_adv_sm_start_periodic(struct ble_ll_adv_sm *advsm) /* keep channel map since we cannot change it later on */ memcpy(advsm->periodic_chanmap, g_ble_ll_data.chan_map, BLE_LL_CHAN_MAP_LEN); - advsm->periodic_num_used_chans = g_ble_ll_data.chan_map_num_used; + advsm->periodic_num_used_chans = g_ble_ll_data.chan_map_used; advsm->periodic_event_cntr = 0; /* for chaining we start with random counter as we share access addr */ advsm->periodic_chain_event_cntr = ble_ll_rand(); - advsm->periodic_access_addr = ble_ll_utils_calc_access_addr(); + advsm->periodic_access_addr = ble_ll_utils_calc_aa(); advsm->periodic_channel_id = ((advsm->periodic_access_addr & 0xffff0000) >> 16) ^ (advsm->periodic_access_addr & 0x0000ffff); advsm->periodic_crcinit = ble_ll_rand() & 0xffffff; @@ -2629,8 +2718,7 @@ ble_ll_adv_sm_stop_periodic(struct ble_ll_adv_sm *advsm) ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_PERIODIC_SYNC_SENDING); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, - &advsm->adv_periodic_txdone_ev); + ble_ll_event_remove(&advsm->adv_periodic_txdone_ev); ble_ll_adv_update_periodic_data(advsm); } @@ -2723,20 +2811,11 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) advsm->event_cntr = 0; - access_addr = ble_ll_utils_calc_access_addr(); + access_addr = ble_ll_utils_calc_aa(); advsm->channel_id = ((access_addr & 0xffff0000) >> 16) ^ (access_addr & 0x0000ffff); #endif - /* Determine the advertising interval we will use */ - if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { - /* Set it to max. allowed for high duty cycle advertising */ - advsm->adv_itvl_usecs = BLE_LL_ADV_PDU_ITVL_HD_MS_MAX; - } else { - advsm->adv_itvl_usecs = (uint32_t)advsm->adv_itvl_max; - advsm->adv_itvl_usecs *= BLE_LL_ADV_ITVL; - } - /* Set first advertising channel */ adv_chan = ble_ll_adv_first_chan(advsm); advsm->adv_chan = adv_chan; @@ -3007,6 +3086,19 @@ ble_ll_adv_set_scan_rsp_data(const uint8_t *data, uint8_t datalen, if (!advsm->new_scan_rsp_data) { return BLE_ERR_MEM_CAPACITY; } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && + !ble_ll_adv_aux_check_data_itvl(advsm, advsm->props, advsm->pri_phy, + advsm->sec_phy, + advsm->new_scan_rsp_data, + advsm->adv_itvl_usecs)) { + os_mbuf_free_chain(advsm->new_scan_rsp_data); + advsm->new_scan_rsp_data = NULL; + return BLE_ERR_PACKET_TOO_LONG; + } +#endif + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_NEW_SCAN_RSP_DATA); } else { ble_ll_adv_update_data_mbuf(&advsm->scan_rsp_data, new_data, @@ -3016,6 +3108,16 @@ ble_ll_adv_set_scan_rsp_data(const uint8_t *data, uint8_t datalen, } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && + !ble_ll_adv_aux_check_data_itvl(advsm, advsm->props, advsm->pri_phy, + advsm->sec_phy, + advsm->scan_rsp_data, + advsm->adv_itvl_usecs)) { + os_mbuf_free_chain(advsm->scan_rsp_data); + advsm->scan_rsp_data = NULL; + return BLE_ERR_PACKET_TOO_LONG; + } + /* DID shall be updated when host provides new scan response data */ ble_ll_adv_update_did(advsm); #endif @@ -3149,6 +3251,18 @@ ble_ll_adv_set_adv_data(const uint8_t *data, uint8_t datalen, uint8_t instance, if (!advsm->new_adv_data) { return BLE_ERR_MEM_CAPACITY; } + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && + !ble_ll_adv_aux_check_data_itvl(advsm, advsm->props, advsm->pri_phy, + advsm->sec_phy, advsm->new_adv_data, + advsm->adv_itvl_usecs)) { + os_mbuf_free_chain(advsm->new_adv_data); + advsm->new_adv_data = NULL; + return BLE_ERR_PACKET_TOO_LONG; + } +#endif + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_NEW_ADV_DATA); } else { ble_ll_adv_update_data_mbuf(&advsm->adv_data, new_data, @@ -3158,6 +3272,15 @@ ble_ll_adv_set_adv_data(const uint8_t *data, uint8_t datalen, uint8_t instance, } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (!(advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY) && + !ble_ll_adv_aux_check_data_itvl(advsm, advsm->props, advsm->pri_phy, + advsm->sec_phy, advsm->adv_data, + advsm->adv_itvl_usecs)) { + os_mbuf_free_chain(advsm->adv_data); + advsm->adv_data = NULL; + return BLE_ERR_PACKET_TOO_LONG; + } + /* DID shall be updated when host provides new advertising data */ ble_ll_adv_update_did(advsm); #endif @@ -3215,7 +3338,7 @@ static struct ble_ll_adv_sm * ble_ll_adv_sm_get(uint8_t instance) { struct ble_ll_adv_sm *advsm; - int i; + unsigned int i; advsm = ble_ll_adv_sm_find_configured(instance); if (advsm) { @@ -3246,6 +3369,7 @@ ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, struct ble_ll_adv_sm *advsm; uint32_t adv_itvl_min; uint32_t adv_itvl_max; + uint32_t adv_itvl_usecs; uint16_t props; int rc; @@ -3427,13 +3551,29 @@ ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, goto done; } + /* Determine the advertising interval we will use */ + if (props & BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED) { + /* Set it to max. allowed for high duty cycle advertising */ + adv_itvl_usecs = BLE_LL_ADV_PDU_ITVL_HD_MS_MAX; + } else { + adv_itvl_usecs = adv_itvl_max * BLE_LL_ADV_ITVL; + } + + if (!ble_ll_adv_aux_check_data_itvl(advsm, props, cmd->pri_phy, cmd->sec_phy, + advsm->adv_data, adv_itvl_usecs) || + !ble_ll_adv_aux_check_data_itvl(advsm, props, cmd->pri_phy, cmd->sec_phy, + advsm->scan_rsp_data, adv_itvl_usecs)) { + return BLE_ERR_PACKET_TOO_LONG; + } + rc = BLE_ERR_SUCCESS; if (cmd->tx_power == 127) { /* no preference */ - advsm->adv_txpwr = g_ble_ll_tx_power; + advsm->tx_power = ble_ll_tx_power_round(g_ble_ll_tx_power - g_ble_ll_tx_power_compensation); } else { - advsm->adv_txpwr = ble_phy_txpower_round(cmd->tx_power); + advsm->tx_power = ble_ll_tx_power_round(MIN(cmd->tx_power, MYNEWT_VAL(BLE_LL_TX_PWR_MAX_DBM)) - + g_ble_ll_tx_power_compensation); } /* we can always store as those are validated and used only when needed */ @@ -3442,8 +3582,7 @@ ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, advsm->own_addr_type = cmd->own_addr_type; advsm->adv_filter_policy = cmd->filter_policy; advsm->adv_chanmask = cmd->pri_chan_map; - advsm->adv_itvl_min = adv_itvl_min; - advsm->adv_itvl_max = adv_itvl_max; + advsm->adv_itvl_usecs = adv_itvl_usecs; advsm->pri_phy = cmd->pri_phy; advsm->sec_phy = cmd->sec_phy; /* Update SID only */ @@ -3470,7 +3609,7 @@ ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len, done: /* Update TX power */ - rsp->tx_power = rc ? 0 : advsm->adv_txpwr; + rsp->tx_power = rc ? 0 : (advsm->tx_power + g_ble_ll_tx_power_compensation); *rsplen = sizeof(*rsp); return rc; @@ -3731,7 +3870,7 @@ ble_ll_adv_sync_get_pdu_len(uint16_t data_len, uint16_t *data_offset, } /* AdvData always */ - data_len = min(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_data_len); + data_len = MIN(BLE_LL_MAX_PAYLOAD_LEN - hdr_len, rem_data_len); /* AuxPtr if there are more AdvData remaining that we can fit here */ if (rem_data_len > data_len) { @@ -3767,9 +3906,8 @@ ble_ll_adv_periodic_check_data_itvl(uint16_t payload_len, uint16_t props, while (offset < payload_len) { pdu_len = ble_ll_adv_sync_get_pdu_len(payload_len, &offset, props); - max_usecs += ble_ll_pdu_tx_time_get(pdu_len, phy); - max_usecs += ble_ll_tmr_u2t_up(BLE_LL_MAFS + - MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY)); + max_usecs += ble_ll_pdu_us(pdu_len, phy); + max_usecs += BLE_LL_MAFS + MYNEWT_VAL(BLE_LL_SCHED_AUX_CHAIN_MAFS_DELAY); } itvl_usecs = (uint32_t)itvl * BLE_LL_ADV_PERIODIC_ITVL; @@ -4416,6 +4554,11 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr, if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD)) { ble_ll_adv_sm_stop(advsm); } + } else if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + ble_ll_adv_flags_set(advsm, BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD_ERR); + valid = 1; +#endif } } @@ -4608,12 +4751,12 @@ ble_ll_adv_drop_event(struct ble_ll_adv_sm *advsm) ble_ll_sched_rmv_elem(&advsm->aux[0].sch); ble_ll_sched_rmv_elem(&advsm->aux[1].sch); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); + ble_ll_event_remove(&advsm->adv_sec_txdone_ev); advsm->aux_active = 0; #endif advsm->adv_chan = ble_ll_adv_final_chan(advsm); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + ble_ll_event_add(&advsm->adv_txdone_ev); } static void @@ -4692,7 +4835,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) /* Remove the element from the schedule if it is still there. */ ble_ll_sched_rmv_elem(&advsm->adv_sch); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + ble_ll_event_remove(&advsm->adv_txdone_ev); /* * Check if we have ended our advertising event. If our last advertising @@ -4753,12 +4896,12 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) ++advsm->adv_chan; } - /* - * We will transmit right away. Set next pdu start time to now - * plus a xcvr start delay just so we dont count late adv starts + /* We want to send next PDU right away so start time is set to "now" + * plus scheduling offset. Add an extra tick since LL timer may tick + * when we calculate other things in the meantime. */ advsm->adv_pdu_start_time = ble_ll_tmr_get() + - g_ble_ll_sched_offset_ticks; + g_ble_ll_sched_offset_ticks + 1; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) /* If we're past aux (unlikely, but can happen), just drop an event */ @@ -4832,7 +4975,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm) rc = ble_ll_sched_adv_resched_pdu(&advsm->adv_sch); if (rc) { STATS_INC(ble_ll_stats, adv_resched_pdu_fail); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev); + ble_ll_event_add(&advsm->adv_txdone_ev); } } @@ -4876,12 +5019,17 @@ ble_ll_adv_sec_done(struct ble_ll_adv_sm *advsm) /* Remove anything else scheduled for secondary channel */ ble_ll_sched_rmv_elem(&aux->sch); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_sec_txdone_ev); + ble_ll_event_remove(&advsm->adv_sec_txdone_ev); /* Stop advertising due to transmitting connection response */ if (advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD) { - ble_ll_adv_sm_stop(advsm); - return; + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD_ERR)) { + ble_ll_adv_sm_stop(advsm); + return; + } else { + ble_ll_adv_flags_clear(advsm, BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD | + BLE_LL_ADV_SM_FLAG_CONN_RSP_TXD_ERR); + } } /* If we have next AUX scheduled, try to schedule another one */ @@ -5106,8 +5254,6 @@ ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm) { memset(advsm, 0, sizeof(struct ble_ll_adv_sm)); - advsm->adv_itvl_min = BLE_HCI_ADV_ITVL_DEF; - advsm->adv_itvl_max = BLE_HCI_ADV_ITVL_DEF; advsm->adv_chanmask = BLE_HCI_ADV_CHANMASK_DEF; /* Initialize advertising tx done event */ @@ -5147,6 +5293,55 @@ ble_ll_adv_sm_init(struct ble_ll_adv_sm *advsm) advsm->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; } +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) +struct ble_ll_adv_sm * +ble_ll_adv_sync_get(uint8_t handle) +{ + struct ble_ll_adv_sm *advsm; + + advsm = ble_ll_adv_sm_find_configured(handle); + if (!advsm) { + return NULL; + } + + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED)) { + return NULL; + } + + return advsm; +} + +int +ble_ll_adv_sync_big_add(struct ble_ll_adv_sm *advsm, + struct ble_ll_iso_big *big) +{ + if (!(advsm->flags & BLE_LL_ADV_SM_FLAG_PERIODIC_CONFIGURED)) { + return -EINVAL; + } + + if (advsm->big && (advsm->big != big)) { + return -EBUSY; + } + + advsm->big = big; + + return 0; +} + +int +ble_ll_adv_sync_big_remove(struct ble_ll_adv_sm *advsm, + struct ble_ll_iso_big *big) +{ + if (advsm->big != big) { + return -EINVAL; + } + + advsm->big = NULL; + + return 0; +} +#endif /* BLE_LL_ISO_BROADCASTER */ + /** * Initialize the advertising functionality of a BLE device. This should * be called once on initialization diff --git a/src/nimble/nimble/controller/src/ble_ll_conn.c b/src/nimble/nimble/controller/src/ble_ll_conn.c index 127c4807..c5dc756c 100644 --- a/src/nimble/nimble/controller/src/ble_ll_conn.c +++ b/src/nimble/nimble/controller/src/ble_ll_conn.c @@ -25,26 +25,30 @@ #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os.h" -#include "nimble/porting/nimble/include/os/os_cputime.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/hci_common.h" #include "nimble/nimble/transport/include/nimble/transport.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_conn.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_ctrl.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_ll_tmr.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_pdu.h" +#include "nimble/nimble/controller/include/controller/ble_ll_conn.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_ll_whitelist.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_ctrl.h" +#include "nimble/nimble/controller/include/controller/ble_ll_resolv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_adv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_trace.h" +#include "nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" #include "ble_ll_conn_priv.h" #include "ble_ll_ctrl_priv.h" +#include "ble_ll_priv.h" +#if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc +#include +#endif #if (BLETEST_THROUGHPUT_TEST == 1) extern void bletest_completed_pkt(uint16_t handle); @@ -54,14 +58,6 @@ extern void bletest_completed_pkt(uint16_t handle); struct ble_ll_conn_sm *g_ble_ll_conn_css_ref; #endif -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - /* XXX TODO * 1) I think if we are initiating and we already have a connection with * a device that we will still try and connect to it. Fix this. @@ -177,6 +173,11 @@ struct ble_ll_conn_active_list g_ble_ll_conn_active_list; /* List of free connections */ struct ble_ll_conn_free_list g_ble_ll_conn_free_list; +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) +static uint16_t g_ble_ll_conn_css_next_slot = BLE_LL_CONN_CSS_NO_SLOT; +struct ble_ll_conn_css_list g_ble_ll_conn_css_list; +#endif + STATS_SECT_START(ble_ll_conn_stats) STATS_SECT_ENTRY(cant_set_sched) STATS_SECT_ENTRY(conn_ev_late) @@ -384,7 +385,7 @@ ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf) cp = (const void *)cmd->data; if (cmd->length != sizeof(cp->handles) + cp->handles * sizeof(cp->h[0])) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_conn_cth_flow_error_ev); + ble_ll_event_add(&g_ble_ll_conn_cth_flow_error_ev); return; } @@ -404,9 +405,54 @@ ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf) } #endif - #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) -static uint16_t g_ble_ll_conn_css_next_slot = BLE_LL_CONN_CSS_NO_SLOT; +static void +ble_ll_conn_css_update_list(struct ble_ll_conn_sm *connsm) +{ + struct ble_ll_conn_sm *e; + struct ble_ll_conn_sm *e_last; + struct ble_ll_conn_sm *e_insert_after = NULL; + bool found_to_insert = false; + + if (SLIST_FIRST(&g_ble_ll_conn_css_list) == connsm) { + SLIST_REMOVE_HEAD(&g_ble_ll_conn_css_list, css_sle); + } else { + e_last = NULL; + SLIST_FOREACH(e, &g_ble_ll_conn_css_list, css_sle) { + if (e == connsm) { + SLIST_NEXT(e_last, css_sle) = SLIST_NEXT(e, css_sle); + break; + } + e_last = e; + } + } + + if (SLIST_EMPTY(&g_ble_ll_conn_css_list)) { + SLIST_INSERT_HEAD(&g_ble_ll_conn_css_list, connsm, css_sle); + return; + } + + e_last = NULL; + SLIST_FOREACH(e, &g_ble_ll_conn_css_list, css_sle) { + if (e->css_slot_idx > connsm->css_slot_idx) { + found_to_insert = true; + e_insert_after = e_last; + break; + } + + e_last = e; + } + + if (found_to_insert) { + if (e_insert_after) { + SLIST_INSERT_AFTER(e_last, connsm, css_sle); + } else { + SLIST_INSERT_HEAD(&g_ble_ll_conn_css_list, connsm, css_sle); + } + } else { + SLIST_INSERT_AFTER(e_last, connsm, css_sle); + } +} void ble_ll_conn_css_set_next_slot(uint16_t slot_idx) @@ -427,9 +473,8 @@ ble_ll_conn_css_get_next_slot(void) /* CSS connections are sorted in active conn list so just need to find 1st * free value. */ - SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { - if ((connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) && - (connsm->css_slot_idx != slot_idx) && + SLIST_FOREACH(connsm, &g_ble_ll_conn_css_list, css_sle) { + if ((connsm->css_slot_idx != slot_idx) && (connsm->css_slot_idx_pending != slot_idx)) { break; } @@ -448,10 +493,13 @@ ble_ll_conn_css_is_slot_busy(uint16_t slot_idx) { struct ble_ll_conn_sm *connsm; - SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { - if ((connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) && - ((connsm->css_slot_idx == slot_idx) || - (connsm->css_slot_idx_pending == slot_idx))) { + if (g_ble_ll_conn_css_next_slot == slot_idx) { + return 1; + } + + SLIST_FOREACH(connsm, &g_ble_ll_conn_css_list, css_sle) { + if ((connsm->css_slot_idx == slot_idx) || + (connsm->css_slot_idx_pending == slot_idx)) { return 1; } } @@ -473,15 +521,12 @@ ble_ll_conn_css_move(struct ble_ll_conn_sm *connsm, uint16_t slot_idx) (slot_idx != BLE_LL_CONN_CSS_NO_SLOT)); slot_diff = slot_idx - connsm->css_slot_idx; - - if (slot_diff > 0) { - offset = slot_diff * ble_ll_sched_css_get_slot_us() / - BLE_LL_CONN_ITVL_USECS; - } else { - offset = (ble_ll_sched_css_get_period_slots() + slot_diff) * - ble_ll_sched_css_get_slot_us() / BLE_LL_CONN_ITVL_USECS; + if (slot_diff < 0) { + slot_diff += ble_ll_sched_css_get_period_slots(); } + offset = slot_diff * ble_ll_sched_css_get_slot_us() / BLE_LL_CONN_ITVL_USECS; + if (offset >= 0xffff) { return -1; } @@ -670,7 +715,7 @@ ble_ll_conn_current_sm_over(struct ble_ll_conn_sm *connsm) * need to post to the LL the connection event end event */ if (connsm) { - ble_ll_event_send(&connsm->conn_ev_end); + ble_ll_event_add(&connsm->conn_ev_end); } } @@ -732,14 +777,14 @@ ble_ll_conn_calc_dci_csa1(struct ble_ll_conn_sm *conn) /* Is this a valid channel? */ bitpos = 1 << (curchan & 0x07); - if (conn->chanmap[curchan >> 3] & bitpos) { + if (conn->chan_map[curchan >> 3] & bitpos) { return curchan; } /* Calculate remap index */ - remap_index = curchan % conn->num_used_chans; + remap_index = curchan % conn->chan_map_used; - return ble_ll_utils_remapped_channel(remap_index, conn->chanmap); + return ble_ll_utils_chan_map_remap(conn->chan_map, remap_index); } /** @@ -757,9 +802,9 @@ ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency) uint8_t index; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) - if (CONN_F_CSA2_SUPP(conn)) { + if (conn->flags.csa2) { return ble_ll_utils_dci_csa2(conn->event_cntr, conn->channel_id, - conn->num_used_chans, conn->chanmap); + conn->chan_map_used, conn->chan_map); } #endif @@ -814,11 +859,11 @@ ble_ll_conn_start_rx_encrypt(void *arg) struct ble_ll_conn_sm *connsm; connsm = (struct ble_ll_conn_sm *)arg; - CONN_F_ENCRYPTED(connsm) = 1; - ble_phy_encrypt_enable(connsm->enc_data.rx_pkt_cntr, - connsm->enc_data.iv, - connsm->enc_data.enc_block.cipher_text, - !CONN_IS_CENTRAL(connsm)); + connsm->flags.encrypted = 1; + ble_phy_encrypt_enable(connsm->enc_data.enc_block.cipher_text); + ble_phy_encrypt_iv_set(connsm->enc_data.iv); + ble_phy_encrypt_counter_set(connsm->enc_data.rx_pkt_cntr, + !CONN_IS_CENTRAL(connsm)); } #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) @@ -828,7 +873,7 @@ ble_ll_conn_start_rx_unencrypt(void *arg) struct ble_ll_conn_sm *connsm; connsm = (struct ble_ll_conn_sm *)arg; - CONN_F_ENCRYPTED(connsm) = 0; + connsm->flags.encrypted = 0; ble_phy_encrypt_disable(); } #endif @@ -839,7 +884,7 @@ ble_ll_conn_txend_encrypt(void *arg) struct ble_ll_conn_sm *connsm; connsm = (struct ble_ll_conn_sm *)arg; - CONN_F_ENCRYPTED(connsm) = 1; + connsm->flags.encrypted = 1; ble_ll_conn_current_sm_over(connsm); } @@ -850,7 +895,7 @@ ble_ll_conn_rxend_unencrypt(void *arg) struct ble_ll_conn_sm *connsm; connsm = (struct ble_ll_conn_sm *)arg; - CONN_F_ENCRYPTED(connsm) = 0; + connsm->flags.encrypted = 0; ble_ll_conn_current_sm_over(connsm); } #endif @@ -861,8 +906,8 @@ ble_ll_conn_continue_rx_encrypt(void *arg) struct ble_ll_conn_sm *connsm; connsm = (struct ble_ll_conn_sm *)arg; - ble_phy_encrypt_set_pkt_cntr(connsm->enc_data.rx_pkt_cntr, - !CONN_IS_CENTRAL(connsm)); + ble_phy_encrypt_counter_set(connsm->enc_data.rx_pkt_cntr, + !CONN_IS_CENTRAL(connsm)); } #endif @@ -896,6 +941,14 @@ ble_ll_conn_get_next_sched_time(struct ble_ll_conn_sm *connsm) rem_us = connsm->anchor_point_usecs; ble_ll_tmr_add_u(&ce_end, &rem_us, connsm->conn_itvl_usecs); + ce_end -= ble_ll_tmr_u2t_up(MYNEWT_VAL(BLE_LL_CONN_EVENT_END_MARGIN)); + + if (connsm->max_ce_len_ticks) { + if (LL_TMR_LT(connsm->anchor_point + connsm->max_ce_len_ticks, ce_end)) { + ce_end = connsm->anchor_point + connsm->max_ce_len_ticks; + } + } + if (ble_ll_sched_next_time(&next_sched_time)) { if (LL_TMR_LT(next_sched_time, ce_end)) { ce_end = next_sched_time; @@ -917,7 +970,7 @@ ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm) uint8_t update_status; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (connsm->csmflags.cfbit.send_ltk_req) { + if (connsm->flags.encrypt_ltk_req) { /* * Send Long term key request event to host. If masked, we need to * send a REJECT_IND. @@ -926,7 +979,7 @@ ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm) ble_ll_ctrl_reject_ind_send(connsm, BLE_LL_CTRL_ENC_REQ, BLE_ERR_PINKEY_MISSING); } - connsm->csmflags.cfbit.send_ltk_req = 0; + connsm->flags.encrypt_ltk_req = 0; } #endif @@ -936,7 +989,7 @@ ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm) * has passed the instant. * 2) We successfully sent the reject reason. */ - if (connsm->csmflags.cfbit.host_expects_upd_event) { + if (connsm->flags.conn_update_host_w4event) { update_status = BLE_ERR_SUCCESS; if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE)) { ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE); @@ -947,27 +1000,27 @@ ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm) } } ble_ll_hci_ev_conn_update(connsm, update_status); - connsm->csmflags.cfbit.host_expects_upd_event = 0; + connsm->flags.conn_update_host_w4event = 0; } /* Check if we need to send PHY update complete event */ #if (BLE_LL_BT5_PHY_SUPPORTED == 1) - if (CONN_F_PHY_UPDATE_EVENT(connsm)) { + if (connsm->flags.phy_update_host_w4event) { if (!ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS)) { /* Sent event. Clear flag */ - CONN_F_PHY_UPDATE_EVENT(connsm) = 0; + connsm->flags.phy_update_host_w4event = 0; } } #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) - if (connsm->csmflags.cfbit.subrate_ind_txd) { + if (connsm->flags.subrate_ind_txd) { ble_ll_conn_subrate_set(connsm, &connsm->subrate_trans); connsm->subrate_trans.subrate_factor = 0; ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SUBRATE_UPDATE); - connsm->csmflags.cfbit.subrate_ind_txd = 0; - connsm->csmflags.cfbit.subrate_host_req = 0; + connsm->flags.subrate_ind_txd = 0; + connsm->flags.subrate_host_req = 0; } #endif /* BLE_LL_CTRL_SUBRATE_IND */ #endif /* BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE */ @@ -1009,7 +1062,7 @@ ble_ll_conn_adjust_pyld_len(struct ble_ll_conn_sm *connsm, uint16_t pyld_len) ret = pyld_len; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (CONN_F_ENCRYPTED(connsm)) { + if (connsm->flags.encrypted) { max_pyld_len -= BLE_LL_DATA_MIC_LEN; } #endif @@ -1057,11 +1110,11 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) md = 0; hdr_byte = BLE_LL_LLID_DATA_FRAG; - if (connsm->csmflags.cfbit.terminate_ind_rxd) { + if (connsm->flags.terminate_ind_rxd) { /* We just received terminate indication. * Just send empty packet as an ACK */ - CONN_F_EMPTY_PDU_TXD(connsm) = 1; + connsm->flags.empty_pdu_txd = 1; goto conn_tx_pdu; } @@ -1070,8 +1123,8 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) * the transmit queue. */ pkthdr = STAILQ_FIRST(&connsm->conn_txq); - if (!connsm->cur_tx_pdu && !CONN_F_EMPTY_PDU_TXD(connsm) && !pkthdr) { - CONN_F_EMPTY_PDU_TXD(connsm) = 1; + if (!connsm->cur_tx_pdu && !connsm->flags.empty_pdu_txd && !pkthdr) { + connsm->flags.empty_pdu_txd = 1; goto conn_tx_pdu; } @@ -1080,7 +1133,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) * the connection transmit queue */ cur_offset = 0; - if (!connsm->cur_tx_pdu && !CONN_F_EMPTY_PDU_TXD(connsm)) { + if (!connsm->cur_tx_pdu && !connsm->flags.empty_pdu_txd) { /* Convert packet header to mbuf */ m = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); nextpkthdr = STAILQ_NEXT(pkthdr, omp_next); @@ -1098,7 +1151,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) ((connsm->enc_data.enc_state > CONN_ENC_S_ENC_RSP_TO_BE_SENT) && CONN_IS_PERIPHERAL(connsm))) { if (!ble_ll_ctrl_enc_allowed_pdu_tx(pkthdr)) { - CONN_F_EMPTY_PDU_TXD(connsm) = 1; + connsm->flags.empty_pdu_txd = 1; goto conn_tx_pdu; } @@ -1222,13 +1275,13 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) tx_phy_mode = BLE_PHY_MODE_1M; #endif - ticks = (BLE_LL_IFS * 3) + connsm->eff_max_rx_time + - ble_ll_pdu_tx_time_get(next_txlen, tx_phy_mode) + - ble_ll_pdu_tx_time_get(cur_txlen, tx_phy_mode); + ticks = (BLE_LL_IFS * 3) + connsm->ota_max_rx_time + + ble_ll_pdu_us(next_txlen, tx_phy_mode) + + ble_ll_pdu_us(cur_txlen, tx_phy_mode); #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { - ticks += (BLE_LL_IFS + connsm->eff_max_rx_time); + ticks += (BLE_LL_IFS + connsm->ota_max_rx_time); } #endif @@ -1240,7 +1293,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) /* If we send an empty PDU we need to initialize the header */ conn_tx_pdu: - if (CONN_F_EMPTY_PDU_TXD(connsm)) { + if (connsm->flags.empty_pdu_txd) { /* * This looks strange, but we dont use the data pointer in the mbuf * when we have an empty pdu. @@ -1285,7 +1338,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) * We could do this. Now, we just keep going and hope that we dont * overrun next scheduled item. */ - if ((connsm->csmflags.cfbit.terminate_ind_rxd) || + if ((connsm->flags.terminate_ind_rxd) || (CONN_IS_PERIPHERAL(connsm) && (md == 0) && (connsm->cons_rxd_bad_crc == 0) && ((connsm->last_rxd_hdr_byte & BLE_LL_DATA_HDR_MD_MASK) == 0) && @@ -1314,18 +1367,21 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) * Both central and peripheral send the START_ENC_RSP encrypted and receive * encrypted */ - CONN_F_ENCRYPTED(connsm) = 1; + connsm->flags.encrypted = 1; connsm->enc_data.tx_encrypted = 1; - ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr, - connsm->enc_data.iv, - connsm->enc_data.enc_block.cipher_text, - CONN_IS_CENTRAL(connsm)); + ble_phy_encrypt_enable(connsm->enc_data.enc_block.cipher_text); + ble_phy_encrypt_iv_set(connsm->enc_data.iv); + ble_phy_encrypt_counter_set(connsm->enc_data.tx_pkt_cntr, + CONN_IS_CENTRAL(connsm)); + if (txend_func == NULL) { + txend_func = ble_ll_conn_continue_rx_encrypt; + } } else if (is_ctrl && (opcode == BLE_LL_CTRL_START_ENC_REQ)) { /* * Only the peripheral sends this and it gets sent unencrypted but * we receive encrypted */ - CONN_F_ENCRYPTED(connsm) = 0; + connsm->flags.encrypted = 0; connsm->enc_data.enc_state = CONN_ENC_S_START_ENC_RSP_WAIT; connsm->enc_data.tx_encrypted = 0; ble_phy_encrypt_disable(); @@ -1342,7 +1398,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) switch (connsm->conn_role) { #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_CONN_ROLE_CENTRAL: - CONN_F_ENCRYPTED(connsm) = 0; + connsm->flags.encrypted = 0; connsm->enc_data.enc_state = CONN_ENC_S_PAUSED; connsm->enc_data.tx_encrypted = 0; ble_phy_encrypt_disable(); @@ -1350,12 +1406,12 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) #endif #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_CONN_ROLE_PERIPHERAL: - CONN_F_ENCRYPTED(connsm) = 1; + connsm->flags.encrypted = 1; connsm->enc_data.tx_encrypted = 1; - ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr, - connsm->enc_data.iv, - connsm->enc_data.enc_block.cipher_text, - CONN_IS_CENTRAL(connsm)); + ble_phy_encrypt_enable(connsm->enc_data.enc_block.cipher_text); + ble_phy_encrypt_iv_set(connsm->enc_data.iv); + ble_phy_encrypt_counter_set(connsm->enc_data.tx_pkt_cntr, + CONN_IS_CENTRAL(connsm)); if (txend_func == NULL) { txend_func = ble_ll_conn_start_rx_unencrypt; } else { @@ -1369,10 +1425,10 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) } } else { /* If encrypted set packet counter */ - if (CONN_F_ENCRYPTED(connsm)) { + if (connsm->flags.encrypted) { connsm->enc_data.tx_encrypted = 1; - ble_phy_encrypt_set_pkt_cntr(connsm->enc_data.tx_pkt_cntr, - CONN_IS_CENTRAL(connsm)); + ble_phy_encrypt_counter_set(connsm->enc_data.tx_pkt_cntr, + CONN_IS_CENTRAL(connsm)); if (txend_func == NULL) { txend_func = ble_ll_conn_continue_rx_encrypt; } @@ -1390,18 +1446,24 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) ble_hdr->txinfo.offset); /* Set last transmitted MD bit */ - CONN_F_LAST_TXD_MD(connsm) = md; + connsm->flags.last_txd_md = md; /* Increment packets transmitted */ - if (CONN_F_EMPTY_PDU_TXD(connsm)) { - if (connsm->csmflags.cfbit.terminate_ind_rxd) { - connsm->csmflags.cfbit.terminate_ind_rxd_acked = 1; + if (connsm->flags.empty_pdu_txd) { + if (connsm->flags.terminate_ind_rxd) { + connsm->flags.terminate_ind_rxd_acked = 1; } STATS_INC(ble_ll_conn_stats, tx_empty_pdus); } else if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) + connsm->has_nonempty_pdu = 1; +#endif STATS_INC(ble_ll_conn_stats, tx_ctrl_pdus); STATS_INCN(ble_ll_conn_stats, tx_ctrl_bytes, cur_txlen); } else { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) + connsm->has_nonempty_pdu = 1; +#endif STATS_INC(ble_ll_conn_stats, tx_l2cap_pdus); STATS_INCN(ble_ll_conn_stats, tx_l2cap_bytes, cur_txlen); } @@ -1421,7 +1483,7 @@ ble_ll_conn_tx_pdu(struct ble_ll_conn_sm *connsm) static int ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) { - int rc; + int rc = 0; #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) uint32_t usecs; #endif @@ -1434,12 +1496,12 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) connsm = (struct ble_ll_conn_sm *)sch->cb_arg; g_ble_ll_conn_cur_sm = connsm; BLE_LL_ASSERT(connsm); + + /* In rare cases 1st connection event is fired before LL finished processing + * new connection. In such case just skip this connection event and LL will + * reschedule to next connection event. + */ if (connsm->conn_state == BLE_LL_CONN_STATE_IDLE) { - /* That should not happen. If it does it means connection - * is already closed - */ - STATS_INC(ble_ll_conn_stats, sched_start_in_idle); - BLE_LL_ASSERT(0); ble_ll_conn_current_sm_over(connsm); return BLE_LL_SCHED_STATE_DONE; } @@ -1465,6 +1527,9 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) ble_phy_mode_set(connsm->phy_data.tx_phy_mode, connsm->phy_data.rx_phy_mode); #endif + /* Set the power */ + ble_ll_tx_power_set(g_ble_ll_tx_power); + switch (connsm->conn_role) { #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_CONN_ROLE_CENTRAL: @@ -1473,11 +1538,10 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) rc = ble_phy_tx_set_start_time(start, sch->remainder); if (!rc) { #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (CONN_F_ENCRYPTED(connsm)) { - ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr, - connsm->enc_data.iv, - connsm->enc_data.enc_block.cipher_text, - 1); + if (connsm->flags.encrypted) { + ble_phy_encrypt_enable(connsm->enc_data.enc_block.cipher_text); + ble_phy_encrypt_iv_set(connsm->enc_data.iv); + ble_phy_encrypt_counter_set(connsm->enc_data.tx_pkt_cntr, 1); } else { ble_phy_encrypt_disable(); } @@ -1498,11 +1562,10 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_CONN_ROLE_PERIPHERAL: #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (CONN_F_ENCRYPTED(connsm)) { - ble_phy_encrypt_enable(connsm->enc_data.rx_pkt_cntr, - connsm->enc_data.iv, - connsm->enc_data.enc_block.cipher_text, - 1); + if (connsm->flags.encrypted) { + ble_phy_encrypt_enable(connsm->enc_data.enc_block.cipher_text); + ble_phy_encrypt_iv_set(connsm->enc_data.iv); + ble_phy_encrypt_counter_set(connsm->enc_data.rx_pkt_cntr, 1); } else { ble_phy_encrypt_disable(); } @@ -1520,7 +1583,7 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) * Set flag that tells peripheral to set last anchor point if a packet * has been received. */ - connsm->csmflags.cfbit.periph_set_last_anchor = 1; + connsm->flags.periph_set_last_anchor = 1; /* * Set the wait for response time. The anchor point is when we @@ -1560,10 +1623,7 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch) } if (rc == BLE_LL_SCHED_STATE_DONE) { - ble_ll_event_send(&connsm->conn_ev_end); - ble_phy_disable(); - ble_ll_state_set(BLE_LL_STATE_STANDBY); - g_ble_ll_conn_cur_sm = NULL; + ble_ll_conn_current_sm_over(connsm); } /* Set time that we last serviced the schedule */ @@ -1629,12 +1689,12 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime, if (rem_bytes > connsm->eff_max_tx_octets) { rem_bytes = connsm->eff_max_tx_octets; } - usecs = ble_ll_pdu_tx_time_get(rem_bytes, tx_phy_mode); + usecs = ble_ll_pdu_us(rem_bytes, tx_phy_mode); } else { /* We will send empty pdu (just a LL header) */ - usecs = ble_ll_pdu_tx_time_get(0, tx_phy_mode); + usecs = ble_ll_pdu_us(0, tx_phy_mode); } - usecs += (BLE_LL_IFS * 2) + connsm->eff_max_rx_time; + usecs += (BLE_LL_IFS * 2) + connsm->ota_max_rx_time; ticks = (uint32_t)(next_sched_time - begtime); allowed_usecs = ble_ll_tmr_t2u(ticks); @@ -1709,8 +1769,8 @@ ble_ll_conn_central_common_init(struct ble_ll_conn_sm *connsm) connsm->hop_inc = (ble_ll_rand() % 12) + 5; /* Set channel map to map requested by host */ - connsm->num_used_chans = g_ble_ll_data.chan_map_num_used; - memcpy(connsm->chanmap, g_ble_ll_data.chan_map, BLE_LL_CHAN_MAP_LEN); + connsm->chan_map_used = g_ble_ll_data.chan_map_used; + memcpy(connsm->chan_map, g_ble_ll_data.chan_map, BLE_LL_CHAN_MAP_LEN); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) connsm->acc_subrate_min = g_ble_ll_conn_params.acc_subrate_min; @@ -1721,7 +1781,7 @@ ble_ll_conn_central_common_init(struct ble_ll_conn_sm *connsm) #endif /* Calculate random access address and crc initialization value */ - connsm->access_addr = ble_ll_utils_calc_access_addr(); + connsm->access_addr = ble_ll_utils_calc_aa(); connsm->crcinit = ble_ll_rand() & 0xffffff; /* Set initial schedule callback */ @@ -1753,8 +1813,59 @@ ble_ll_conn_central_init(struct ble_ll_conn_sm *connsm, connsm->conn_itvl_usecs = cc_params->conn_itvl_usecs; connsm->periph_latency = cc_params->conn_latency; connsm->supervision_tmo = cc_params->supervision_timeout; - connsm->min_ce_len = cc_params->min_ce_len; - connsm->max_ce_len = cc_params->max_ce_len; + connsm->max_ce_len_ticks = ble_ll_tmr_u2t_up(cc_params->max_ce_len * BLE_LL_CONN_CE_USECS); +} +#endif + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +int +ble_ll_conn_set_data_len(struct ble_ll_conn_sm *connsm, + uint16_t tx_octets, uint16_t tx_time, + uint16_t rx_octets, uint16_t rx_time) +{ + int init_dle = 0; + + /* Note: octets/time shall be checked by caller! */ + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + /* Keep original values requested by host since we may want to recalculate + * after PHY changes between coded and uncoded. + */ + connsm->host_req_max_tx_time = tx_time; + connsm->host_req_max_rx_time = rx_time; + + /* If peer does not support coded, we cannot use value larger than 2120us */ + if (!ble_ll_conn_rem_feature_check(connsm, BLE_LL_FEAT_LE_CODED_PHY)) { + tx_time = MIN(tx_time, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); + rx_time = MIN(rx_time, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); + } +#endif + + if (connsm->max_tx_time != tx_time) { + connsm->max_tx_time = tx_time; + init_dle = 1; + } + + if (connsm->max_tx_octets != tx_octets) { + connsm->max_tx_octets = tx_octets; + init_dle = 1; + } + + if (rx_time && (connsm->max_rx_time != rx_time)) { + connsm->max_rx_time = rx_time; + init_dle = 1; + } + + if (rx_octets && (connsm->max_rx_octets != rx_octets)) { + connsm->max_rx_octets = rx_octets; + init_dle = 1; + } + + if (init_dle) { + ble_ll_ctrl_initiate_dle(connsm, false); + } + + return 0; } #endif @@ -1835,7 +1946,7 @@ ble_ll_conn_set_csa(struct ble_ll_conn_sm *connsm, bool chsel) { #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) if (chsel) { - CONN_F_CSA2_SUPP(connsm) = 1; + connsm->flags.csa2 = 1; connsm->channel_id = ((connsm->access_addr & 0xffff0000) >> 16) ^ (connsm->access_addr & 0x0000ffff); @@ -1864,13 +1975,9 @@ void ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) { struct ble_ll_conn_global_params *conn_params; -#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - struct ble_ll_conn_sm *connsm_css_prev = NULL; - struct ble_ll_conn_sm *connsm_css; -#endif /* Reset following elements */ - connsm->csmflags.conn_flags = 0; + memset(&connsm->flags, 0, sizeof(connsm->flags)); connsm->event_cntr = 0; connsm->conn_state = BLE_LL_CONN_STATE_IDLE; connsm->disconnect_reason = 0; @@ -1888,7 +1995,8 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) connsm->subrate_base_event = 0; connsm->subrate_factor = 1; connsm->cont_num = 0; - connsm->last_pdu_event = 0; + connsm->cont_num_left = 0; + connsm->has_nonempty_pdu = 0; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) @@ -1944,12 +2052,14 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) connsm->rem_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN; connsm->eff_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN; connsm->eff_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN; + connsm->ota_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN; connsm->rem_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; connsm->rem_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; connsm->eff_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; connsm->eff_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) connsm->host_req_max_tx_time = 0; + connsm->host_req_max_rx_time = 0; #endif /* Reset encryption data */ @@ -1960,87 +2070,83 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) connsm->auth_pyld_tmo = BLE_LL_CONN_DEF_AUTH_PYLD_TMO; - CONN_F_LE_PING_SUPP(connsm) = 1; - ble_npl_callout_init(&connsm->auth_pyld_timer, - &g_ble_ll_data.ll_evq, - ble_ll_conn_auth_pyld_timer_cb, - connsm); + connsm->flags.le_ping_supp = 1; #endif /* Add to list of active connections */ -#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { - /* We will insert sorted by css_slot_idx to make finding free slot - * easier. - */ - SLIST_FOREACH(connsm_css, &g_ble_ll_conn_active_list, act_sle) { - if ((connsm_css->conn_role == BLE_LL_CONN_ROLE_CENTRAL) && - (connsm_css->css_slot_idx > connsm->css_slot_idx)) { - if (connsm_css_prev) { - SLIST_INSERT_AFTER(connsm_css_prev, connsm, act_sle); - } - break; - } - connsm_css_prev = connsm_css; - } + SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle); - if (!connsm_css_prev) { - /* List was empty or need to insert before 1st connection */ - SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle); - } else if (!connsm_css) { - /* Insert at the end of list */ - SLIST_INSERT_AFTER(connsm_css_prev, connsm, act_sle); - } - } else { - SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle); +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + if (ble_ll_sched_css_is_enabled() && + (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL)) { + ble_ll_conn_css_update_list(connsm); } -#else - SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle); #endif } void ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm) { + int ota_max_rx_time_calc = 0; int send_event; uint16_t eff_time; uint16_t eff_bytes; + uint16_t ota_time; + uint8_t phy_mode; /* Assume no event sent */ send_event = 0; /* See if effective times have changed */ - eff_time = min(connsm->rem_max_tx_time, connsm->max_rx_time); + eff_time = MIN(connsm->rem_max_tx_time, connsm->max_rx_time); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) if (connsm->phy_data.cur_rx_phy == BLE_PHY_CODED) { - eff_time = max(eff_time, BLE_LL_CONN_SUPP_TIME_MIN_CODED); + eff_time = MAX(eff_time, BLE_LL_CONN_SUPP_TIME_MIN_CODED); } #endif if (eff_time != connsm->eff_max_rx_time) { connsm->eff_max_rx_time = eff_time; + ota_max_rx_time_calc = 1; send_event = 1; } - eff_time = min(connsm->rem_max_rx_time, connsm->max_tx_time); + eff_time = MIN(connsm->rem_max_rx_time, connsm->max_tx_time); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) if (connsm->phy_data.cur_tx_phy == BLE_PHY_CODED) { - eff_time = max(eff_time, BLE_LL_CONN_SUPP_TIME_MIN_CODED); + eff_time = MAX(eff_time, BLE_LL_CONN_SUPP_TIME_MIN_CODED); } #endif if (eff_time != connsm->eff_max_tx_time) { connsm->eff_max_tx_time = eff_time; send_event = 1; } - eff_bytes = min(connsm->rem_max_tx_octets, connsm->max_rx_octets); + eff_bytes = MIN(connsm->rem_max_tx_octets, connsm->max_rx_octets); if (eff_bytes != connsm->eff_max_rx_octets) { connsm->eff_max_rx_octets = eff_bytes; + ota_max_rx_time_calc = 1; send_event = 1; } - eff_bytes = min(connsm->rem_max_rx_octets, connsm->max_tx_octets); + eff_bytes = MIN(connsm->rem_max_rx_octets, connsm->max_tx_octets); if (eff_bytes != connsm->eff_max_tx_octets) { connsm->eff_max_tx_octets = eff_bytes; send_event = 1; } + /* If effective rx octets and/or time value changes, we need to calculate + * actual OTA max rx time, i.e. lesser of effective max rx time and rx time + * of PDU containing max rx octets of payload. This is then used to calculate + * connection events timings. + */ + if (ota_max_rx_time_calc) { +#if BLE_LL_BT5_PHY_SUPPORTED + phy_mode = ble_ll_phy_to_phy_mode(connsm->phy_data.cur_rx_phy, + BLE_HCI_LE_PHY_CODED_S8_PREF); +#else + phy_mode = BLE_PHY_MODE_1M; +#endif + ota_time = ble_ll_pdu_us(connsm->eff_max_rx_octets, phy_mode); + connsm->ota_max_rx_time = MIN(ota_time, connsm->eff_max_rx_time); + } + if (send_event) { ble_ll_hci_ev_datalen_chg(connsm); } @@ -2087,16 +2193,17 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err) SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle); #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - /* If current connection was reference for CSS, we need to find another - * one. It does not matter which one we'll pick. - */ - if (connsm == g_ble_ll_conn_css_ref) { - SLIST_FOREACH(g_ble_ll_conn_css_ref, &g_ble_ll_conn_active_list, - act_sle) { - if (g_ble_ll_conn_css_ref->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { - break; - } + if (ble_ll_sched_css_is_enabled() && + (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL)) { + /* If current connection was reference for CSS, we need to find another + * one. It does not matter which one we'll pick. + */ + OS_ENTER_CRITICAL(sr); + SLIST_REMOVE(&g_ble_ll_conn_css_list, connsm, ble_ll_conn_sm, css_sle); + if (connsm == g_ble_ll_conn_css_ref) { + g_ble_ll_conn_css_ref = SLIST_FIRST(&g_ble_ll_conn_css_list); } + OS_EXIT_CRITICAL(sr); } #endif @@ -2124,7 +2231,7 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err) } /* Make sure events off queue */ - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end); + ble_ll_event_remove(&connsm->conn_ev_end); /* Connection state machine is now idle */ connsm->conn_state = BLE_LL_CONN_STATE_IDLE; @@ -2133,19 +2240,19 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err) * If we have features and there's pending HCI command, send an event before * disconnection event so it does make sense to host. */ - if (connsm->csmflags.cfbit.pending_hci_rd_features && - connsm->csmflags.cfbit.rxd_features) { + if (connsm->flags.features_host_req && + connsm->flags.features_rxd) { ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); - connsm->csmflags.cfbit.pending_hci_rd_features = 0; + connsm->flags.features_host_req = 0; } /* * If there is still pending read features request HCI command, send an * event to complete it. */ - if (connsm->csmflags.cfbit.pending_hci_rd_features) { + if (connsm->flags.features_host_req) { ble_ll_hci_ev_rd_rem_used_feat(connsm, ble_err); - connsm->csmflags.cfbit.pending_hci_rd_features = 0; + connsm->flags.features_host_req = 0; } /* @@ -2157,7 +2264,7 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err) * received and we should not send an event. */ if (ble_err && (ble_err != BLE_ERR_UNK_CONN_ID || - connsm->csmflags.cfbit.terminate_ind_rxd)) { + connsm->flags.terminate_ind_rxd)) { ble_ll_disconn_comp_event_send(connsm, ble_err); } @@ -2195,8 +2302,6 @@ ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event, int ble_ll_conn_move_anchor(struct ble_ll_conn_sm *connsm, uint16_t offset) { - struct ble_ll_conn_params cp = { }; - BLE_LL_ASSERT(connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL); if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ) || @@ -2204,14 +2309,8 @@ ble_ll_conn_move_anchor(struct ble_ll_conn_sm *connsm, uint16_t offset) return -1; } - /* Keep parameters, we just want to move anchor */ - cp.interval_max = connsm->conn_itvl; - cp.interval_min = connsm->conn_itvl; - cp.latency = connsm->periph_latency; - cp.timeout = connsm->supervision_tmo; - cp.offset0 = offset; - - ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE, &cp); + connsm->conn_update_anchor_offset_req = offset; + ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE, NULL); return 0; } @@ -2249,17 +2348,19 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) uint16_t trans_next_event_cntr; uint16_t subrate_conn_upd_event_cntr; #endif - +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + uint8_t anchor_calc_for_css = 0; +#endif /* XXX: deal with connection request procedure here as well */ ble_ll_conn_chk_csm_flags(connsm); /* If unable to start terminate procedure, start it now */ - if (connsm->disconnect_reason && !CONN_F_TERMINATE_STARTED(connsm)) { + if (connsm->disconnect_reason && !connsm->flags.terminate_started) { ble_ll_ctrl_terminate_start(connsm); } - if (CONN_F_TERMINATE_STARTED(connsm) && CONN_IS_PERIPHERAL(connsm)) { + if (connsm->flags.terminate_started && CONN_IS_PERIPHERAL(connsm)) { /* Some of the devices waits whole connection interval to ACK our * TERMINATE_IND sent as a Slave. Since we are here it means we are still waiting for ACK. * Make sure we catch it in next connection event. @@ -2272,10 +2373,25 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) base_event_cntr = connsm->subrate_base_event; subrate_factor = connsm->subrate_factor; - if ((connsm->cont_num > 0) && - (connsm->event_cntr + 1 == connsm->subrate_base_event + - connsm->subrate_factor) && - (connsm->event_cntr - connsm->last_pdu_event < connsm->cont_num)) { + /* We need to restore remaining continuation events counter if a non-empty + * PDU was txd/rxd in this connection event. Also we need to set counter to + * 0 in case there was no valid PDU at subrated event, since we should not + * use continuation events in such case (i.e. ignore any valid PDUs prior + * to subrated event). + * + * Note that has_nonempty_pdu flag is also cleared here since LL may move to + * next connection event due to scheduling conflict and there will be no + * start callback for new event. + */ + if (connsm->has_nonempty_pdu) { + connsm->cont_num_left = connsm->cont_num; + connsm->has_nonempty_pdu = 0; + } else if (connsm->event_cntr == connsm->subrate_base_event) { + connsm->cont_num_left = 0; + } + + if (connsm->cont_num_left > 0) { + connsm->cont_num_left--; next_is_subrated = 0; } #else @@ -2298,11 +2414,11 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) /* Set event counter to the next connection event that we will tx/rx in */ use_periph_latency = next_is_subrated && - connsm->csmflags.cfbit.allow_periph_latency && - !connsm->csmflags.cfbit.conn_update_sched && - !connsm->csmflags.cfbit.phy_update_sched && - !connsm->csmflags.cfbit.chanmap_update_scheduled && - connsm->csmflags.cfbit.pkt_rxd; + connsm->flags.periph_use_latency && + !connsm->flags.conn_update_sched && + !connsm->flags.phy_update_sched && + !connsm->flags.chanmap_update_sched && + connsm->flags.pkt_rxd; if (next_is_subrated) { next_event_cntr = base_event_cntr + subrate_factor; @@ -2314,7 +2430,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) /* If we are in subrate transition mode, we should also listen on * subrated connection events based on new parameters. */ - if (connsm->csmflags.cfbit.subrate_trans) { + if (connsm->flags.subrate_trans) { BLE_LL_ASSERT(CONN_IS_CENTRAL(connsm)); cstp = &connsm->subrate_trans; @@ -2340,7 +2456,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) * and one connection event before instant regardless of subrating. */ if (CONN_IS_PERIPHERAL(connsm) && - connsm->csmflags.cfbit.conn_update_sched && + connsm->flags.conn_update_sched && (connsm->subrate_factor > 1)) { subrate_conn_upd_event_cntr = connsm->conn_update_req.instant - 1; if (connsm->event_cntr == subrate_conn_upd_event_cntr) { @@ -2372,14 +2488,16 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) connsm->event_cntr = next_event_cntr; #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { + if (ble_ll_sched_css_is_enabled() && + connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { connsm->css_period_idx += event_cntr_diff; - /* If this is non-reference connection, we set anchor from reference - * instead of calculating manually. + /* If this is non-reference connection, we calculate anchor point from + * reference connection instead of using connection interval. This is + * to make sure connections do not drift over time. */ if (g_ble_ll_conn_css_ref != connsm) { - ble_ll_sched_css_set_conn_anchor(connsm); + anchor_calc_for_css = 1; skip_anchor_calc = 1; } } @@ -2407,7 +2525,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) * connection by the the transmit window offset. We also copy in the * update parameters as they now should take effect. */ - if (connsm->csmflags.cfbit.conn_update_sched && + if (connsm->flags.conn_update_sched && (connsm->event_cntr == connsm->conn_update_req.instant)) { /* Set flag so we send connection update event */ @@ -2418,7 +2536,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) (connsm->conn_itvl != upd->interval) || (connsm->periph_latency != upd->latency) || (connsm->supervision_tmo != upd->timeout)) { - connsm->csmflags.cfbit.host_expects_upd_event = 1; + connsm->flags.conn_update_host_w4event = 1; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) @@ -2429,6 +2547,36 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) } #endif +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + if (ble_ll_sched_css_is_enabled() && + connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { + BLE_LL_ASSERT(connsm->css_slot_idx_pending != + BLE_LL_CONN_CSS_NO_SLOT); + + /* If we are moving to an earlier slot, we are effectively skipping + * one period. + */ + if (connsm->css_slot_idx_pending < connsm->css_slot_idx) { + connsm->css_period_idx++; + } + + connsm->css_slot_idx = connsm->css_slot_idx_pending; + connsm->css_slot_idx_pending = BLE_LL_CONN_CSS_NO_SLOT; + + ble_ll_conn_css_update_list(connsm); + + if (anchor_calc_for_css) { + ble_ll_sched_css_set_conn_anchor(connsm); + anchor_calc_for_css = 0; + } + +#if MYNEWT_VAL(BLE_LL_HCI_VS_CONN_STRICT_SCHED) + ble_ll_hci_ev_send_vs_css_slot_changed(connsm->conn_handle, + connsm->css_slot_idx); +#endif + } +#endif + connsm->supervision_tmo = upd->timeout; connsm->periph_latency = upd->latency; connsm->tx_win_size = upd->winsize; @@ -2440,6 +2588,11 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) ble_ll_conn_itvl_to_ticks(connsm->conn_itvl, &connsm->conn_itvl_ticks, &connsm->conn_itvl_usecs); + if (connsm->conn_param_req.handle != 0) { + connsm->max_ce_len_ticks = ble_ll_tmr_u2t_up(connsm->conn_param_req.max_ce_len * BLE_LL_CONN_CE_USECS); + connsm->conn_param_req.handle = 0; + } + if (upd->winoffset != 0) { usecs = upd->winoffset * BLE_LL_CONN_ITVL_USECS; ble_ll_tmr_add(&connsm->anchor_point, &connsm->anchor_point_usecs, @@ -2449,17 +2602,8 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) /* Reset the starting point of the connection supervision timeout */ connsm->last_rxd_pdu_cputime = connsm->anchor_point; -#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { - BLE_LL_ASSERT(connsm->css_slot_idx_pending != - BLE_LL_CONN_CSS_NO_SLOT); - connsm->css_slot_idx = connsm->css_slot_idx_pending; - connsm->css_slot_idx_pending = BLE_LL_CONN_CSS_NO_SLOT; - } -#endif - /* Reset update scheduled flag */ - connsm->csmflags.cfbit.conn_update_sched = 0; + connsm->flags.conn_update_sched = 0; } /* @@ -2471,18 +2615,18 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) * new channel map once the event counter equals or has passed channel * map update instant. */ - if (connsm->csmflags.cfbit.chanmap_update_scheduled && + if (connsm->flags.chanmap_update_sched && ((int16_t)(connsm->chanmap_instant - connsm->event_cntr) <= 0)) { /* XXX: there is a chance that the control packet is still on * the queue of the central. This means that we never successfully * transmitted update request. Would end up killing connection on peripheral side. Could ignore it or see if still enqueued. */ - connsm->num_used_chans = - ble_ll_utils_calc_num_used_chans(connsm->req_chanmap); - memcpy(connsm->chanmap, connsm->req_chanmap, BLE_LL_CHAN_MAP_LEN); + connsm->chan_map_used = + ble_ll_utils_chan_map_used_get(connsm->req_chanmap); + memcpy(connsm->chan_map, connsm->req_chanmap, BLE_LL_CHAN_MAP_LEN); - connsm->csmflags.cfbit.chanmap_update_scheduled = 0; + connsm->flags.chanmap_update_sched = 0; ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CHAN_MAP_UPD); @@ -2490,8 +2634,14 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) check to make sure we dont have to restart! */ } +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + if (anchor_calc_for_css) { + ble_ll_sched_css_set_conn_anchor(connsm); + } +#endif + #if (BLE_LL_BT5_PHY_SUPPORTED == 1) - if (CONN_F_PHY_UPDATE_SCHED(connsm) && + if (connsm->flags.phy_update_sched && (connsm->event_cntr == connsm->phy_instant)) { /* Set cur phy to new phy */ @@ -2510,8 +2660,8 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) } /* Clear flags and set flag to send event at next instant */ - CONN_F_PHY_UPDATE_SCHED(connsm) = 0; - CONN_F_PHY_UPDATE_EVENT(connsm) = 1; + connsm->flags.phy_update_sched = 0; + connsm->flags.phy_update_host_w4event = 1; ble_ll_ctrl_phy_update_proc_complete(connsm); @@ -2530,7 +2680,7 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) !ble_ll_conn_rem_feature_check(connsm, BLE_LL_FEAT_LE_CODED_PHY)) { ble_ll_conn_rem_feature_add(connsm, BLE_LL_FEAT_LE_CODED_PHY); connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; - ble_ll_ctrl_initiate_dle(connsm); + ble_ll_ctrl_initiate_dle(connsm, false); } #endif } @@ -2544,18 +2694,31 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm) * passed the termination timeout. If so, no need to continue with * connection as we will time out anyway. */ - if (CONN_F_TERMINATE_STARTED(connsm)) { + if (connsm->flags.terminate_started) { if ((int32_t)(connsm->terminate_timeout - connsm->anchor_point) <= 0) { return -1; } } /* - * Calculate ce end time. For a peripgheral, we need to add window widening + * Calculate ce end time. For a peripheral, we need to add window widening * and the transmit window if we still have one. */ +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + /* If css is enabled, use slot duration instead of conn_init_slots for + * reservation. + */ + if (ble_ll_sched_css_is_enabled() && + connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { + ce_duration = ble_ll_tmr_u2t(ble_ll_sched_css_get_slot_us()); + } else { + ce_duration = ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * + BLE_LL_SCHED_USECS_PER_SLOT); + } +#else ce_duration = ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * - BLE_LL_SCHED_USECS_PER_SLOT); + BLE_LL_SCHED_USECS_PER_SLOT); +#endif #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_PERIPHERAL) { @@ -2611,7 +2774,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) connsm->conn_state = BLE_LL_CONN_STATE_CREATED; /* Clear packet received flag */ - connsm->csmflags.cfbit.pkt_rxd = 0; + connsm->flags.pkt_rxd = 0; /* Consider time created the last scheduled time */ connsm->last_scheduled = ble_ll_tmr_get(); @@ -2640,7 +2803,7 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) usecs = rxhdr->rem_usecs + 1250 + (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS) + - ble_ll_pdu_tx_time_get(BLE_CONNECT_REQ_LEN, + ble_ll_pdu_us(BLE_CONNECT_REQ_LEN, rxhdr->rxinfo.phy_mode); if (rxhdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) { @@ -2694,12 +2857,19 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr) * the other side can support it? */ if (!ble_ll_conn_phy_update_if_needed(connsm)) { - CONN_F_CTRLR_PHY_UPDATE(connsm) = 1; + connsm->flags.phy_update_self_initiated = 1; } #endif switch (connsm->conn_role) { #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_CONN_ROLE_CENTRAL: +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + if (ble_ll_sched_css_is_enabled()) { + ble_ll_sched_css_update_anchor(connsm); + ble_ll_conn_css_set_next_slot(BLE_LL_CONN_CSS_NO_SLOT); + } +#endif + evbuf = ble_ll_init_get_conn_comp_ev(); ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf, NULL); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) @@ -2752,20 +2922,6 @@ ble_ll_conn_event_end(struct ble_npl_event *ev) /* Better be a connection state machine! */ connsm = (struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev); BLE_LL_ASSERT(connsm); - if (connsm->conn_state == BLE_LL_CONN_STATE_IDLE) { - /* That should not happen. If it does it means connection - * is already closed. - * Make sure LL state machine is in idle - */ - STATS_INC(ble_ll_conn_stats, sched_end_in_idle); - BLE_LL_ASSERT(0); - - /* Just in case */ - ble_ll_state_set(BLE_LL_STATE_STANDBY); - - ble_ll_scan_chk_resume(); - return; - } /* Log event end */ ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CONN_EV_END, connsm->conn_handle, @@ -2774,10 +2930,10 @@ ble_ll_conn_event_end(struct ble_npl_event *ev) ble_ll_scan_chk_resume(); /* If we have transmitted the terminate IND successfully, we are done */ - if ((connsm->csmflags.cfbit.terminate_ind_txd) || - (connsm->csmflags.cfbit.terminate_ind_rxd && - connsm->csmflags.cfbit.terminate_ind_rxd_acked)) { - if (connsm->csmflags.cfbit.terminate_ind_txd) { + if ((connsm->flags.terminate_ind_txd) || + (connsm->flags.terminate_ind_rxd && + connsm->flags.terminate_ind_rxd_acked)) { + if (connsm->flags.terminate_ind_txd) { ble_err = BLE_ERR_CONN_TERM_LOCAL; } else { /* Make sure the disconnect reason is valid! */ @@ -2791,13 +2947,13 @@ ble_ll_conn_event_end(struct ble_npl_event *ev) } /* Remove any connection end events that might be enqueued */ - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end); + ble_ll_event_remove(&connsm->conn_ev_end); /* * If we have received a packet, we can set the current transmit window * usecs to 0 since we dont need to listen in the transmit window. */ - if (connsm->csmflags.cfbit.pkt_rxd) { + if (connsm->flags.pkt_rxd) { connsm->periph_cur_tx_win_usecs = 0; } @@ -2824,7 +2980,7 @@ ble_ll_conn_event_end(struct ble_npl_event *ev) /* Reset "per connection event" variables */ connsm->cons_rxd_bad_crc = 0; - connsm->csmflags.cfbit.pkt_rxd = 0; + connsm->flags.pkt_rxd = 0; /* See if we need to start any control procedures */ ble_ll_ctrl_chk_proc_start(connsm); @@ -2875,10 +3031,10 @@ ble_ll_conn_event_end(struct ble_npl_event *ev) ble_ll_conn_num_comp_pkts_event_send(connsm); /* If we have features and there's pending HCI command, send an event */ - if (connsm->csmflags.cfbit.pending_hci_rd_features && - connsm->csmflags.cfbit.rxd_features) { + if (connsm->flags.features_host_req && + connsm->flags.features_rxd) { ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); - connsm->csmflags.cfbit.pending_hci_rd_features = 0; + connsm->flags.features_host_req = 0; } } @@ -3016,7 +3172,7 @@ ble_ll_conn_tx_connect_ind_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_by put_le16(dptr + 10, connsm->conn_itvl); put_le16(dptr + 12, connsm->periph_latency); put_le16(dptr + 14, connsm->supervision_tmo); - memcpy(dptr + 16, &connsm->chanmap, BLE_LL_CHAN_MAP_LEN); + memcpy(dptr + 16, &connsm->chan_map, BLE_LL_CHAN_MAP_LEN); dptr[21] = connsm->hop_inc | (connsm->central_sca << 5); *hdr_byte = pdu_data->hdr_byte; @@ -3037,8 +3193,8 @@ ble_ll_conn_event_halt(void) { ble_ll_state_set(BLE_LL_STATE_STANDBY); if (g_ble_ll_conn_cur_sm) { - g_ble_ll_conn_cur_sm->csmflags.cfbit.pkt_rxd = 0; - ble_ll_event_send(&g_ble_ll_conn_cur_sm->conn_ev_end); + g_ble_ll_conn_cur_sm->flags.pkt_rxd = 0; + ble_ll_event_add(&g_ble_ll_conn_cur_sm->conn_ev_end); g_ble_ll_conn_cur_sm = NULL; } } @@ -3236,7 +3392,7 @@ ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa) if (aa != connsm->access_addr) { STATS_INC(ble_ll_conn_stats, rx_data_pdu_bad_aa); ble_ll_state_set(BLE_LL_STATE_STANDBY); - ble_ll_event_send(&connsm->conn_ev_end); + ble_ll_event_add(&connsm->conn_ev_end); g_ble_ll_conn_cur_sm = NULL; return -1; } @@ -3245,14 +3401,14 @@ ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa) rxhdr->rxinfo.handle = connsm->conn_handle; /* Set flag denoting we have received a packet in connection event */ - connsm->csmflags.cfbit.pkt_rxd = 1; + connsm->flags.pkt_rxd = 1; /* Connection is established */ connsm->conn_state = BLE_LL_CONN_STATE_ESTABLISHED; /* Set anchor point (and last) if 1st rxd frame in connection event */ - if (connsm->csmflags.cfbit.periph_set_last_anchor) { - connsm->csmflags.cfbit.periph_set_last_anchor = 0; + if (connsm->flags.periph_set_last_anchor) { + connsm->flags.periph_set_last_anchor = 0; connsm->last_anchor_point = rxhdr->beg_cputime; connsm->anchor_point = connsm->last_anchor_point; connsm->anchor_point_usecs = rxhdr->rem_usecs; @@ -3300,16 +3456,18 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) hdr_byte = rxbuf[0]; acl_len = rxbuf[1]; llid = hdr_byte & BLE_LL_DATA_HDR_LLID_MASK; - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) - connsm->last_pdu_event = connsm->event_cntr; -#endif - + rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) if (BLE_MBUF_HDR_MIC_FAILURE(hdr)) { - STATS_INC(ble_ll_conn_stats, mic_failures); - ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); + /* MIC failure is expected on retransmissions since packet counter does + * not match, so we simply ignore retransmitted PDU with MIC failure as + * they do not have proper decrypted contents. + */ + if (rxd_sn != connsm->last_rxd_sn) { + STATS_INC(ble_ll_conn_stats, mic_failures); + ble_ll_conn_timeout(connsm, BLE_ERR_CONN_TERM_MIC); + } goto conn_rx_data_pdu_end; } #endif @@ -3347,13 +3505,13 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) * connection */ if ((connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) && - CONN_F_LE_PING_SUPP(connsm) && (acl_len != 0)) { + connsm->flags.le_ping_supp && (acl_len != 0)) { ble_ll_conn_auth_pyld_timer_start(connsm); } #endif /* Update RSSI */ - connsm->conn_rssi = hdr->rxinfo.rssi; + connsm->conn_rssi = hdr->rxinfo.rssi - ble_ll_rx_gain(); /* * If we are a peripheral, we can only start to use peripheral latency @@ -3362,7 +3520,7 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_PERIPHERAL) { if (hdr_byte & BLE_LL_DATA_HDR_NESN_MASK) { - connsm->csmflags.cfbit.allow_periph_latency = 1; + connsm->flags.periph_use_latency = 1; } } #endif @@ -3371,7 +3529,6 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) * Discard the received PDU if the sequence number is the same * as the last received sequence number */ - rxd_sn = hdr_byte & BLE_LL_DATA_HDR_SN_MASK; if (rxd_sn == connsm->last_rxd_sn) { STATS_INC(ble_ll_conn_stats, data_pdu_rx_dup); goto conn_rx_data_pdu_end; @@ -3385,6 +3542,10 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) goto conn_rx_data_pdu_end; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) + connsm->has_nonempty_pdu = 1; +#endif + if (llid == BLE_LL_LLID_CTRL) { /* Process control frame */ STATS_INC(ble_ll_conn_stats, rx_ctrl_pdus); @@ -3412,9 +3573,9 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) /* Free buffer */ conn_rx_data_pdu_end: -#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL) +#if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_CONN_CREDIT_INT) { - ble_transport_int_flow_ctl_put(); + hci_ipc_put(HCI_IPC_TYPE_ACL); } #endif @@ -3450,7 +3611,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) uint8_t hdr_nesn; uint8_t conn_sn; uint8_t conn_nesn; - uint8_t reply; + uint8_t reply = 0; uint16_t rem_bytes; uint8_t opcode = 0; uint8_t rx_pyld_len; @@ -3478,12 +3639,12 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) alloc_rxpdu = false; } -#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL) - /* Do not alloc PDU if there are no free buffers in transport. We'll nak - * this PDU in LL. +#if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc + /* If IPC transport is used, make sure there is buffer available on app side + * for this PDU. We'll just nak in LL if there are no free buffers. */ if (alloc_rxpdu && BLE_LL_LLID_IS_DATA(hdr_byte) && (rx_pyld_len > 0)) { - if (ble_transport_int_flow_ctl_get()) { + if (hci_ipc_get(HCI_IPC_TYPE_ACL)) { rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_CREDIT_INT; } else { alloc_rxpdu = false; @@ -3503,8 +3664,9 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) if (ble_ll_conn_cth_flow_alloc_credit(connsm)) { rxhdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_CREDIT; } else { -#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL) - ble_transport_int_flow_ctl_put(); +#if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc + /* Need to return app buffer to pool since we won't use it */ + hci_ipc_put(HCI_IPC_TYPE_ACL); #endif alloc_rxpdu = false; } @@ -3543,7 +3705,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) rx_phy_mode = BLE_PHY_MODE_1M; #endif add_usecs = rxhdr->rem_usecs + - ble_ll_pdu_tx_time_get(rx_pyld_len, rx_phy_mode); + ble_ll_pdu_us(rx_pyld_len, rx_phy_mode); /* * Check the packet CRC. A connection event can continue even if the @@ -3562,7 +3724,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) switch (connsm->conn_role) { #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_CONN_ROLE_CENTRAL: - reply = CONN_F_LAST_TXD_MD(connsm); + reply = connsm->flags.last_txd_md; break; #endif #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) @@ -3599,7 +3761,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) if (rxpdu && ((hdr_sn && conn_nesn) || (!hdr_sn && !conn_nesn))) { connsm->next_exp_seqnum ^= 1; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) - if (CONN_F_ENCRYPTED(connsm) && !ble_ll_conn_is_empty_pdu(rxbuf)) { + if (connsm->flags.encrypted && !ble_ll_conn_is_empty_pdu(rxbuf)) { ++connsm->enc_data.rx_pkt_cntr; } #endif @@ -3612,7 +3774,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) * Check NESN bit from header. If same as tx seq num, the transmission * is acknowledged. Otherwise we need to resend this PDU. */ - if (CONN_F_EMPTY_PDU_TXD(connsm) || connsm->cur_tx_pdu) { + if (connsm->flags.empty_pdu_txd || connsm->cur_tx_pdu) { hdr_nesn = hdr_byte & BLE_LL_DATA_HDR_NESN_MASK; conn_sn = connsm->tx_seqnum; if ((hdr_nesn && conn_sn) || (!hdr_nesn && !conn_sn)) { @@ -3624,8 +3786,8 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) STATS_INC(ble_ll_conn_stats, data_pdu_txg); /* If we transmitted the empty pdu, clear flag */ - if (CONN_F_EMPTY_PDU_TXD(connsm)) { - CONN_F_EMPTY_PDU_TXD(connsm) = 0; + if (connsm->flags.empty_pdu_txd) { + connsm->flags.empty_pdu_txd = 0; goto chk_rx_terminate_ind; } @@ -3664,8 +3826,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) #endif ++connsm->completed_pkts; if (connsm->completed_pkts > 2) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, - &g_ble_ll_data.ll_comp_pkt_ev); + ble_ll_event_add(&g_ble_ll_data.ll_comp_pkt_ev); } } os_mbuf_free_chain(txpdu); @@ -3697,14 +3858,14 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) if (BLE_LL_LLID_IS_CTRL(hdr_byte) && (opcode == BLE_LL_CTRL_TERMINATE_IND) && (rx_pyld_len == (1 + BLE_LL_CTRL_TERMINATE_IND_LEN))) { - connsm->csmflags.cfbit.terminate_ind_rxd = 1; + connsm->flags.terminate_ind_rxd = 1; connsm->rxd_disconnect_reason = rxbuf[3]; } switch (connsm->conn_role) { #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_CONN_ROLE_CENTRAL: - reply = CONN_F_LAST_TXD_MD(connsm) || (hdr_byte & BLE_LL_DATA_HDR_MD_MASK); + reply = connsm->flags.last_txd_md || (hdr_byte & BLE_LL_DATA_HDR_MD_MASK); break; #endif #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) @@ -3721,7 +3882,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) /* If reply flag set, send data pdu and continue connection event */ rc = -1; - if (rx_pyld_len && CONN_F_ENCRYPTED(connsm)) { + if (rx_pyld_len && connsm->flags.encrypted) { rx_pyld_len += BLE_LL_DATA_MIC_LEN; } if (reply && ble_ll_conn_can_send_next_pdu(connsm, begtime, add_usecs)) { @@ -3879,29 +4040,13 @@ ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t length) } } #endif -/** - * Called to set the global channel mask that we use for all connections. - * - * @param num_used_chans - * @param chanmap - */ + void -ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap) +ble_ll_conn_chan_map_update(void) { #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) struct ble_ll_conn_sm *connsm; -#endif - - /* Do nothing if same channel map */ - if (!memcmp(g_ble_ll_data.chan_map, chanmap, BLE_LL_CHAN_MAP_LEN)) { - return; - } - - /* Change channel map and cause channel map update procedure to start */ - g_ble_ll_data.chan_map_num_used = num_used_chans; - memcpy(g_ble_ll_data.chan_map, chanmap, BLE_LL_CHAN_MAP_LEN); -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) /* Perform channel map update */ SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) { if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { @@ -3973,7 +4118,7 @@ ble_ll_conn_periph_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr connsm->conn_itvl = get_le16(dptr + 10); connsm->periph_latency = get_le16(dptr + 12); connsm->supervision_tmo = get_le16(dptr + 14); - memcpy(&connsm->chanmap, dptr + 16, BLE_LL_CHAN_MAP_LEN); + memcpy(&connsm->chan_map, dptr + 16, BLE_LL_CHAN_MAP_LEN); connsm->hop_inc = dptr[21] & 0x1F; connsm->central_sca = dptr[21] >> 5; @@ -4011,8 +4156,8 @@ ble_ll_conn_periph_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr connsm->peer_addr_type = pat; /* Calculate number of used channels; make sure it meets min requirement */ - connsm->num_used_chans = ble_ll_utils_calc_num_used_chans(connsm->chanmap); - if (connsm->num_used_chans < 2) { + connsm->chan_map_used = ble_ll_utils_chan_map_used_get(connsm->chan_map); + if (connsm->chan_map_used < 2) { goto err_periph_start; } @@ -4100,14 +4245,14 @@ ble_ll_conn_subrate_req_hci(struct ble_ll_conn_sm *connsm, connsm->subrate_trans.periph_latency = srp->max_latency; connsm->subrate_trans.cont_num = srp->cont_num; connsm->subrate_trans.supervision_tmo = srp->supervision_tmo; - connsm->csmflags.cfbit.subrate_host_req = 1; + connsm->flags.subrate_host_req = 1; ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SUBRATE_UPDATE, NULL); break; #endif #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_CONN_ROLE_PERIPHERAL: connsm->subrate_req = *srp; - connsm->csmflags.cfbit.subrate_host_req = 1; + connsm->flags.subrate_host_req = 1; ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SUBRATE_REQ, NULL); break; #endif @@ -4146,15 +4291,15 @@ ble_ll_conn_subrate_req_llcp(struct ble_ll_conn_sm *connsm, return -EINVAL; } - connsm->subrate_trans.subrate_factor = min(connsm->acc_subrate_max, + connsm->subrate_trans.subrate_factor = MIN(connsm->acc_subrate_max, srp->subrate_max); connsm->subrate_trans.subrate_base_event = connsm->event_cntr; - connsm->subrate_trans.periph_latency = min(connsm->acc_max_latency, + connsm->subrate_trans.periph_latency = MIN(connsm->acc_max_latency, srp->max_latency); - connsm->subrate_trans.cont_num = min(max(connsm->acc_cont_num, + connsm->subrate_trans.cont_num = MIN(MAX(connsm->acc_cont_num, srp->cont_num), connsm->subrate_trans.subrate_factor - 1); - connsm->subrate_trans.supervision_tmo = min(connsm->supervision_tmo, + connsm->subrate_trans.supervision_tmo = MIN(connsm->supervision_tmo, srp->supervision_tmo); ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_SUBRATE_UPDATE, NULL); @@ -4172,7 +4317,7 @@ ble_ll_conn_subrate_set(struct ble_ll_conn_sm *connsm, /* Assume parameters were checked by caller */ - send_ev = connsm->csmflags.cfbit.subrate_host_req || + send_ev = connsm->flags.subrate_host_req || (connsm->subrate_factor != sp->subrate_factor) || (connsm->periph_latency != sp->periph_latency) || (connsm->cont_num != sp->cont_num) || @@ -4196,11 +4341,9 @@ ble_ll_conn_subrate_set(struct ble_ll_conn_sm *connsm, #endif #define MAX_TIME_UNCODED(_maxbytes) \ - ble_ll_pdu_tx_time_get(_maxbytes + BLE_LL_DATA_MIC_LEN, \ - BLE_PHY_MODE_1M); + ble_ll_pdu_us(_maxbytes + BLE_LL_DATA_MIC_LEN, BLE_PHY_MODE_1M); #define MAX_TIME_CODED(_maxbytes) \ - ble_ll_pdu_tx_time_get(_maxbytes + BLE_LL_DATA_MIC_LEN, \ - BLE_PHY_MODE_CODED_125KBPS); + ble_ll_pdu_us(_maxbytes + BLE_LL_DATA_MIC_LEN, BLE_PHY_MODE_CODED_125KBPS); /** * Called to reset the connection module. When this function is called the @@ -4250,7 +4393,7 @@ ble_ll_conn_module_reset(void) /* Configure the global LL parameters */ conn_params = &g_ble_ll_conn_params; - maxbytes = min(MYNEWT_VAL(BLE_LL_SUPP_MAX_RX_BYTES), max_phy_pyld); + maxbytes = MIN(MYNEWT_VAL(BLE_LL_SUPP_MAX_RX_BYTES), max_phy_pyld); conn_params->supp_max_rx_octets = maxbytes; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) conn_params->supp_max_rx_time = MAX_TIME_CODED(maxbytes); @@ -4258,7 +4401,7 @@ ble_ll_conn_module_reset(void) conn_params->supp_max_rx_time = MAX_TIME_UNCODED(maxbytes); #endif - maxbytes = min(MYNEWT_VAL(BLE_LL_SUPP_MAX_TX_BYTES), max_phy_pyld); + maxbytes = MIN(MYNEWT_VAL(BLE_LL_SUPP_MAX_TX_BYTES), max_phy_pyld); conn_params->supp_max_tx_octets = maxbytes; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) conn_params->supp_max_tx_time = MAX_TIME_CODED(maxbytes); @@ -4266,7 +4409,7 @@ ble_ll_conn_module_reset(void) conn_params->supp_max_tx_time = MAX_TIME_UNCODED(maxbytes); #endif - maxbytes = min(MYNEWT_VAL(BLE_LL_CONN_INIT_MAX_TX_BYTES), max_phy_pyld); + maxbytes = MIN(MYNEWT_VAL(BLE_LL_CONN_INIT_MAX_TX_BYTES), max_phy_pyld); conn_params->conn_init_max_tx_octets = maxbytes; conn_params->conn_init_max_tx_time = MAX_TIME_UNCODED(maxbytes); conn_params->conn_init_max_tx_time_uncoded = MAX_TIME_UNCODED(maxbytes); @@ -4298,6 +4441,10 @@ ble_ll_conn_module_reset(void) g_ble_ll_conn_cth_flow.max_buffers = 1; g_ble_ll_conn_cth_flow.num_buffers = 1; #endif + +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + g_ble_ll_conn_css_next_slot = BLE_LL_CONN_CSS_NO_SLOT; +#endif } /* Initialize the connection module */ @@ -4312,6 +4459,10 @@ ble_ll_conn_module_init(void) SLIST_INIT(&g_ble_ll_conn_active_list); STAILQ_INIT(&g_ble_ll_conn_free_list); +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + SLIST_INIT(&g_ble_ll_conn_css_list); +#endif + /* * Take all the connections off the free memory pool and add them to * the free connection list, assigning handles in linear order. Note: diff --git a/src/nimble/nimble/controller/src/ble_ll_conn_hci.c b/src/nimble/nimble/controller/src/ble_ll_conn_hci.c index 235c46ea..fc9e7217 100644 --- a/src/nimble/nimble/controller/src/ble_ll_conn_hci.c +++ b/src/nimble/nimble/controller/src/ble_ll_conn_hci.c @@ -26,22 +26,17 @@ #include "nimble/porting/nimble/include/os/os.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_utils.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_conn.h" -#include "../include/controller/ble_ll_ctrl.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_adv.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_conn.h" +#include "nimble/nimble/controller/include/controller/ble_ll_ctrl.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_ll_adv.h" #include "ble_ll_conn_priv.h" #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(array) \ - (sizeof(array) / sizeof((array)[0])) -#endif - /* * Used to limit the rate at which we send the number of completed packets * event to the host. This is the os time at which we can send an event. @@ -146,7 +141,7 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, struct ble_hci_ev_le_subev_enh_conn_complete *enh_ev; struct ble_hci_ev_le_subev_conn_complete *ev; struct ble_hci_ev *hci_ev = (void *) evbuf; - uint8_t *rpa; + uint8_t *rpa = NULL; BLE_LL_ASSERT(evbuf); @@ -486,12 +481,14 @@ ble_ll_conn_hci_create_check_params(struct ble_ll_conn_create_params *cc_params) return BLE_ERR_INV_HCI_CMD_PARMS; } - /* Adjust min/max ce length to be less than interval */ - if (cc_params->min_ce_len > cc_params->conn_itvl) { - cc_params->min_ce_len = cc_params->conn_itvl; + /* Adjust min/max ce length to be less than interval + * Note that interval is in 1.25ms and CE is in 625us + */ + if (cc_params->min_ce_len > cc_params->conn_itvl * 2) { + cc_params->min_ce_len = cc_params->conn_itvl * 2; } - if (cc_params->max_ce_len > cc_params->conn_itvl) { - cc_params->max_ce_len = cc_params->conn_itvl; + if (cc_params->max_ce_len > cc_params->conn_itvl * 2) { + cc_params->max_ce_len = cc_params->conn_itvl * 2; } /* Precalculate conn interval */ @@ -520,7 +517,7 @@ ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len) uint16_t conn_itvl_min; uint16_t conn_itvl_max; #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - uint16_t css_slot_idx; + uint16_t css_slot_idx = 0; #endif int rc; @@ -543,9 +540,11 @@ ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len) } #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - css_slot_idx = ble_ll_conn_css_get_next_slot(); - if (css_slot_idx == BLE_LL_CONN_CSS_NO_SLOT) { - return BLE_ERR_MEM_CAPACITY; + if (ble_ll_sched_css_is_enabled()) { + css_slot_idx = ble_ll_conn_css_get_next_slot(); + if (css_slot_idx == BLE_LL_CONN_CSS_NO_SLOT) { + return BLE_ERR_MEM_CAPACITY; + } } #endif @@ -581,10 +580,14 @@ ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len) } #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - cc_params.conn_itvl = ble_ll_sched_css_get_conn_interval_us(); - if ((cc_params.conn_itvl < conn_itvl_min) || - (cc_params.conn_itvl > conn_itvl_max)) { - return BLE_ERR_INV_HCI_CMD_PARMS; + if (ble_ll_sched_css_is_enabled()) { + cc_params.conn_itvl = ble_ll_sched_css_get_conn_interval_us(); + if ((cc_params.conn_itvl < conn_itvl_min) || + (cc_params.conn_itvl > conn_itvl_max)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } else { + cc_params.conn_itvl = conn_itvl_max; } #else cc_params.conn_itvl = conn_itvl_max; @@ -624,6 +627,11 @@ ble_ll_conn_hci_create(const uint8_t *cmdbuf, uint8_t len) if (rc) { SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + if (ble_ll_sched_css_is_enabled()) { + SLIST_REMOVE(&g_ble_ll_conn_css_list, connsm, ble_ll_conn_sm, css_sle); + } +#endif } return rc; @@ -674,10 +682,14 @@ ble_ll_conn_hci_ext_create_parse_params(const struct conn_params *params, } #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - cc_params->conn_itvl = ble_ll_sched_css_get_conn_interval_us(); - if ((cc_params->conn_itvl < conn_itvl_min) || - (cc_params->conn_itvl > conn_itvl_max)) { - return BLE_ERR_INV_HCI_CMD_PARMS; + if (ble_ll_sched_css_is_enabled()) { + cc_params->conn_itvl = ble_ll_sched_css_get_conn_interval_us(); + if ((cc_params->conn_itvl < conn_itvl_min) || + (cc_params->conn_itvl > conn_itvl_max)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } else { + cc_params->conn_itvl = conn_itvl_max; } #else cc_params->conn_itvl = conn_itvl_max; @@ -741,7 +753,7 @@ ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len) struct ble_ll_conn_sm *connsm; const struct init_phy *init_phy; #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - uint16_t css_slot_idx; + uint16_t css_slot_idx = 0; #endif int rc; @@ -766,9 +778,11 @@ ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len) } #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - css_slot_idx = ble_ll_conn_css_get_next_slot(); - if (css_slot_idx == BLE_LL_CONN_CSS_NO_SLOT) { - return BLE_ERR_MEM_CAPACITY; + if (ble_ll_sched_css_is_enabled()) { + css_slot_idx = ble_ll_conn_css_get_next_slot(); + if (css_slot_idx == BLE_LL_CONN_CSS_NO_SLOT) { + return BLE_ERR_MEM_CAPACITY; + } } #endif @@ -790,7 +804,7 @@ ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len) cc_params_fb = NULL; - for (int i = 0; i < ARRAY_SIZE(init_phys); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(init_phys); i++) { init_phy = &init_phys[i]; if ((cc_scan.init_phy_mask & init_phy->mask) == 0) { @@ -840,6 +854,11 @@ ble_ll_conn_hci_ext_create(const uint8_t *cmdbuf, uint8_t len) if (rc) { SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle); STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe); +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + if (ble_ll_sched_css_is_enabled()) { + SLIST_REMOVE(&g_ble_ll_conn_css_list, connsm, ble_ll_conn_sm, css_sle); + } +#endif } return rc; @@ -903,7 +922,7 @@ ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len) } /* If already pending exit with error */ - if (connsm->csmflags.cfbit.pending_hci_rd_features) { + if (connsm->flags.features_host_req) { return BLE_ERR_CMD_DISALLOWED; } @@ -911,8 +930,8 @@ ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len) * Start control procedure if we did not receive peer's features and did not * start procedure already. */ - if (!connsm->csmflags.cfbit.rxd_features && - !IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG)) { + if (!connsm->flags.features_rxd && + !IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG)) { #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) if ((connsm->conn_role == BLE_LL_CONN_ROLE_PERIPHERAL) && !(ble_ll_read_supp_features() & BLE_LL_FEAT_PERIPH_INIT)) { @@ -923,11 +942,39 @@ ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len) ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG, NULL); } - connsm->csmflags.cfbit.pending_hci_rd_features = 1; + connsm->flags.features_host_req = 1; return BLE_ERR_SUCCESS; } +static bool +ble_ll_conn_params_in_range(struct ble_ll_conn_sm *connsm, + const struct ble_hci_le_conn_update_cp *cmd) +{ + if (!IN_RANGE(connsm->conn_itvl, le16toh(cmd->conn_itvl_min), + le16toh(cmd->conn_itvl_max))) { + return false; + } + + if (connsm->periph_latency != le16toh(cmd->conn_latency)) { + return false; + } + + if (connsm->supervision_tmo != le16toh(cmd->supervision_timeout)) { + return false; + } + + return true; +} + +static void +ble_ll_conn_hci_update_complete_event(void *user_data) +{ + struct ble_ll_conn_sm *connsm = user_data; + + ble_ll_hci_ev_conn_update(connsm, BLE_ERR_SUCCESS); +} + /** * Called to process a connection update command. * @@ -944,6 +991,7 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) uint16_t handle; struct ble_ll_conn_sm *connsm; struct hci_conn_update *hcu; + uint16_t max_ce_len; /* * XXX: must deal with peripheral not supporting this feature and using @@ -961,6 +1009,36 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_UNK_CONN_ID; } + /* if current connection parameters fit updated values we don't have to + * trigger LL procedure and just update local values (Min/Max CE Length) + * + * Note that this is also allowed for CSS as nothing changes WRT connections + * scheduling. + */ + if (ble_ll_conn_params_in_range(connsm, cmd)) { + max_ce_len = le16toh(cmd->max_ce_len); + + if (le16toh(cmd->min_ce_len) > max_ce_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + connsm->max_ce_len_ticks = ble_ll_tmr_u2t_up(max_ce_len * BLE_LL_CONN_CE_USECS); + + ble_ll_hci_post_cmd_cb_set(ble_ll_conn_hci_update_complete_event, connsm); + + return BLE_ERR_SUCCESS; + } + +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + /* Do not allow connection update if css in enabled, we only allow to move + * anchor point (i.e. change slot) via dedicated HCI command. + */ + if (ble_ll_sched_css_is_enabled() && + connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { + return BLE_ERR_CMD_DISALLOWED; + } +#endif + /* Better not have this procedure ongoing! */ if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ) || IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE)) { @@ -985,11 +1063,11 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) * peripheral has initiated the procedure, we need to send a reject to the * peripheral. */ - if (connsm->csmflags.cfbit.awaiting_host_reply) { + if (connsm->flags.conn_update_host_w4reply) { switch (connsm->conn_role) { #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_CONN_ROLE_CENTRAL: - connsm->csmflags.cfbit.awaiting_host_reply = 0; + connsm->flags.conn_update_host_w4reply = 0; /* XXX: If this fails no reject ind will be sent! */ ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, @@ -1012,7 +1090,7 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len) * update procedure we should deny the peripheral request for now. */ #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) - if (connsm->csmflags.cfbit.chanmap_update_scheduled) { + if (connsm->flags.chanmap_update_sched) { if (connsm->conn_role == BLE_LL_CONN_ROLE_PERIPHERAL) { return BLE_ERR_DIFF_TRANS_COLL; } @@ -1082,7 +1160,7 @@ ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len, rc = ble_ll_conn_process_conn_params(cmd, connsm); /* The connection should be awaiting a reply. If not, just discard */ - if (connsm->csmflags.cfbit.awaiting_host_reply) { + if (connsm->flags.conn_update_host_w4reply) { /* Get a control packet buffer */ if (rc == BLE_ERR_SUCCESS) { om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, @@ -1100,7 +1178,7 @@ ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len, ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, BLE_ERR_CONN_PARMS); } - connsm->csmflags.cfbit.awaiting_host_reply = 0; + connsm->flags.conn_update_host_w4reply = 0; /* XXX: if we cant get a buffer, what do we do? We need to remember * reason if it was a negative reply. We also would need to have @@ -1147,11 +1225,11 @@ ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len, rc = BLE_ERR_SUCCESS; /* The connection should be awaiting a reply. If not, just discard */ - if (connsm->csmflags.cfbit.awaiting_host_reply) { + if (connsm->flags.conn_update_host_w4reply) { /* XXX: check return code and deal */ ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode, cmd->reason); - connsm->csmflags.cfbit.awaiting_host_reply = 0; + connsm->flags.conn_update_host_w4reply = 0; /* XXX: if we cant get a buffer, what do we do? We need to remember * reason if it was a negative reply. We also would need to have @@ -1170,7 +1248,7 @@ ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len, * safe to use g_ble_ll_conn_comp_ev */ static void -ble_ll_conn_hci_cancel_conn_complete_event(void) +ble_ll_conn_hci_cancel_conn_complete_event(void *user_data) { BLE_LL_ASSERT(g_ble_ll_conn_comp_ev); @@ -1188,7 +1266,7 @@ ble_ll_conn_hci_cancel_conn_complete_event(void) * @return int */ int -ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) +ble_ll_conn_create_cancel(void) { int rc; struct ble_ll_conn_sm *connsm; @@ -1208,7 +1286,7 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) ble_ll_scan_sm_stop(1); ble_ll_conn_end(connsm, BLE_ERR_UNK_CONN_ID); - *post_cmd_cb = ble_ll_conn_hci_cancel_conn_complete_event; + ble_ll_hci_post_cmd_cb_set(ble_ll_conn_hci_cancel_conn_complete_event, NULL); rc = BLE_ERR_SUCCESS; } else { @@ -1257,7 +1335,7 @@ ble_ll_conn_hci_disconnect_cmd(const struct ble_hci_lc_disconnect_cp *cmd) rc = BLE_ERR_CMD_DISALLOWED; } else { /* This control procedure better not be pending! */ - BLE_LL_ASSERT(CONN_F_TERMINATE_STARTED(connsm) == 0); + BLE_LL_ASSERT(connsm->flags.terminate_started == 0); /* Record the disconnect reason */ connsm->disconnect_reason = cmd->reason; @@ -1316,7 +1394,7 @@ ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len) * NOTE: we cant just send the event here. That would cause the event to * be queued before the command status. */ - if (!connsm->csmflags.cfbit.version_ind_sent) { + if (!connsm->flags.version_ind_txd) { ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG, NULL); } else { connsm->pending_ctrl_procs |= (1 << BLE_LL_CTRL_PROC_VERSION_XCHG); @@ -1391,10 +1469,10 @@ ble_ll_conn_hci_rd_chan_map(const uint8_t *cmdbuf, uint8_t len, rc = BLE_ERR_UNK_CONN_ID; memset(rsp->chan_map, 0, sizeof(rsp->chan_map)); } else { - if (connsm->csmflags.cfbit.chanmap_update_scheduled) { + if (connsm->flags.chanmap_update_sched) { memcpy(rsp->chan_map, connsm->req_chanmap, BLE_LL_CHAN_MAP_LEN); } else { - memcpy(rsp->chan_map, connsm->chanmap, BLE_LL_CHAN_MAP_LEN); + memcpy(rsp->chan_map, connsm->chan_map, BLE_LL_CHAN_MAP_LEN); } rc = BLE_ERR_SUCCESS; } @@ -1406,38 +1484,6 @@ ble_ll_conn_hci_rd_chan_map(const uint8_t *cmdbuf, uint8_t len, } #endif -/** - * Called when the host issues the LE command "set host channel classification" - * - * @param cmdbuf - * - * @return int - */ -int -ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len) -{ - const struct ble_hci_le_set_host_chan_class_cp *cmd = (const void *) cmdbuf; - uint8_t num_used_chans; - - if (len != sizeof(*cmd)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* - * The HCI command states that the host is allowed to mask in just one - * channel but the Link Layer needs minimum two channels to operate. So - * I will not allow this command if there are less than 2 channels masked. - */ - num_used_chans = ble_ll_utils_calc_num_used_chans(cmd->chan_map); - if ((num_used_chans < 2) || ((cmd->chan_map[4] & 0xe0) != 0)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } - - /* Set the host channel mask */ - ble_ll_conn_set_global_chanmap(num_used_chans, cmd->chan_map); - return BLE_ERR_SUCCESS; -} - #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) @@ -1449,8 +1495,8 @@ ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, struct ble_hci_le_set_data_len_rp *rsp = (void *) rspbuf; int rc; uint16_t handle; - uint16_t txoctets; - uint16_t txtime; + uint16_t tx_octets; + uint16_t tx_time; struct ble_ll_conn_sm *connsm; if (len != sizeof(*cmd)) { @@ -1465,42 +1511,19 @@ ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, goto done; } - txoctets = le16toh(cmd->tx_octets); - txtime = le16toh(cmd->tx_time); + tx_octets = le16toh(cmd->tx_octets); + tx_time = le16toh(cmd->tx_time); - /* Make sure it is valid */ - if (!ble_ll_chk_txrx_octets(txoctets) || - !ble_ll_chk_txrx_time(txtime)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; - } - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - /* - * Keep original value requested by host since we may want to recalculate - * MaxTxTime after PHY changes between coded and uncoded. - */ - connsm->host_req_max_tx_time = txtime; - - /* If peer does not support coded, we cannot use value larger than 2120us */ - if (!ble_ll_conn_rem_feature_check(connsm, BLE_LL_FEAT_LE_CODED_PHY)) { - txtime = min(txtime, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); + if (!ble_ll_hci_check_dle(tx_octets, tx_time)) { + return BLE_ERR_INV_HCI_CMD_PARMS; } -#endif - rc = BLE_ERR_SUCCESS; - if (connsm->max_tx_time != txtime || - connsm->max_tx_octets != txoctets) { - - connsm->max_tx_time = txtime; - connsm->max_tx_octets = txoctets; - - ble_ll_ctrl_initiate_dle(connsm); - } + rc = ble_ll_conn_set_data_len(connsm, tx_octets, tx_time, 0, 0); done: rsp->conn_handle = htole16(handle); *rsplen = sizeof(*rsp); + return rc; } #endif @@ -1968,7 +1991,7 @@ ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len) * If host has requested a PHY update and we are not finished do * not allow another one */ - if (CONN_F_HOST_PHY_UPDATE(connsm)) { + if (connsm->flags.phy_update_host_initiated) { return BLE_ERR_CMD_DISALLOWED; } @@ -1997,9 +2020,9 @@ ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len) */ if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE)) { if (connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_PHY_UPDATE) { - CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; + connsm->flags.phy_update_self_initiated = 0; } - CONN_F_HOST_PHY_UPDATE(connsm) = 1; + connsm->flags.phy_update_host_initiated = 1; } else { /* * We could be doing a peer-initiated PHY update procedure. If this @@ -2007,20 +2030,20 @@ ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len) * we are not done with a peer-initiated procedure we just set the * pending bit but do not start the control procedure. */ - if (CONN_F_PEER_PHY_UPDATE(connsm)) { + if (connsm->flags.phy_update_peer_initiated) { connsm->pending_ctrl_procs |= (1 << BLE_LL_CTRL_PROC_PHY_UPDATE); - CONN_F_HOST_PHY_UPDATE(connsm) = 1; + connsm->flags.phy_update_host_initiated = 1; } else { /* Check if we should start phy update procedure */ if (!ble_ll_conn_phy_update_if_needed(connsm)) { - CONN_F_HOST_PHY_UPDATE(connsm) = 1; + connsm->flags.phy_update_host_initiated = 1; } else { /* * Set flag to send a PHY update complete event. We set flag * even if we do not do an update procedure since we have to * inform the host even if we decide not to change anything. */ - CONN_F_PHY_UPDATE_EVENT(connsm) = 1; + connsm->flags.phy_update_host_w4event = 1; } } } diff --git a/src/nimble/nimble/controller/src/ble_ll_conn_priv.h b/src/nimble/nimble/controller/src/ble_ll_conn_priv.h index 1c2fac3e..09546bed 100644 --- a/src/nimble/nimble/controller/src/ble_ll_conn_priv.h +++ b/src/nimble/nimble/controller/src/ble_ll_conn_priv.h @@ -20,8 +20,8 @@ #ifndef H_BLE_LL_CONN_PRIV_ #define H_BLE_LL_CONN_PRIV_ -#include "../include/controller/ble_ll_conn.h" -#include "../include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_conn.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" #ifdef __cplusplus extern "C" { @@ -104,6 +104,11 @@ STAILQ_HEAD(ble_ll_conn_free_list, ble_ll_conn_sm); extern struct ble_ll_conn_active_list g_ble_ll_conn_active_list; extern struct ble_ll_conn_free_list g_ble_ll_conn_free_list; +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) +SLIST_HEAD(ble_ll_conn_css_list, ble_ll_conn_sm); +extern struct ble_ll_conn_css_list g_ble_ll_conn_css_list; +#endif + struct ble_ll_conn_create_scan { uint8_t filter_policy; uint8_t own_addr_type; @@ -177,7 +182,6 @@ int ble_ll_conn_periph_start(uint8_t *rxbuf, uint8_t pat, /* Link Layer interface */ void ble_ll_conn_module_init(void); -void ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap); void ble_ll_conn_module_reset(void); void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len); int ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa); @@ -200,7 +204,7 @@ int ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); int ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen); -int ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb); +int ble_ll_conn_create_cancel(void); void ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm); void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status, uint8_t *evbuf, struct ble_ll_adv_sm *advsm); @@ -236,6 +240,7 @@ int ble_ll_conn_hci_subrate_req(const uint8_t *cmdbuf, uint8_t len, #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm); +void ble_ll_conn_auth_pyld_timer_cb(struct ble_npl_event *ev); #else #define ble_ll_conn_auth_pyld_timer_start(x) #endif @@ -246,12 +251,15 @@ bool ble_ll_conn_cth_flow_enable(bool enabled); void ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf); #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +int ble_ll_conn_set_data_len(struct ble_ll_conn_sm *connsm, + uint16_t tx_octets, uint16_t tx_time, + uint16_t rx_octets, uint16_t rx_time); +#endif + void ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint32_t *itvl_ticks, uint8_t *itvl_usecs); -int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg); -int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg); - int ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len, uint8_t *rsp, uint8_t *rsplen); int ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len); diff --git a/src/nimble/nimble/controller/src/ble_ll_crypto.c b/src/nimble/nimble/controller/src/ble_ll_crypto.c new file mode 100644 index 00000000..15d62ebf --- /dev/null +++ b/src/nimble/nimble/controller/src/ble_ll_crypto.c @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include + +int +ble_ll_crypto_cmac(const uint8_t *key, const uint8_t *in, int len, + uint8_t *out) +{ + struct tc_aes_key_sched_struct sched; + struct tc_cmac_struct state; + + if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) { + return -1; + } + + if (tc_cmac_update(&state, in, len) == TC_CRYPTO_FAIL) { + return -1; + } + + if (tc_cmac_final(out, &state) == TC_CRYPTO_FAIL) { + return -1; + } + + return 0; +} + +int +ble_ll_crypto_h8(const uint8_t *k, const uint8_t *s, const uint8_t *key_id, + uint8_t *out) +{ + uint8_t ik[16]; + int rc; + + rc = ble_ll_crypto_cmac(s, k, 16, ik); + if (rc) { + return rc; + } + + return ble_ll_crypto_cmac(ik, key_id, 4, out); +} diff --git a/src/nimble/nimble/controller/src/ble_ll_ctrl.c b/src/nimble/nimble/controller/src/ble_ll_ctrl.c index 340e6eb7..52a80c98 100644 --- a/src/nimble/nimble/controller/src/ble_ll_ctrl.c +++ b/src/nimble/nimble/controller/src/ble_ll_ctrl.c @@ -26,25 +26,18 @@ #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" #include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_ctrl.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll_sync.h" -#include "../include/controller/ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_ctrl.h" +#include "nimble/nimble/controller/include/controller/ble_ll_trace.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sync.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" #include "ble_ll_conn_priv.h" #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - /* To use spec sample data for testing */ #undef BLE_LL_ENCRYPT_USE_TEST_DATA @@ -55,7 +48,7 @@ */ #undef BLE_LL_ENCRYPT_DEBUG #ifdef BLE_LL_ENCRYPT_DEBUG -#include "console/console.h" +#include "nimble/console/console.h" #endif /* @@ -207,13 +200,13 @@ ble_ll_ctrl_phy_update_cancel(struct ble_ll_conn_sm *connsm, uint8_t ble_err) CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); /* Check if the host wants an event */ - if (CONN_F_HOST_PHY_UPDATE(connsm)) { + if (connsm->flags.phy_update_host_initiated) { ble_ll_hci_ev_phy_update(connsm, ble_err); - CONN_F_HOST_PHY_UPDATE(connsm) = 0; + connsm->flags.phy_update_host_initiated = 0; } /* Clear any bits for phy updates that might be in progress */ - CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; + connsm->flags.phy_update_self_initiated = 0; } #endif @@ -376,7 +369,7 @@ ble_ll_ctrl_conn_param_pdu_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr, */ ble_ll_hci_ev_rem_conn_parm_req(connsm, req); connsm->host_reply_opcode = opcode; - connsm->csmflags.cfbit.awaiting_host_reply = 1; + connsm->flags.conn_update_host_w4reply = 1; rsp_opcode = 255; } else { /* Create reply to connection request */ @@ -392,18 +385,29 @@ ble_ll_ctrl_conn_param_pdu_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr, return rsp_opcode; } -/** - * Called to make a connection update request LL control PDU - * - * Context: Link Layer - * - * @param connsm - * @param rsp - */ static void -ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld, - struct ble_ll_conn_params *cp) +ble_ll_ctrl_conn_update_init_proc(struct ble_ll_conn_sm *connsm, + struct ble_ll_conn_params *cp) { + /* This only stores conn params, if any. The caller will enqueue LL Control + * PDU and we will calculate its contents when dequeued so we know that + * instant is in the future. + */ + + connsm->flags.conn_update_sched = 0; + connsm->flags.conn_update_use_cp = (cp != NULL); + + if (cp) { + connsm->conn_cp = *cp; + } +} + +static void +ble_ll_ctrl_conn_update_make_ind_pdu(struct ble_ll_conn_sm *connsm, + uint8_t *ctrdata) +{ + struct ble_ll_conn_params *cp = NULL; + struct ble_ll_conn_params offset_cp = { }; uint16_t instant; uint32_t dt; uint32_t num_old_ce; @@ -412,6 +416,10 @@ ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld, struct hci_conn_update *hcu; struct ble_ll_conn_upd_req *req; + if (connsm->flags.conn_update_use_cp) { + cp = &connsm->conn_cp; + } + /* * Set instant. We set the instant to the current event counter plus * the amount of peripheral latency as the peripheral may not be listening @@ -426,6 +434,18 @@ ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld, instant = connsm->event_cntr + connsm->periph_latency + 6 + 1; #endif + /* Check if this is a move anchor request and configure proper connection + * parameters */ + if (connsm->conn_update_anchor_offset_req) { + offset_cp.interval_min = connsm->conn_itvl; + offset_cp.interval_max = connsm->conn_itvl; + offset_cp.latency = connsm->periph_latency; + offset_cp.timeout = connsm->supervision_tmo; + offset_cp.offset0 = connsm->conn_update_anchor_offset_req; + connsm->conn_update_anchor_offset_req = 0; + cp = &offset_cp; + } + /* * XXX: This should change in the future, but for now we will just * start the new instant at the same anchor using win offset 0. @@ -471,15 +491,12 @@ ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld, req->instant = instant; /* XXX: make sure this works for the connection parameter request proc. */ - pyld[0] = req->winsize; - put_le16(pyld + 1, req->winoffset); - put_le16(pyld + 3, req->interval); - put_le16(pyld + 5, req->latency); - put_le16(pyld + 7, req->timeout); - put_le16(pyld + 9, instant); - - /* Set flag in state machine to denote we have scheduled an update */ - connsm->csmflags.cfbit.conn_update_sched = 1; + ctrdata[0] = req->winsize; + put_le16(ctrdata + 1, req->winoffset); + put_le16(ctrdata + 3, req->interval); + put_le16(ctrdata + 5, req->latency); + put_le16(ctrdata + 7, req->timeout); + put_le16(ctrdata + 9, instant); } /** @@ -515,12 +532,12 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t * BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_CONN_PARM_REQ); #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { - ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL); + ble_ll_ctrl_conn_update_init_proc(connsm, NULL); connsm->reject_reason = BLE_ERR_SUCCESS; return BLE_LL_CTRL_CONN_UPDATE_IND; } #endif - /* Else falls through. */ + /* fall through */ case BLE_LL_CTRL_CONN_PARM_RSP: ctrl_proc = BLE_LL_CTRL_PROC_CONN_PARAM_REQ; break; @@ -555,11 +572,11 @@ ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t * if (ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ) { ble_ll_hci_ev_conn_update(connsm, BLE_ERR_UNSUPP_REM_FEATURE); } else if (ctrl_proc == BLE_LL_CTRL_PROC_FEATURE_XCHG) { - if (connsm->csmflags.cfbit.pending_hci_rd_features) { + if (connsm->flags.features_host_req) { ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_UNSUPP_REM_FEATURE); } - connsm->csmflags.cfbit.pending_hci_rd_features = 0; + connsm->flags.features_host_req = 0; } } @@ -672,24 +689,24 @@ ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm) connsm->phy_tx_transition = 0; - if (CONN_F_PEER_PHY_UPDATE(connsm)) { - CONN_F_PEER_PHY_UPDATE(connsm) = 0; - } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) { - CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; + if (connsm->flags.phy_update_peer_initiated) { + connsm->flags.phy_update_peer_initiated = 0; + } else if (connsm->flags.phy_update_self_initiated) { + connsm->flags.phy_update_self_initiated = 0; } else { /* Must be a host-initiated update */ - CONN_F_HOST_PHY_UPDATE(connsm) = 0; + connsm->flags.phy_update_host_initiated = 0; chk_host_phy = 0; - if (CONN_F_PHY_UPDATE_EVENT(connsm) == 0) { + if (connsm->flags.phy_update_host_w4event == 0) { ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS); } } /* Must check if we need to start host procedure */ if (chk_host_phy) { - if (CONN_F_HOST_PHY_UPDATE(connsm)) { + if (connsm->flags.phy_update_host_initiated) { if (ble_ll_conn_phy_update_if_needed(connsm)) { - CONN_F_HOST_PHY_UPDATE(connsm) = 0; + connsm->flags.phy_update_host_initiated = 0; } else { chk_proc_stop = 0; } @@ -814,14 +831,14 @@ ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, * one running. */ if ((m_to_s == 0) && (s_to_m == 0)) { - if (CONN_F_PEER_PHY_UPDATE(connsm)) { - CONN_F_PEER_PHY_UPDATE(connsm) = 0; - } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) { - CONN_F_CTRLR_PHY_UPDATE(connsm) = 0; + if (connsm->flags.phy_update_peer_initiated) { + connsm->flags.phy_update_peer_initiated = 0; + } else if (connsm->flags.phy_update_self_initiated) { + connsm->flags.phy_update_self_initiated = 0; ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); } else { ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS); - CONN_F_HOST_PHY_UPDATE(connsm) = 0; + connsm->flags.phy_update_host_initiated = 0; ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE); } instant = 0; @@ -829,7 +846,7 @@ ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr, /* Determine instant we will use. 6 more is minimum */ instant = connsm->event_cntr + connsm->periph_latency + 6 + 1; connsm->phy_instant = instant; - CONN_F_PHY_UPDATE_SCHED(connsm) = 1; + connsm->flags.phy_update_sched = 1; /* Set new phys to use when instant occurs */ connsm->phy_data.new_tx_phy = m_to_s; @@ -906,7 +923,7 @@ ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req, * NOTE: do not change order of these two lines as the call to * make the LL_PHY_UPDATE_IND pdu might clear the flag. */ - CONN_F_PEER_PHY_UPDATE(connsm) = 1; + connsm->flags.phy_update_peer_initiated = 1; ble_ll_ctrl_phy_update_ind_make(connsm, req, rsp, 1); rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND; } @@ -925,14 +942,14 @@ ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req, ble_ll_ctrl_phy_update_cancel(connsm, err); /* XXX: ? Should not be any phy update events */ - CONN_F_PHY_UPDATE_EVENT(connsm) = 0; + connsm->flags.phy_update_host_w4event = 0; } /* XXX: TODO: if we started another procedure with an instant * why are we doing this? Need to look into this.*/ /* Respond to central's phy update procedure */ - CONN_F_PEER_PHY_UPDATE(connsm) = 1; + connsm->flags.phy_update_peer_initiated = 1; ble_ll_ctrl_phy_req_rsp_make(connsm, rsp); rsp_opcode = BLE_LL_CTRL_PHY_RSP; @@ -1078,7 +1095,7 @@ ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr) connsm->phy_data.new_tx_phy = new_tx_phy; connsm->phy_data.new_rx_phy = new_rx_phy; connsm->phy_instant = instant; - CONN_F_PHY_UPDATE_SCHED(connsm) = 1; + connsm->flags.phy_update_sched = 1; } return BLE_ERR_MAX; } @@ -1275,7 +1292,7 @@ ble_ll_ctrl_rx_subrate_ind(struct ble_ll_conn_sm *connsm, uint8_t *req, ble_ll_conn_subrate_set(connsm, sp); ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_SUBRATE_REQ); - connsm->csmflags.cfbit.subrate_host_req = 0; + connsm->flags.subrate_host_req = 0; return BLE_ERR_MAX; } @@ -1716,7 +1733,7 @@ ble_ll_ctrl_rx_pause_enc_req(struct ble_ll_conn_sm *connsm) static uint8_t ble_ll_ctrl_rx_pause_enc_rsp(struct ble_ll_conn_sm *connsm) { - int rc; + int rc = 0; switch (connsm->conn_role) { #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) @@ -1757,7 +1774,7 @@ ble_ll_ctrl_rx_pause_enc_rsp(struct ble_ll_conn_sm *connsm) static uint8_t ble_ll_ctrl_rx_start_enc_rsp(struct ble_ll_conn_sm *connsm) { - int rc; + int rc = 0; /* Not in proper state. Discard */ if (connsm->enc_data.enc_state != CONN_ENC_S_START_ENC_RSP_WAIT) { @@ -1860,11 +1877,11 @@ static void ble_ll_ctrl_version_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld) { /* Set flag to denote we have sent/received this */ - connsm->csmflags.cfbit.version_ind_sent = 1; + connsm->flags.version_ind_txd = 1; /* Fill out response */ pyld[0] = BLE_HCI_VER_BCS; - put_le16(pyld + 1, MYNEWT_VAL(BLE_LL_MFRG_ID)); + put_le16(pyld + 1, MYNEWT_VAL(BLE_LL_MANUFACTURER_ID)); put_le16(pyld + 3, BLE_LL_SUB_VERS_NR); } @@ -1886,7 +1903,7 @@ ble_ll_ctrl_chanmap_req_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld) put_le16(pyld + BLE_LL_CHAN_MAP_LEN, connsm->chanmap_instant); /* Set scheduled flag */ - connsm->csmflags.cfbit.chanmap_update_scheduled = 1; + connsm->flags.chanmap_update_sched = 1; } /** @@ -1903,13 +1920,12 @@ uint8_t ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm, uint8_t *rsp, struct ble_ll_conn_params *req) { - uint8_t rsp_opcode; + uint8_t rsp_opcode = 0; switch (connsm->conn_role) { #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_CONN_ROLE_CENTRAL: - /* Create a connection update pdu */ - ble_ll_ctrl_conn_upd_make(connsm, rsp + 1, req); + ble_ll_ctrl_conn_update_init_proc(connsm, req); rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND; break; #endif @@ -1950,6 +1966,9 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr, ble_error = dptr[1]; } + /* Suppress unused-but-set if not used by following code (due to syscfg) */ + (void)ble_error; + /* XXX: should I check to make sure the rejected opcode is sane if we receive ind ext? */ switch (connsm->cur_ctrl_proc) { @@ -1960,7 +1979,7 @@ ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr, case BLE_LL_CONN_ROLE_CENTRAL: /* As a central we should send connection update indication in this point */ rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND; - ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL); + ble_ll_ctrl_conn_update_init_proc(connsm, NULL); connsm->reject_reason = BLE_ERR_SUCCESS; break; #endif @@ -2056,7 +2075,7 @@ ble_ll_ctrl_rx_conn_update(struct ble_ll_conn_sm *connsm, uint8_t *dptr) if (conn_events >= 32767) { ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED); } else { - connsm->csmflags.cfbit.conn_update_sched = 1; + connsm->flags.conn_update_sched = 1; /* * Errata says that receiving a connection update when the event @@ -2078,7 +2097,7 @@ ble_ll_ctrl_rx_conn_update(struct ble_ll_conn_sm *connsm, uint8_t *dptr) } void -ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm) +ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm, bool initial) { if (!(connsm->conn_features & BLE_LL_FEAT_DATA_LEN_EXT)) { return; @@ -2087,12 +2106,15 @@ ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm) /* * Section 4.5.10 Vol 6 PART B. If the max tx/rx time or octets * exceeds the minimum, data length procedure needs to occur + * "at the earliest practical opportunity". */ - if ((connsm->max_tx_octets <= BLE_LL_CONN_SUPP_BYTES_MIN) && - (connsm->max_rx_octets <= BLE_LL_CONN_SUPP_BYTES_MIN) && - (connsm->max_tx_time <= BLE_LL_CONN_SUPP_TIME_MIN) && - (connsm->max_rx_time <= BLE_LL_CONN_SUPP_TIME_MIN)) { - return; + if (initial) { + if ((connsm->max_tx_octets <= BLE_LL_CONN_SUPP_BYTES_MIN) && + (connsm->max_rx_octets <= BLE_LL_CONN_SUPP_BYTES_MIN) && + (connsm->max_tx_time <= BLE_LL_CONN_SUPP_TIME_MIN) && + (connsm->max_rx_time <= BLE_LL_CONN_SUPP_TIME_MIN)) { + return; + } } ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD, NULL); @@ -2105,7 +2127,7 @@ ble_ll_ctrl_update_features(struct ble_ll_conn_sm *connsm, uint8_t *feat) memcpy(connsm->remote_features, feat + 1, 7); /* If we received peer's features for the 1st time, we should try DLE */ - if (!connsm->csmflags.cfbit.rxd_features) { + if (!connsm->flags.features_rxd) { #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) /* * If connection was established on uncoded PHY, by default we use @@ -2116,17 +2138,25 @@ ble_ll_ctrl_update_features(struct ble_ll_conn_sm *connsm, uint8_t *feat) */ if (ble_ll_conn_rem_feature_check(connsm, BLE_LL_FEAT_LE_CODED_PHY)) { if (connsm->host_req_max_tx_time) { - connsm->max_tx_time = max(connsm->max_tx_time, + connsm->max_tx_time = MAX(connsm->max_tx_time, connsm->host_req_max_tx_time); } else { connsm->max_tx_time = g_ble_ll_conn_params.conn_init_max_tx_time_coded; } - connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; + if (connsm->host_req_max_rx_time) { + connsm->max_rx_time = MAX(connsm->max_rx_time, + connsm->host_req_max_rx_time); + } else { + connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; + } } #endif - connsm->csmflags.cfbit.pending_initiate_dle = 1; - connsm->csmflags.cfbit.rxd_features = 1; +#if MYNEWT_VAL(BLE_LL_CONN_INIT_AUTO_DLE) + connsm->flags.pending_initiate_dle = 1; +#endif + + connsm->flags.features_rxd = 1; } } @@ -2206,9 +2236,9 @@ ble_ll_ctrl_rx_feature_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr) } /* Send event to host if pending features read */ - if (connsm->csmflags.cfbit.pending_hci_rd_features) { + if (connsm->flags.features_host_req) { ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS); - connsm->csmflags.cfbit.pending_hci_rd_features = 0; + connsm->flags.features_host_req = 0; } } @@ -2237,13 +2267,14 @@ ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, * well. This is not expected to happen anyway. A return of BLE_ERR_MAX * means that we will simply discard the connection parameter request */ - if (connsm->csmflags.cfbit.awaiting_host_reply) { + if (connsm->flags.conn_update_host_w4reply) { return BLE_ERR_MAX; } #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) /* Reject any attempts to change connection parameters by peripheral */ - if (connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { + if (ble_ll_sched_css_is_enabled() && + connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) { rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ; rspbuf[2] = BLE_ERR_UNSUPPORTED; @@ -2297,7 +2328,7 @@ ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr, */ #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) if ((connsm->conn_role == BLE_LL_CONN_ROLE_CENTRAL) && - (connsm->csmflags.cfbit.chanmap_update_scheduled)) { + (connsm->flags.chanmap_update_sched)) { rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT; rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ; rspbuf[2] = BLE_ERR_DIFF_TRANS_COLL; @@ -2330,8 +2361,8 @@ ble_ll_ctrl_rx_conn_param_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, * state just clear the awaiting reply. The peripheral will hopefully stop its * procedure when we reply. */ - if (connsm->csmflags.cfbit.awaiting_host_reply) { - connsm->csmflags.cfbit.awaiting_host_reply = 0; + if (connsm->flags.conn_update_host_w4reply) { + connsm->flags.conn_update_host_w4reply = 0; } /* If we receive a response and no procedure is pending, just leave */ @@ -2366,10 +2397,10 @@ ble_ll_ctrl_rx_version_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr, connsm->vers_nr = dptr[0]; connsm->comp_id = get_le16(dptr + 1); connsm->sub_vers_nr = get_le16(dptr + 3); - connsm->csmflags.cfbit.rxd_version_ind = 1; + connsm->flags.version_ind_rxd = 1; rsp_opcode = BLE_ERR_MAX; - if (!connsm->csmflags.cfbit.version_ind_sent) { + if (!connsm->flags.version_ind_txd) { rsp_opcode = BLE_LL_CTRL_VERSION_IND; ble_ll_ctrl_version_ind_make(connsm, rspbuf); } @@ -2410,7 +2441,7 @@ ble_ll_ctrl_rx_chanmap_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr) } else { connsm->chanmap_instant = instant; memcpy(connsm->req_chanmap, dptr, BLE_LL_CHAN_MAP_LEN); - connsm->csmflags.cfbit.chanmap_update_scheduled = 1; + connsm->flags.chanmap_update_sched = 1; } return BLE_ERR_MAX; @@ -2432,7 +2463,7 @@ static struct os_mbuf * ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc, void *data) { uint8_t len; - uint8_t opcode; + uint8_t opcode = 0; uint8_t *dptr; uint8_t *ctrdata; struct os_mbuf *om; @@ -2448,7 +2479,7 @@ ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc, void *data) switch (ctrl_proc) { case BLE_LL_CTRL_PROC_CONN_UPDATE: opcode = BLE_LL_CTRL_CONN_UPDATE_IND; - ble_ll_ctrl_conn_upd_make(connsm, ctrdata, data); + ble_ll_ctrl_conn_update_init_proc(connsm, data); break; case BLE_LL_CTRL_PROC_CHAN_MAP_UPD: opcode = BLE_LL_CTRL_CHANNEL_MAP_REQ; @@ -2614,7 +2645,7 @@ ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm) ctrl_proc = BLE_LL_CTRL_PROC_TERMINATE; om = ble_ll_ctrl_proc_init(connsm, ctrl_proc, NULL); if (om) { - CONN_F_TERMINATE_STARTED(connsm) = 1; + connsm->flags.terminate_started = 1; /* Set terminate "timeout" */ usecs = connsm->supervision_tmo * BLE_HCI_CONN_SPVN_TMO_UNITS * 1000; @@ -2680,7 +2711,7 @@ ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm) * terminate if needed */ if (connsm->disconnect_reason) { - if (!CONN_F_TERMINATE_STARTED(connsm)) { + if (!connsm->flags.terminate_started) { /* * If the terminate procedure has not started it means we were not * able to start it right away (no control pdu was available). @@ -2705,7 +2736,7 @@ ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm) * received the information dont start it. */ if ((i == BLE_LL_CTRL_PROC_VERSION_XCHG) && - (connsm->csmflags.cfbit.rxd_version_ind)) { + (connsm->flags.version_ind_rxd)) { ble_ll_hci_ev_rd_rem_ver(connsm, BLE_ERR_SUCCESS); CLR_PENDING_CTRL_PROC(connsm, i); } else { @@ -2737,7 +2768,6 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) uint64_t feature; uint8_t len; uint8_t opcode; - uint8_t rsp_opcode; uint8_t *dptr; uint8_t *rspbuf; uint8_t *rspdata; @@ -2745,6 +2775,7 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) int restart_encryption; #endif int rc = 0; + uint8_t rsp_opcode = 0; /* XXX: where do we validate length received and packet header length? * do this in LL task when received. Someplace!!! What I mean @@ -3037,10 +3068,12 @@ ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om) #endif } - if (connsm->csmflags.cfbit.pending_initiate_dle) { - connsm->csmflags.cfbit.pending_initiate_dle = 0; - ble_ll_ctrl_initiate_dle(connsm); +#if MYNEWT_VAL(BLE_LL_CONN_INIT_AUTO_DLE) + if (connsm->flags.pending_initiate_dle) { + connsm->flags.pending_initiate_dle = 0; + ble_ll_ctrl_initiate_dle(connsm, true); } +#endif return rc; } @@ -3095,12 +3128,21 @@ int ble_ll_ctrl_tx_start(struct ble_ll_conn_sm *connsm, struct os_mbuf *txpdu) { uint8_t opcode; + uint8_t *ctrdata; opcode = txpdu->om_data[0]; + ctrdata = &txpdu->om_data[1]; + switch (opcode) { + case BLE_LL_CTRL_CONN_UPDATE_IND: + ble_ll_ctrl_conn_update_make_ind_pdu(connsm, ctrdata); + connsm->flags.conn_update_sched = 1; + break; +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) case BLE_LL_CTRL_SUBRATE_IND: - connsm->csmflags.cfbit.subrate_trans = 1; + connsm->flags.subrate_trans = 1; break; +#endif } return 0; @@ -3132,7 +3174,7 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) opcode = txpdu->om_data[0]; switch (opcode) { case BLE_LL_CTRL_TERMINATE_IND: - connsm->csmflags.cfbit.terminate_ind_txd = 1; + connsm->flags.terminate_ind_txd = 1; rc = -1; break; case BLE_LL_CTRL_REJECT_IND_EXT: @@ -3144,7 +3186,7 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) if (txpdu->om_data[1] == BLE_LL_CTRL_CONN_PARM_REQ && txpdu->om_data[2] != BLE_ERR_LMP_COLLISION) { connsm->reject_reason = txpdu->om_data[2]; - connsm->csmflags.cfbit.host_expects_upd_event = 1; + connsm->flags.conn_update_host_w4event = 1; } } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) @@ -3166,13 +3208,13 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) break; case BLE_LL_CTRL_ENC_RSP: connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT; - connsm->csmflags.cfbit.send_ltk_req = 1; + connsm->flags.encrypt_ltk_req = 1; break; #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_CTRL_START_ENC_RSP: if (connsm->conn_role == BLE_LL_CONN_ROLE_PERIPHERAL) { connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED; - if (CONN_F_LE_PING_SUPP(connsm)) { + if (connsm->flags.le_ping_supp) { ble_ll_conn_auth_pyld_timer_start(connsm); } } @@ -3202,8 +3244,8 @@ ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_LL_CTRL_SUBRATE_IND: - connsm->csmflags.cfbit.subrate_trans = 0; - connsm->csmflags.cfbit.subrate_ind_txd = 1; + connsm->flags.subrate_trans = 0; + connsm->flags.subrate_ind_txd = 1; break; #endif /* BLE_LL_CTRL_SUBRATE_IND */ #endif /* BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE */ @@ -3220,6 +3262,11 @@ ble_ll_ctrl_init_conn_sm(struct ble_ll_conn_sm *connsm) { ble_npl_callout_init(&connsm->ctrl_proc_rsp_timer, &g_ble_ll_data.ll_evq, ble_ll_ctrl_proc_rsp_timer_cb, connsm); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) + ble_npl_callout_init(&connsm->auth_pyld_timer, &g_ble_ll_data.ll_evq, + ble_ll_conn_auth_pyld_timer_cb, connsm); +#endif } #endif diff --git a/src/nimble/nimble/controller/src/ble_ll_ctrl_priv.h b/src/nimble/nimble/controller/src/ble_ll_ctrl_priv.h index 0a3719ae..01001f2b 100644 --- a/src/nimble/nimble/controller/src/ble_ll_ctrl_priv.h +++ b/src/nimble/nimble/controller/src/ble_ll_ctrl_priv.h @@ -20,7 +20,7 @@ #ifndef H_BLE_LL_CTRL_PRIV_ #define H_BLE_LL_CTRL_PRIV_ -#include "../include/controller/ble_ll_conn.h" +#include "nimble/nimble/controller/include/controller/ble_ll_conn.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/nimble/controller/src/ble_ll_dtm.c b/src/nimble/nimble/controller/src/ble_ll_dtm.c index 748b7d2a..76255b23 100644 --- a/src/nimble/nimble/controller/src/ble_ll_dtm.c +++ b/src/nimble/nimble/controller/src/ble_ll_dtm.c @@ -25,13 +25,15 @@ #include #include "nimble/porting/nimble/include/os/os.h" -#include "nimble/nimble/porting/nimble/include/stats/stats.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_ll_tmr.h" +#include "nimble/porting/nimble/include/stats/stats.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_pdu.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" #include "ble_ll_dtm_priv.h" +#include "ble_ll_priv.h" STATS_SECT_START(ble_ll_dtm_stats) STATS_SECT_ENTRY(rx_count) @@ -195,16 +197,6 @@ ble_ll_dtm_ev_tx_resched_cb(struct ble_npl_event *evt) { BLE_LL_ASSERT(rc == 0); } -static int ble_ll_dtm_rx_start(void); - -static void -ble_ll_dtm_ev_rx_restart_cb(struct ble_npl_event *evt) { - if (ble_ll_dtm_rx_start() != 0) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); - STATS_INC(ble_ll_dtm_stats, rx_failed); - } -} - static void ble_ll_dtm_tx_done(void *arg) { @@ -218,7 +210,7 @@ ble_ll_dtm_tx_done(void *arg) g_ble_ll_dtm_ctx.num_of_packets++; /* Reschedule event in LL context */ - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt); + ble_ll_event_add(&ctx->evt); ble_ll_state_set(BLE_LL_STATE_STANDBY); } @@ -244,7 +236,7 @@ ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item *sch) ble_phy_mode_set(ctx->phy_mode, ctx->phy_mode); #endif ble_phy_set_txend_cb(ble_ll_dtm_tx_done, ctx); - ble_phy_txpwr_set(0); + ble_ll_tx_power_set(g_ble_ll_tx_power); sch->start_time += g_ble_ll_sched_offset_ticks; @@ -264,7 +256,7 @@ ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item *sch) resched: /* Reschedule from LL task if late for this PDU */ - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt); + ble_ll_event_add(&ctx->evt); STATS_INC(ble_ll_dtm_stats, tx_failed); @@ -279,7 +271,7 @@ ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len, uint32_t itvl_usec; /* Calculate interval as per spec Bluetooth 5.0 Vol 6. Part F, 4.1.6 */ - l = ble_ll_pdu_tx_time_get(len + BLE_LL_PDU_HDR_LEN, phy_mode); + l = ble_ll_pdu_us(len, phy_mode); itvl_usec = ((l + 249 + 624) / 625) * 625; #if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS) @@ -402,7 +394,7 @@ ble_ll_dtm_rx_start(void) #endif OS_ENTER_CRITICAL(sr); - rc = ble_phy_rx_set_start_time(ble_ll_tmr_get(), 0); + rc = ble_phy_rx_set_start_time(ble_ll_rfmgmt_enable_now(), 0); OS_EXIT_CRITICAL(sr); if (rc && rc != BLE_PHY_ERR_RX_LATE) { return rc; @@ -413,22 +405,9 @@ ble_ll_dtm_rx_start(void) return 0; } -static int -ble_ll_dtm_rx_sched_cb(struct ble_ll_sched_item *sch) -{ - if (ble_ll_dtm_rx_start() != 0) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); - STATS_INC(ble_ll_dtm_stats, rx_failed); - return BLE_LL_SCHED_STATE_DONE; - } - - return BLE_LL_SCHED_STATE_RUNNING; -} - static int ble_ll_dtm_rx_create_ctx(uint8_t rf_channel, uint8_t phy_mode) { - struct ble_ll_sched_item *sch = &g_ble_ll_dtm_ctx.sch; int rc; g_ble_ll_dtm_ctx.phy_mode = phy_mode; @@ -436,16 +415,8 @@ ble_ll_dtm_rx_create_ctx(uint8_t rf_channel, uint8_t phy_mode) STATS_CLEAR(ble_ll_dtm_stats, rx_count); - ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_rx_restart_cb, - NULL); - - sch->sched_cb = ble_ll_dtm_rx_sched_cb; - sch->cb_arg = &g_ble_ll_dtm_ctx; - sch->sched_type = BLE_LL_SCHED_TYPE_DTM; - sch->start_time = ble_ll_rfmgmt_enable_now(); - - rc = ble_ll_sched_dtm(sch); - BLE_LL_ASSERT(rc == 0); + rc = ble_ll_dtm_rx_start(); + assert(rc == 0); ble_phy_enable_dtm(); @@ -465,7 +436,7 @@ ble_ll_dtm_ctx_free(struct dtm_ctx * ctx) } ble_ll_sched_rmv_elem(&ctx->sch); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); + ble_ll_event_remove(&g_ble_ll_dtm_ctx.evt); ble_phy_disable(); ble_phy_disable_dtm(); @@ -483,7 +454,7 @@ ble_ll_dtm_tx_test(uint8_t tx_chan, uint8_t len, uint8_t packet_payload, { uint8_t phy_mode; - if (g_ble_ll_dtm_ctx.active) { + if (g_ble_ll_dtm_ctx.active || ble_ll_is_busy(0)) { return BLE_ERR_CTLR_BUSY; } @@ -585,7 +556,7 @@ ble_ll_dtm_rx_test(uint8_t rx_chan, uint8_t hci_phy) { uint8_t phy_mode; - if (g_ble_ll_dtm_ctx.active) { + if (g_ble_ll_dtm_ctx.active || ble_ll_is_busy(0)) { return BLE_ERR_CTLR_BUSY; } @@ -665,10 +636,7 @@ ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) STATS_INC(ble_ll_dtm_stats, rx_count); } - if (ble_ll_dtm_rx_start() != 0) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt); - STATS_INC(ble_ll_dtm_stats, rx_failed); - } + ble_phy_restart_rx(); } int @@ -705,6 +673,12 @@ ble_ll_dtm_reset(void) ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx); } +int +ble_ll_dtm_enabled(void) +{ + return g_ble_ll_dtm_ctx.active; +} + void ble_ll_dtm_init(void) { diff --git a/src/nimble/nimble/controller/src/ble_ll_dtm_priv.h b/src/nimble/nimble/controller/src/ble_ll_dtm_priv.h index 6b501273..95f03acf 100644 --- a/src/nimble/nimble/controller/src/ble_ll_dtm_priv.h +++ b/src/nimble/nimble/controller/src/ble_ll_dtm_priv.h @@ -37,4 +37,5 @@ int ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr); void ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr); void ble_ll_dtm_wfr_timer_exp(void); void ble_ll_dtm_reset(void); +int ble_ll_dtm_enabled(void); #endif diff --git a/src/nimble/nimble/controller/src/ble_ll_hci.c b/src/nimble/nimble/controller/src/ble_ll_hci.c index f6b1ea9e..021e2ada 100644 --- a/src/nimble/nimble/controller/src/ble_ll_hci.c +++ b/src/nimble/nimble/controller/src/ble_ll_hci.c @@ -15,7 +15,7 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - */ + */ #ifndef ESP_PLATFORM #include @@ -24,16 +24,21 @@ #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os.h" #include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/include/nimble/nimble_opt.h" #include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_sync.h" -#include "../include/controller/ble_ll_iso.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_ll_adv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_whitelist.h" +#include "nimble/nimble/controller/include/controller/ble_ll_resolv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sync.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_ll_isoal.h" +#include "nimble/nimble/controller/include/controller/ble_ll_iso.h" +#include "nimble/nimble/controller/include/controller/ble_ll_iso_big.h" #include "ble_ll_priv.h" #include "ble_ll_conn_priv.h" #include "ble_ll_hci_priv.h" @@ -42,14 +47,6 @@ #include "ble_ll_dtm_priv.h" #endif -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - static void ble_ll_hci_cmd_proc(struct ble_npl_event *ev); /* OS event to enqueue command */ @@ -63,6 +60,9 @@ static uint64_t g_ble_ll_hci_event_mask2; static int16_t rx_path_pwr_compensation; static int16_t tx_path_pwr_compensation; +static ble_ll_hci_post_cmd_complete_cb hci_cmd_post_cb = NULL; +static void *hci_cmd_post_cb_user_data = NULL; + #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) static enum { ADV_MODE_ANY, @@ -220,7 +220,7 @@ ble_ll_hci_rd_local_version(uint8_t *rspbuf, uint8_t *rsplen) rsp->hci_ver = BLE_HCI_VER_BCS; rsp->hci_rev = 0; rsp->lmp_ver = BLE_LMP_VER_BCS; - rsp->manufacturer = htole16(MYNEWT_VAL(BLE_LL_MFRG_ID)); + rsp->manufacturer = htole16(MYNEWT_VAL(BLE_LL_MANUFACTURER_ID)); rsp->lmp_subver = 0; *rsplen = sizeof(*rsp); @@ -264,8 +264,7 @@ ble_ll_hci_rd_local_supp_cmd(uint8_t *rspbuf, uint8_t *rsplen) { struct ble_hci_ip_rd_loc_supp_cmd_rp *rsp = (void *) rspbuf; - memset(rsp->commands, 0, sizeof(rsp->commands)); - memcpy(rsp->commands, g_ble_ll_supp_cmds, sizeof(g_ble_ll_supp_cmds)); + ble_ll_hci_supp_cmd_get(rsp->commands); *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; @@ -343,7 +342,7 @@ ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen) return BLE_ERR_SUCCESS; } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) +#if MYNEWT_VAL(BLE_LL_ISO) /** * HCI read buffer size v2 command. Returns the ACL and ISO data packet length and * num data packets. @@ -360,8 +359,8 @@ ble_ll_hci_le_read_bufsize_v2(uint8_t *rspbuf, uint8_t *rsplen) rp->data_len = htole16(g_ble_ll_data.ll_acl_pkt_size); rp->data_packets = g_ble_ll_data.ll_num_acl_pkts; - rp->iso_data_len = 0; - rp->iso_data_packets = 0; + rp->iso_data_len = htole16(g_ble_ll_data.ll_iso_pkt_size); + rp->iso_data_packets = g_ble_ll_data.ll_num_iso_pkts; *rsplen = sizeof(*rp); return BLE_ERR_SUCCESS; @@ -444,6 +443,15 @@ ble_ll_hci_le_set_def_phy(const uint8_t *cmdbuf, uint8_t len) #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +int +ble_ll_hci_check_dle(uint16_t max_octets, uint16_t max_time) +{ + return (max_octets >= BLE_LL_CONN_SUPP_BYTES_MIN) && + (max_octets <= BLE_LL_CONN_SUPP_BYTES_MAX) && + (max_time >= BLE_LL_CONN_SUPP_TIME_MIN) && + (max_time <= BLE_LL_CONN_SUPP_TIME_MAX); +} + /** * HCI write suggested default data length command. * @@ -462,51 +470,47 @@ ble_ll_hci_le_set_def_phy(const uint8_t *cmdbuf, uint8_t len) static int ble_ll_hci_le_wr_sugg_data_len(const uint8_t *cmdbuf, uint8_t len) { - const struct ble_hci_le_wr_sugg_def_data_len_cp *cmd = (const void*) cmdbuf; - uint16_t tx_oct; + const struct ble_hci_le_wr_sugg_def_data_len_cp *cmd = (const void *)cmdbuf; + uint16_t tx_octets; uint16_t tx_time; - int rc; if (len != sizeof(*cmd)) { return BLE_ERR_INV_HCI_CMD_PARMS; } /* Get suggested octets and time */ - tx_oct = le16toh(cmd->max_tx_octets); + tx_octets = le16toh(cmd->max_tx_octets); tx_time = le16toh(cmd->max_tx_time); - /* If valid, write into suggested and change connection initial times */ - if (ble_ll_chk_txrx_octets(tx_oct) && ble_ll_chk_txrx_time(tx_time)) { - g_ble_ll_conn_params.sugg_tx_octets = (uint8_t)tx_oct; - g_ble_ll_conn_params.sugg_tx_time = tx_time; + if (!ble_ll_hci_check_dle(tx_octets, tx_time)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } - /* - * We can disregard host suggestion, but we are a nice controller so - * let's use host suggestion, unless they exceed max supported values - * in which case we just use our max. - */ - g_ble_ll_conn_params.conn_init_max_tx_octets = - min(tx_oct, g_ble_ll_conn_params.supp_max_tx_octets); - g_ble_ll_conn_params.conn_init_max_tx_time = - min(tx_time, g_ble_ll_conn_params.supp_max_tx_time); + g_ble_ll_conn_params.sugg_tx_octets = tx_octets; + g_ble_ll_conn_params.sugg_tx_time = tx_time; - /* - * Use the same for coded and uncoded defaults. These are used when PHY - * parameters are initialized and we want to use values overridden by - * host. Make sure we do not exceed max supported time on uncoded. - */ - g_ble_ll_conn_params.conn_init_max_tx_time_uncoded = - min(BLE_LL_CONN_SUPP_TIME_MAX_UNCODED, - g_ble_ll_conn_params.conn_init_max_tx_time); - g_ble_ll_conn_params.conn_init_max_tx_time_coded = - g_ble_ll_conn_params.conn_init_max_tx_time; + /* + * We can disregard host suggestion, but we are a nice controller so + * let's use host suggestion, unless they exceed max supported values + * in which case we just use our max. + */ + g_ble_ll_conn_params.conn_init_max_tx_octets = + MIN(tx_octets, g_ble_ll_conn_params.supp_max_tx_octets); + g_ble_ll_conn_params.conn_init_max_tx_time = + MIN(tx_time, g_ble_ll_conn_params.supp_max_tx_time); - rc = BLE_ERR_SUCCESS; - } else { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - } + /* + * Use the same for coded and uncoded defaults. These are used when PHY + * parameters are initialized and we want to use values overridden by + * host. Make sure we do not exceed max supported time on uncoded. + */ + g_ble_ll_conn_params.conn_init_max_tx_time_uncoded = + MIN(BLE_LL_CONN_SUPP_TIME_MAX_UNCODED, + g_ble_ll_conn_params.conn_init_max_tx_time); + g_ble_ll_conn_params.conn_init_max_tx_time_coded = + g_ble_ll_conn_params.conn_init_max_tx_time; - return rc; + return 0; } /** @@ -661,6 +665,11 @@ ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf) case BLE_HCI_OCF_LE_GEN_DHKEY: case BLE_HCI_OCF_LE_SET_PHY: case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC: +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + case BLE_HCI_OCF_LE_CREATE_BIG: + case BLE_HCI_OCF_LE_CREATE_BIG_TEST: + case BLE_HCI_OCF_LE_TERMINATE_BIG: +#endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) case BLE_HCI_OCF_LE_REQ_PEER_SCA: #endif @@ -790,8 +799,8 @@ ble_ll_read_tx_power(uint8_t *rspbuf, uint8_t *rsplen) { struct ble_hci_le_rd_transmit_power_rp *rsp = (void *) rspbuf; - rsp->min_tx_power = ble_phy_txpower_round(-127); - rsp->max_tx_power = ble_phy_txpower_round(126); + rsp->min_tx_power = ble_ll_tx_power_round(-127); + rsp->max_tx_power = ble_ll_tx_power_round(126); *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; @@ -830,15 +839,43 @@ ble_ll_write_rf_path_compensation(const uint8_t *cmdbuf, uint8_t len) tx_path_pwr_compensation = tx; rx_path_pwr_compensation = rx; - ble_phy_set_rx_pwr_compensation(rx_path_pwr_compensation / 10); + g_ble_ll_tx_power_compensation = tx / 10; + g_ble_ll_rx_power_compensation = rx / 10; return BLE_ERR_SUCCESS; } -int8_t -ble_ll_get_tx_pwr_compensation(void) +static int +ble_ll_hci_le_set_host_chan_class(const uint8_t *cmdbuf, uint8_t len) { - return tx_path_pwr_compensation / 10; + const struct ble_hci_le_set_host_chan_class_cp *cmd = (const void *)cmdbuf; + uint8_t chan_map_used; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* HCI command allows only single channel to be enabled, but LL needs at + * least 2 channels to work so let's reject in such case. + */ + chan_map_used = ble_ll_utils_chan_map_used_get(cmd->chan_map); + if ((chan_map_used < 2) || (cmd->chan_map[4] & 0xe0)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!memcmp(g_ble_ll_data.chan_map, cmd->chan_map, BLE_LL_CHAN_MAP_LEN)) { + return BLE_ERR_SUCCESS; + } + + memcpy(g_ble_ll_data.chan_map, cmd->chan_map, BLE_LL_CHAN_MAP_LEN); + g_ble_ll_data.chan_map_used = chan_map_used; + + ble_ll_conn_chan_map_update(); +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + ble_ll_iso_big_chan_map_update(); +#endif + + return BLE_ERR_SUCCESS; } /** @@ -857,8 +894,7 @@ ble_ll_get_tx_pwr_compensation(void) */ static int ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, - uint8_t *rspbuf, uint8_t *rsplen, - ble_ll_hci_post_cmd_complete_cb *cb) + uint8_t *rspbuf, uint8_t *rsplen) { int rc; @@ -938,7 +974,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, break; case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL: if (len == 0) { - rc = ble_ll_conn_create_cancel(cb); + rc = ble_ll_conn_create_cancel(); } break; #endif @@ -965,7 +1001,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, break; #endif case BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS: - rc = ble_ll_conn_hci_set_chan_class(cmdbuf, len); + rc = ble_ll_hci_le_set_host_chan_class(cmdbuf, len); break; #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) case BLE_HCI_OCF_LE_RD_CHAN_MAP: @@ -1165,7 +1201,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, break; case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL: if (len == 0) { - rc = ble_ll_sync_cancel(cb); + rc = ble_ll_sync_cancel(); } break; case BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC: @@ -1230,6 +1266,17 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, rc = ble_ll_set_default_sync_transfer_params(cmdbuf, len); break; #endif +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + case BLE_HCI_OCF_LE_CREATE_BIG: + rc = ble_ll_iso_big_hci_create(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_CREATE_BIG_TEST: + rc = ble_ll_iso_big_hci_create_test(cmdbuf, len); + break; + case BLE_HCI_OCF_LE_TERMINATE_BIG: + rc = ble_ll_iso_big_hci_terminate(cmdbuf, len); + break; +#endif /* BLE_LL_ISO_BROADCASTER */ #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) case BLE_HCI_OCF_LE_READ_ISO_TX_SYNC: rc = ble_ll_iso_read_tx_sync(cmdbuf, len); @@ -1249,30 +1296,29 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, case BLE_HCI_OCF_LE_REJECT_CIS_REQ: rc = ble_ll_iso_reject_cis_req(cmdbuf, len); break; - case BLE_HCI_OCF_LE_CREATE_BIG: - rc = ble_ll_iso_create_big(cmdbuf, len); - break; - case BLE_HCI_OCF_LE_TERMINATE_BIG: - rc = ble_ll_iso_terminate_big(cmdbuf, len); - break; case BLE_HCI_OCF_LE_BIG_CREATE_SYNC: rc = ble_ll_iso_big_create_sync(cmdbuf, len); break; case BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC: rc = ble_ll_iso_big_terminate_sync(cmdbuf,len); break; +#endif +#if MYNEWT_VAL(BLE_LL_ISO) case BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH: - rc = ble_ll_iso_setup_iso_data_path(cmdbuf, len); + rc = ble_ll_isoal_hci_setup_iso_data_path(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH: - rc = ble_ll_iso_remove_iso_data_path(cmdbuf, len); + rc = ble_ll_isoal_hci_remove_iso_data_path(cmdbuf, len, rspbuf, rsplen); + break; + case BLE_HCI_OCF_LE_READ_ISO_TX_SYNC: + rc = ble_ll_isoal_hci_read_tx_sync(cmdbuf, len, rspbuf, rsplen); break; case BLE_HCI_OCF_LE_RD_BUF_SIZE_V2: if (len == 0) { rc = ble_ll_hci_le_read_bufsize_v2(rspbuf, rsplen); } break; -#endif +#endif /* BLE_LL_ISO */ #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO_TEST) case BLE_HCI_OCF_LE_SET_CIG_PARAM_TEST: rc = ble_ll_iso_set_cig_param_test(cmdbuf, len, rspbuf, rsplen); @@ -1294,7 +1340,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf, break; #endif #if MYNEWT_VAL(BLE_VERSION) >= 52 - case BLE_HCI_OCF_LE_SET_HOST_FEAT: + case BLE_HCI_OCF_LE_SET_HOST_FEATURE: rc = ble_ll_set_host_feat(cmdbuf, len); break; #endif @@ -1442,17 +1488,9 @@ ble_ll_hci_cb_host_buf_size(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } - /* - * Core 5.2 Vol 4 Part E section 7.3.39 states that "Both the Host and the - * Controller shall support command and event packets, where the data portion - * (excluding header) contained in the packets is 255 octets in size.". - * This means we can basically accept any allowed value since LL does not - * reassemble incoming data thus will not send more than 255 octets in single - * data packet. - */ acl_num = le16toh(cmd->acl_num); acl_data_len = le16toh(cmd->acl_data_len); - if (acl_data_len < 255) { + if ((acl_num < 1) || (acl_data_len < 1)) { return BLE_ERR_INV_HCI_CMD_PARMS; } @@ -1589,6 +1627,43 @@ ble_ll_hci_status_params_cmd_proc(const uint8_t *cmdbuf, uint8_t len, } #if MYNEWT_VAL(BLE_LL_HBD_FAKE_DUAL_MODE) +static void +ble_ll_hci_cmd_fake_dual_mode_inquiry_complete(struct ble_npl_event *ev) +{ + struct ble_hci_ev *hci_ev; + + hci_ev = ble_transport_alloc_evt(1); + if (!hci_ev) { + return; + } + + hci_ev->opcode = BLE_HCI_EVCODE_INQUIRY_CMP; + hci_ev->length = 1; + hci_ev->data[0] = 0; + + ble_ll_hci_event_send(hci_ev); +} + +static void +ble_ll_hci_cmd_fake_dual_mode_inquiry(uint32_t length) +{ + static struct ble_npl_callout inquiry_timer; + static bool init; + + if (!init) { + ble_npl_callout_init(&inquiry_timer, &g_ble_ll_data.ll_evq, + ble_ll_hci_cmd_fake_dual_mode_inquiry_complete, + NULL); + } + + if (length) { + ble_npl_callout_reset(&inquiry_timer, + ble_npl_time_ms_to_ticks32(length * 1280)); + } else { + ble_npl_callout_stop(&inquiry_timer); + } +} + static int ble_ll_hci_cmd_fake_dual_mode(uint16_t opcode, uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf, uint8_t *rsplen) @@ -1597,10 +1672,16 @@ ble_ll_hci_cmd_fake_dual_mode(uint16_t opcode, uint8_t *cmdbuf, uint8_t len, switch (opcode) { case BLE_HCI_OP(BLE_HCI_OGF_LINK_CTRL, 0x01): /* Inquiry */ + ble_ll_hci_cmd_fake_dual_mode_inquiry(cmdbuf[3]); rc = BLE_ERR_MAX + 1; break; case BLE_HCI_OP(BLE_HCI_OGF_LINK_CTRL, 0x02): /* Inquiry Cancel */ + ble_ll_hci_cmd_fake_dual_mode_inquiry(0); + rc = 0; + break; + case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x05): /* Set Event Filter */ case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x13): /* Write Local Name */ + case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x16): /* Write Connection Accept Timeout */ case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x18): /* Write Page Timeout */ case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x1a): /* Write Scan Enable */ case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x1c): /* Write Page Scan Activity */ @@ -1610,9 +1691,37 @@ ble_ll_hci_cmd_fake_dual_mode(uint16_t opcode, uint8_t *cmdbuf, uint8_t len, case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x33): /* Host Buffer Size */ case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x45): /* Write Inquiry Mode */ case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x52): /* Write Extended Inquiry Response */ + case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x56): /* Write Simple Pairing Mode */ case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x6d): /* Write LE Host Support */ rc = 0; break; + case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x14): /* Read Local Name */ + memset(rspbuf, 0, 248); + strcpy((char *)rspbuf, "NimBLE"); + *rsplen = 248; + rc = 0; + break; + case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x23): /* Read Class Of Device */ + put_le24(rspbuf, 0); + *rsplen = 3; + rc = 0; + break; + case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x25): /* Read Voice Settings */ + put_le16(rspbuf, 0); + *rsplen = 2; + rc = 0; + break; + case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x38): /* Read Number Of Supported IAC */ + rspbuf[0] = 1; + *rsplen = 1; + rc = 0; + break; + case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x39): /* Read Current IAC LAP */ + rspbuf[0] = 1; + put_le24(&rspbuf[1], 0x9e8b33); + *rsplen = 4; + rc = 0; + break; case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, 0x58): /* Read Inquiry Response Transmit Power Level */ rspbuf[0] = 0x04; *rsplen = 1; @@ -1623,6 +1732,13 @@ ble_ll_hci_cmd_fake_dual_mode(uint16_t opcode, uint8_t *cmdbuf, uint8_t len, *rsplen = 8; rc = 0; break; + case BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, 0x04): /* Read Local Extended Features */ + rspbuf[0] = 0; + rspbuf[1] = 0; + put_le64(&rspbuf[2], 0x877bffdbfe0ffebf); + *rsplen = 10; + rc = 0; + break; case BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, BLE_HCI_OCF_IP_RD_BUF_SIZE): put_le16(rspbuf, 255); rspbuf[2] = 0; @@ -1644,6 +1760,15 @@ ble_ll_hci_cmd_fake_dual_mode(uint16_t opcode, uint8_t *cmdbuf, uint8_t len, } #endif + +void +ble_ll_hci_post_cmd_cb_set(ble_ll_hci_post_cmd_complete_cb cb, void *user_data) +{ + BLE_LL_ASSERT(hci_cmd_post_cb == NULL); + hci_cmd_post_cb = cb; + hci_cmd_post_cb_user_data = user_data; +} + /** * Called to process an HCI command from the host. * @@ -1658,7 +1783,6 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) struct ble_hci_cmd *cmd; uint16_t opcode; uint16_t ocf; - ble_ll_hci_post_cmd_complete_cb post_cb = NULL; struct ble_hci_ev *hci_ev; struct ble_hci_ev_command_status *cmd_status; struct ble_hci_ev_command_complete *cmd_complete; @@ -1687,6 +1811,22 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) /* Assume response length is zero */ rsplen = 0; +#if MYNEWT_VAL(BLE_LL_DTM) + /* if DTM test is enabled disallow any command other than LE Test End or + * HCI Reset + */ + if (ble_ll_dtm_enabled()) { + switch (opcode) { + case BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_TEST_END): + case BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_RESET): + break; + default: + rc = BLE_ERR_CMD_DISALLOWED; + goto send_cc_cs; + } + } +#endif + #if MYNEWT_VAL(BLE_LL_HBD_FAKE_DUAL_MODE) rc = ble_ll_hci_cmd_fake_dual_mode(opcode, cmd->data, cmd->length, rspbuf, &rsplen); @@ -1709,7 +1849,7 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) rc = ble_ll_hci_status_params_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); break; case BLE_HCI_OGF_LE: - rc = ble_ll_hci_le_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen, &post_cb); + rc = ble_ll_hci_le_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen); break; #if MYNEWT_VAL(BLE_LL_HCI_VS) case BLE_HCI_OGF_VENDOR: @@ -1729,7 +1869,7 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) rc += (BLE_ERR_MAX + 1); } -#if MYNEWT_VAL(BLE_LL_HBD_FAKE_DUAL_MODE) +#if MYNEWT_VAL(BLE_LL_HBD_FAKE_DUAL_MODE) || MYNEWT_VAL(BLE_LL_DTM) send_cc_cs: #endif /* If no response is generated, we free the buffers */ @@ -1767,26 +1907,18 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev) ble_ll_hci_event_send(hci_ev); /* Call post callback if set by command handler */ - if (post_cb) { - post_cb(); + if (hci_cmd_post_cb) { + hci_cmd_post_cb(hci_cmd_post_cb_user_data); + + hci_cmd_post_cb = NULL; + hci_cmd_post_cb_user_data = NULL; } BLE_LL_DEBUG_GPIO(HCI_CMD, 0); } -/** - * Sends an HCI command to the controller. On success, the supplied buffer is - * relinquished to the controller task. On failure, the caller must free the - * buffer. - * - * @param cmd A flat buffer containing the HCI command to - * send. - * - * @return 0 on success; - * BLE_ERR_MEM_CAPACITY on HCI buffer exhaustion. - */ int -ble_ll_hci_cmd_rx(uint8_t *cmdbuf, void *arg) +ble_ll_hci_cmd_rx(uint8_t *cmdbuf) { struct ble_npl_event *ev; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) @@ -1822,14 +1954,13 @@ ble_ll_hci_cmd_rx(uint8_t *cmdbuf, void *arg) /* Fill out the event and post to Link Layer */ ble_npl_event_set_arg(ev, cmdbuf); - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev); + ble_ll_event_add(ev); return 0; } -/* Send ACL data from host to contoller */ int -ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg) +ble_ll_hci_acl_rx(struct os_mbuf *om) { #if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) ble_ll_acl_data_in(om); @@ -1840,6 +1971,17 @@ ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg) return 0; } +int +ble_ll_hci_iso_rx(struct os_mbuf *om) +{ +#if MYNEWT_VAL(BLE_LL_ISO) + ble_ll_isoal_data_in(om); +#else + os_mbuf_free_chain(om); +#endif + return 0; +} + /** * Initalize the LL HCI. * diff --git a/src/nimble/nimble/controller/src/ble_ll_hci_ev.c b/src/nimble/nimble/controller/src/ble_ll_hci_ev.c index 700d1607..51b72e81 100644 --- a/src/nimble/nimble/controller/src/ble_ll_hci_ev.c +++ b/src/nimble/nimble/controller/src/ble_ll_hci_ev.c @@ -16,17 +16,20 @@ * specific language governing permissions and limitations * under the License. */ + #ifndef ESP_PLATFORM -#include #include +#include +#include +#include #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_ctrl.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_ctrl.h" #include "ble_ll_conn_priv.h" #if (BLETEST_CONCURRENT_CONN_TEST == 1) @@ -134,7 +137,7 @@ ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status) struct ble_hci_ev_enrypt_chg *ev_enc_chf; struct ble_hci_ev *hci_ev; - if (CONN_F_ENC_CHANGE_SENT(connsm) == 0) { + if (connsm->flags.encrypt_event_sent == 0) { if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_ENCRYPT_CHG)) { hci_ev = ble_transport_alloc_evt(0); if (hci_ev) { @@ -150,7 +153,7 @@ ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status) } } - CONN_F_ENC_CHANGE_SENT(connsm) = 1; + connsm->flags.encrypt_event_sent = 1; return; } @@ -330,7 +333,7 @@ ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm) ev->subev_code = BLE_HCI_LE_SUBEV_CHAN_SEL_ALG; ev->conn_handle = htole16(connsm->conn_handle); - ev->csa = connsm->csmflags.cfbit.csa2_supp ? 0x01 : 0x00; + ev->csa = connsm->flags.csa2 ? 0x01 : 0x00; ble_ll_hci_event_send(hci_ev); } @@ -525,10 +528,36 @@ ble_ll_hci_ev_subrate_change(struct ble_ll_conn_sm *connsm, uint8_t status) } #endif +#if MYNEWT_VAL(BLE_LL_HCI_VS_CONN_STRICT_SCHED) +void +ble_ll_hci_ev_send_vs_css_slot_changed(uint16_t conn_handle, uint16_t slot_idx) +{ + struct ble_hci_ev_vs_css_slot_changed *ev; + struct ble_hci_ev_vs *ev_vs; + struct ble_hci_ev *hci_ev; + + hci_ev = ble_transport_alloc_evt(0); + if (!hci_ev) { + return; + + } + + hci_ev->opcode = BLE_HCI_EVCODE_VS; + hci_ev->length = sizeof(*ev_vs) + sizeof(*ev); + ev_vs = (void *)hci_ev->data; + ev_vs->id = BLE_HCI_VS_SUBEV_ID_CSS_SLOT_CHANGED; + ev = (void *)ev_vs->data; + ev->conn_handle = htole16(conn_handle); + ev->slot_idx = htole16(slot_idx); + + ble_ll_hci_event_send(hci_ev); +} +#endif + void ble_ll_hci_ev_send_vs_assert(const char *file, uint32_t line) { - struct ble_hci_ev_vs_debug *ev; + struct ble_hci_ev_vs *ev; struct ble_hci_ev *hci_ev; unsigned int str_len; bool skip = true; @@ -543,12 +572,12 @@ ble_ll_hci_ev_send_vs_assert(const char *file, uint32_t line) hci_ev = ble_transport_alloc_evt(0); if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_VS_DEBUG; + hci_ev->opcode = BLE_HCI_EVCODE_VS; hci_ev->length = sizeof(*ev); ev = (void *) hci_ev->data; /* Debug id for future use */ - ev->id = 0x00; + ev->id = BLE_HCI_VS_SUBEV_ID_ASSERT; /* snprintf would be nicer but this is heavy on flash * len = snprintf((char *) ev->data, max_len, "%s:%u", file, line); @@ -561,7 +590,7 @@ ble_ll_hci_ev_send_vs_assert(const char *file, uint32_t line) * hci_ev->length += len; */ str_len = strlen(file); - if (str_len > max_len) { + if (str_len > (unsigned int)max_len) { str_len = max_len; } @@ -585,21 +614,47 @@ ble_ll_hci_ev_send_vs_assert(const char *file, uint32_t line) } } +void +ble_ll_hci_ev_send_vs_printf(uint8_t id, const char *fmt, ...) +{ + struct ble_hci_ev_vs *ev; + struct ble_hci_ev *hci_ev; + va_list ap; + + hci_ev = ble_transport_alloc_evt(1); + if (!hci_ev) { + return; + } + + hci_ev->opcode = BLE_HCI_EVCODE_VS; + hci_ev->length = sizeof(*ev); + + ev = (void *) hci_ev->data; + ev->id = id; + + va_start(ap, fmt); + hci_ev->length += vsnprintf((void *)ev->data, + BLE_HCI_MAX_DATA_LEN - sizeof(*ev), fmt, ap); + va_end(ap); + + ble_ll_hci_event_send(hci_ev); +} + #if MYNEWT_VAL(BLE_LL_HCI_LLCP_TRACE) void ble_ll_hci_ev_send_vs_llcp_trace(uint8_t type, uint16_t handle, uint16_t count, void *pdu, size_t length) { - struct ble_hci_ev_vs_debug *ev; + struct ble_hci_ev_vs *ev; struct ble_hci_ev *hci_ev; hci_ev = ble_transport_alloc_evt(1); if (hci_ev) { - hci_ev->opcode = BLE_HCI_EVCODE_VS_DEBUG; + hci_ev->opcode = BLE_HCI_EVCODE_VS; hci_ev->length = sizeof(*ev) + 8 + length; ev = (void *) hci_ev->data; - ev->id = 0x17; + ev->id = BLE_HCI_VS_SUBEV_ID_LLCP_TRACE; ev->data[0] = type; put_le16(&ev->data[1], handle); put_le16(&ev->data[3], count); @@ -611,6 +666,5 @@ ble_ll_hci_ev_send_vs_llcp_trace(uint8_t type, uint16_t handle, uint16_t count, ble_ll_hci_event_send(hci_ev); } } - -#endif #endif +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_hci_supp_cmd.c b/src/nimble/nimble/controller/src/ble_ll_hci_supp_cmd.c new file mode 100644 index 00000000..71068cc3 --- /dev/null +++ b/src/nimble/nimble/controller/src/ble_ll_hci_supp_cmd.c @@ -0,0 +1,345 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef ESP_PLATFORM + +#include +#include +#include +#include +#include + +/* Magic macros */ +#define BIT(n) (1 << (n)) | +#define OCTET(x) (0 | x 0) + +static const uint8_t octet_0 = OCTET( +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(5) /* HCI Disconnect */ +#endif +); + +static const uint8_t octet_2 = OCTET( +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(7) /* HCI Read Remote Version Information */ +#endif +); + +static const uint8_t octet_5 = OCTET( + BIT(6) /* HCI Set Event Mask */ + BIT(7) /* HCI Reset */ +); + +static const uint8_t octet_10 = OCTET( +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) + BIT(5) /* HCI Set Controller To Host Flow Control */ + BIT(6) /* HCI Host Buffer Size */ + BIT(7) /* HCI Host Number Of Completed Packets */ +#endif +); + +static const uint8_t octet_14 = OCTET( + BIT(3) /* HCI Read Local Version Information */ + BIT(5) /* HCI Read Local Supported Features */ +); + +static const uint8_t octet_15 = OCTET( + BIT(1) /* HCI Read BD ADDR */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(5) /* HCI Read RSSI */ +#endif +); + +static const uint8_t octet_25 = OCTET( + BIT(0) /* HCI LE Set Event Mask */ + BIT(1) /* HCI LE Read Buffer Size [v1] */ + BIT(2) /* HCI LE Read Local Supported Features */ + BIT(4) /* HCI LE Set Random Address */ +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + BIT(5) /* HCI LE Set Advertising Parameters */ + BIT(6) /* HCI LE Read Advertising Physical Channel Tx Power */ + BIT(7) /* HCI LE Set Advertising Data */ +#endif +); + +static const uint8_t octet_26 = OCTET( +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + BIT(0) /* HCI LE Set Scan Response Data */ + BIT(1) /* HCI LE Set Advertising Enable */ +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + BIT(2) /* HCI LE Set Scan Parameters */ + BIT(3) /* HCI LE Set Scan Enable */ +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(4) /* HCI LE Create Connection */ + BIT(5) /* HCI LE Create Connection Cancel */ +#endif + BIT(6) /* HCI LE Read Filter Accept List Size */ + BIT(7) /* HCI LE Clear Filter Accept List */ +); + +static const uint8_t octet_27 = OCTET( + BIT(0) /* HCI LE Add Device To Filter Accept List */ + BIT(1) /* HCI LE Remove Device From Filter Accept List */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(2) /* HCI LE Connection Update */ +#endif + BIT(3) /* HCI LE Set Host Channel Classification */ +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(4) /* HCI LE Read Channel Map */ + BIT(5) /* HCI LE Read Remote Features */ +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) + BIT(6) /* HCI LE Encrypt */ +#endif + BIT(7) /* HCI LE Rand */ +); + +static const uint8_t octet_28 = OCTET( +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(0) /* HCI LE Enable Encryption */ +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) + BIT(1) /* HCI LE Long Term Key Request Reply */ + BIT(2) /* HCI LE Long Term Key Request Negative Reply */ +#endif +#endif + BIT(3) /* HCI LE Read Supported States */ +#if MYNEWT_VAL(BLE_LL_DTM) + BIT(4) /* HCI LE Receiver Test [v1] */ + BIT(5) /* HCI LE Transmitter Test [v1] */ + BIT(6) /* HCI LE Test End */ +#endif +); + +static const uint8_t octet_33 = OCTET( +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(4) /* HCI LE Remote Connection Parameter Request Reply */ + BIT(5) /* HCI LE Remote Connection Parameter Request Negative Reply */ +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) + BIT(6) /* HCI LE Set Data Length */ + BIT(7) /* HCI LE Read Suggested Default Data Length */ +#endif +); + +static const uint8_t octet_34 = OCTET( +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) + BIT(0) /* HCI LE Write Suggested Data Length */ +#endif +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + BIT(3) /* HCI LE Add Device To Resolving List */ + BIT(4) /* HCI LE Remove Device From Resolving List */ + BIT(5) /* HCI LE Clear Resolving List */ + BIT(6) /* HCI LE Read Resolving List Size */ + BIT(7) /* HCI LE Read Peer Resolvable Address */ +#endif +); + +static const uint8_t octet_35 = OCTET( +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + BIT(0) /* HCI LE Read Local Resolvable Address */ + BIT(1) /* HCI LE Set Address Resolution Enable */ + BIT(2) /* HCI LE Set Resolvable Private Address Timeout */ +#endif + BIT(3) /* HCI LE Read Maximum Data Length */ +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) +#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(4) /* HCI LE Read PHY */ + BIT(5) /* HCI LE Set Default PHY */ + BIT(6) /* HCI LE Set PHY */ +#endif +#endif +#if MYNEWT_VAL(BLE_LL_DTM) + BIT(7) /* HCI LE Receiver Test [v2] */ +#endif +); + +static const uint8_t octet_36 = OCTET( +#if MYNEWT_VAL(BLE_LL_DTM) + BIT(0) /* HCI LE Transmitter Test [v2] */ +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + BIT(1) /* HCI LE Set Advertising Set Random Address */ + BIT(2) /* HCI LE Set Extended Advertising Parameters */ + BIT(3) /* HCI LE Set Extended Advertising Data */ + BIT(4) /* HCI LE Set Extended Scan Response Data */ + BIT(5) /* HCI LE Set Extended Advertising Enable */ + BIT(6) /* HCI LE Read Maximum Advertising Data Length */ + BIT(7) /* HCI LE Read Number of Supported Advertising Sets */ +#endif +); + +static const uint8_t octet_37 = OCTET( +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + BIT(0) /* HCI LE Remove Advertising Set */ + BIT(1) /* HCI LE Clear Advertising Sets */ +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + BIT(2) /* HCI LE Set Periodic Advertising Parameters */ + BIT(3) /* HCI LE Set Periodic Advertising Data */ + BIT(4) /* HCI LE Set Periodic Advertising Enable */ +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + BIT(5) /* HCI LE Set Extended Scan Parameters */ + BIT(6) /* HCI LE Set Extended Scan Enable */ +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + BIT(7) /* HCI LE Extended Create Connection */ +#endif +#endif +); + +static const uint8_t octet_38 = OCTET( +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + BIT(0) /* HCI LE Periodic Advertising Create Sync */ + BIT(1) /* HCI LE Periodic Advertising Create Sync Cancel */ + BIT(2) /* HCI LE Periodic Advertising Terminate Sync */ + BIT(3) /* HCI LE Add Device To Periodic Advertiser List */ + BIT(4) /* HCI LE Remove Device From Periodic Advertiser List */ + BIT(5) /* HCI LE Clear Periodic Advertiser List */ + BIT(6) /* HCI LE Read Periodic Advertiser List Size */ +#endif + BIT(7) /* HCI LE Read Transmit Power */ +); + +static const uint8_t octet_39 = OCTET( + BIT(0) /* HCI LE Read RF Path Compensation */ + BIT(1) /* HCI LE Write RF Path Compensation */ +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + BIT(2) /* HCI LE Set Privacy Mode */ +#endif +); + +static const uint8_t octet_40 = OCTET( +#if MYNEWT_VAL(BLE_VERSION) >= 51 && MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + BIT(5) /* HCI LE Set Periodic Advertising Receive Enable */ +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) +#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) + BIT(6) /* HCI LE Periodic Advertising Sync Transfer */ +#endif +#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) + BIT(7) /* HCI LE Periodic Advertising Set Info Transfer */ +#endif +#endif +#endif +); + +static const uint8_t octet_41 = OCTET( +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) + BIT(0) /* HCI LE Set Periodic Advertising Sync Transfer Parameters */ + BIT(1) /* HCI LE Set Default Periodic Advertising Sync Transfer Parameters */ +#endif +#if MYNEWT_VAL(BLE_LL_ISO) + BIT(5) /* HCI LE Read Buffer Size [v2] */ + BIT(6) /* HCI LE Read ISO TX Sync */ +#endif +); + +static const uint8_t octet_42 = OCTET( +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + BIT(5) /* HCI LE Create BIG */ + BIT(6) /* HCI LE Create BIG Test */ + BIT(7) /* HCI LE Terminate BIG */ +#endif +); + +static const uint8_t octet_43 = OCTET( +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) + BIT(2) /* HCI LE Request Peer SCA */ +#endif +); + +static const uint8_t octet_44 = OCTET( +#if MYNEWT_VAL(BLE_VERSION) >= 52 + BIT(1) /* HCI LE Set Host Feature */ +#endif +); + +static const uint8_t octet_46 = OCTET( +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) + BIT(0) /* HCI LE Set Default Subrate */ + BIT(1) /* HCI LE Subrate Request */ +#endif +); + +static const uint8_t g_ble_ll_hci_supp_cmds[64] = { + octet_0, + 0, + octet_2, + 0, + 0, + octet_5, + 0, + 0, + 0, + 0, + octet_10, + 0, + 0, + 0, + octet_14, + octet_15, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + octet_25, + octet_26, + octet_27, + octet_28, + 0, + 0, + 0, + 0, + octet_33, + octet_34, + octet_35, + octet_36, + octet_37, + octet_38, + octet_39, + octet_40, + octet_41, + octet_42, + octet_43, + octet_44, + 0, + octet_46, +}; + +void +ble_ll_hci_supp_cmd_get(uint8_t *buf) +{ + memcpy(buf, g_ble_ll_hci_supp_cmds, sizeof(g_ble_ll_hci_supp_cmds)); +} + +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_hci_vs.c b/src/nimble/nimble/controller/src/ble_ll_hci_vs.c index ca43a7e4..b405f7c1 100644 --- a/src/nimble/nimble/controller/src/ble_ll_hci_vs.c +++ b/src/nimble/nimble/controller/src/ble_ll_hci_vs.c @@ -21,22 +21,19 @@ #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_sync.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sync.h" +#include "nimble/nimble/controller/include/controller/ble_ll_adv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_fem.h" #include "ble_ll_conn_priv.h" #include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_HCI_VS) -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(array) \ - (sizeof(array) / sizeof((array)[0])) -#endif - SLIST_HEAD(ble_ll_hci_vs_list, ble_ll_hci_vs_cmd); static struct ble_ll_hci_vs_list g_ble_ll_hci_vs_list; @@ -63,56 +60,6 @@ ble_ll_hci_vs_rd_static_addr(uint16_t ocf, return BLE_ERR_SUCCESS; } -/* disallow changing TX power if there is any radio activity - * note: we could allow to change it if there is no TX activity (eg only - * passive scan or sync) but lets just keep this simple for now - */ -static int -ble_ll_hci_vs_is_controller_busy(void) -{ -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) - struct ble_ll_conn_sm *cur; - int i = 0; -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) - if (ble_ll_sync_enabled()) { - return 1; - } -#endif - -#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) - if (ble_ll_adv_enabled()) { - return 1; - } -#endif - -#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) - if (ble_ll_scan_enabled()) { - return 1; - } -#endif - -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) - if (g_ble_ll_conn_create_sm.connsm) { - return 1; - } -#endif - -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) - STAILQ_FOREACH(cur, &g_ble_ll_conn_free_list, free_stqe) { - i++; - } - - /* check if all connection objects are free */ - if (i < MYNEWT_VAL(BLE_MAX_CONNECTIONS)) { - return 1; - } -#endif - - return 0; -} - static int ble_ll_hci_vs_set_tx_power(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, uint8_t *rsplen) @@ -124,18 +71,22 @@ ble_ll_hci_vs_set_tx_power(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, return BLE_ERR_INV_HCI_CMD_PARMS; } - if (ble_ll_hci_vs_is_controller_busy()) { + if (ble_ll_is_busy(0)) { return BLE_ERR_CMD_DISALLOWED; } if (cmd->tx_power == 127) { /* restore reset default */ - g_ble_ll_tx_power = MYNEWT_VAL(BLE_LL_TX_PWR_DBM); + g_ble_ll_tx_power = ble_ll_tx_power_round(MIN(MYNEWT_VAL(BLE_LL_TX_PWR_DBM), + MYNEWT_VAL(BLE_LL_TX_PWR_MAX_DBM)) - + g_ble_ll_tx_power_compensation); } else { - g_ble_ll_tx_power = ble_phy_txpower_round(cmd->tx_power); + g_ble_ll_tx_power = ble_ll_tx_power_round(MIN(cmd->tx_power, + MYNEWT_VAL(BLE_LL_TX_PWR_MAX_DBM)) - + g_ble_ll_tx_power_compensation); } - rsp->tx_power = g_ble_ll_tx_power; + rsp->tx_power = g_ble_ll_tx_power + g_ble_ll_tx_power_compensation; *rsplen = sizeof(*rsp); return BLE_ERR_SUCCESS; @@ -145,7 +96,7 @@ ble_ll_hci_vs_set_tx_power(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, #if MYNEWT_VAL(BLE_LL_HCI_VS_CONN_STRICT_SCHED) #if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED) static int -ble_ll_hci_vs_css_configure(const uint8_t *cmdbuf, uint8_t cmdlen, +ble_ll_hci_vs_css_configure(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, uint8_t *rspbuf, uint8_t *rsplen) { const struct ble_hci_vs_css_configure_cp *cmd = (const void *)cmdbuf; @@ -156,8 +107,8 @@ ble_ll_hci_vs_css_configure(const uint8_t *cmdbuf, uint8_t cmdlen, return BLE_ERR_INV_HCI_CMD_PARMS; } - if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) { - return BLE_ERR_CTLR_BUSY; + if (ble_ll_sched_css_is_enabled()) { + return BLE_ERR_CMD_DISALLOWED; } slot_us = le32toh(cmd->slot_us); @@ -178,8 +129,32 @@ ble_ll_hci_vs_css_configure(const uint8_t *cmdbuf, uint8_t cmdlen, #endif static int -ble_ll_hci_vs_css_set_next_slot(const uint8_t *cmdbuf, uint8_t cmdlen, - uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_hci_vs_css_enable(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_vs_css_enable_cp *cmd = (const void *)cmdbuf; + + if (cmdlen != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!SLIST_EMPTY(&g_ble_ll_conn_active_list)) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (cmd->enable & 0xfe) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + ble_ll_sched_css_set_enabled(cmd->enable); + + return BLE_ERR_SUCCESS; +} + +static int +ble_ll_hci_vs_css_set_next_slot(uint16_t ocf, const uint8_t *cmdbuf, + uint8_t cmdlen, uint8_t *rspbuf, + uint8_t *rsplen) { const struct ble_hci_vs_css_set_next_slot_cp *cmd = (const void *)cmdbuf; uint16_t slot_idx; @@ -204,8 +179,9 @@ ble_ll_hci_vs_css_set_next_slot(const uint8_t *cmdbuf, uint8_t cmdlen, } static int -ble_ll_hci_vs_css_set_conn_slot(const uint8_t *cmdbuf, uint8_t cmdlen, - uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_hci_vs_css_set_conn_slot(uint16_t ocf, const uint8_t *cmdbuf, + uint8_t cmdlen, uint8_t *rspbuf, + uint8_t *rsplen) { const struct ble_hci_vs_css_set_conn_slot_cp *cmd = (const void *)cmdbuf; struct ble_ll_conn_sm *connsm; @@ -216,6 +192,10 @@ ble_ll_hci_vs_css_set_conn_slot(const uint8_t *cmdbuf, uint8_t cmdlen, return BLE_ERR_INV_HCI_CMD_PARMS; } + if (!ble_ll_sched_css_is_enabled()) { + return BLE_ERR_CMD_DISALLOWED; + } + slot_idx = le16toh(cmd->slot_idx); if ((slot_idx >= ble_ll_sched_css_get_period_slots()) && (slot_idx != BLE_LL_CONN_CSS_NO_SLOT)) { @@ -227,7 +207,7 @@ ble_ll_hci_vs_css_set_conn_slot(const uint8_t *cmdbuf, uint8_t cmdlen, } conn_handle = le16toh(cmd->conn_handle); - connsm = ble_ll_conn_find_active_conn(conn_handle); + connsm = ble_ll_conn_find_by_handle(conn_handle); if (!connsm) { return BLE_ERR_UNK_CONN_ID; } @@ -248,29 +228,105 @@ ble_ll_hci_vs_css_set_conn_slot(const uint8_t *cmdbuf, uint8_t cmdlen, } static int -ble_ll_hci_vs_css(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, - uint8_t *rspbuf, uint8_t *rsplen) +ble_ll_hci_vs_css_read_conn_slot(uint16_t ocf, const uint8_t *cmdbuf, + uint8_t cmdlen, uint8_t *rspbuf, + uint8_t *rsplen) { - const struct ble_hci_vs_css_cp *cmd = (const void *)cmdbuf; + const struct ble_hci_vs_css_read_conn_slot_cp *cmd = (const void *)cmdbuf; + struct ble_hci_vs_css_read_conn_slot_rp *rsp = (void *)rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t conn_handle; - if (cmdlen < sizeof(*cmd)) { + if (cmdlen != sizeof(*cmd)) { return BLE_ERR_INV_HCI_CMD_PARMS; } - *rsplen = 0; + if (!ble_ll_sched_css_is_enabled()) { + return BLE_ERR_CMD_DISALLOWED; + } - switch (cmd->opcode) { -#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED) - case BLE_HCI_VS_CSS_OP_CONFIGURE: - return ble_ll_hci_vs_css_configure(cmdbuf, cmdlen, rspbuf, rsplen); + conn_handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_by_handle(conn_handle); + if (!connsm) { + return BLE_ERR_UNK_CONN_ID; + } + + *rsplen = sizeof(*rsp); + rsp->conn_handle = cmd->conn_handle; + rsp->slot_idx = htole16(connsm->css_slot_idx); + + return BLE_ERR_SUCCESS; +} #endif - case BLE_HCI_VS_CSS_OP_SET_NEXT_SLOT: - return ble_ll_hci_vs_css_set_next_slot(cmdbuf, cmdlen, rspbuf, rsplen); - case BLE_HCI_VS_CSS_OP_SET_CONN_SLOT: - return ble_ll_hci_vs_css_set_conn_slot(cmdbuf, cmdlen, rspbuf, rsplen); + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +static int +ble_ll_hci_vs_set_data_len(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_vs_set_data_len_cp *cmd = (const void *) cmdbuf; + struct ble_hci_vs_set_data_len_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t conn_handle; + uint16_t tx_octets; + uint16_t tx_time; + uint16_t rx_octets; + uint16_t rx_time; + int rc; + + if (cmdlen != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + conn_handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_by_handle(conn_handle); + if (!connsm) { + return BLE_ERR_UNK_CONN_ID; } - return BLE_ERR_INV_HCI_CMD_PARMS; + tx_octets = le16toh(cmd->tx_octets); + tx_time = le16toh(cmd->tx_time); + rx_octets = le16toh(cmd->rx_octets); + rx_time = le16toh(cmd->rx_time); + + if (!ble_ll_hci_check_dle(tx_octets, tx_time) || + !ble_ll_hci_check_dle(rx_octets, rx_time)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rc = ble_ll_conn_set_data_len(connsm, tx_octets, tx_time, rx_octets, + rx_time); + if (rc) { + return rc; + } + + rsp->conn_handle = htole16(conn_handle); + *rsplen = sizeof(*rsp); + + return 0; +} +#endif + +#if MYNEWT_VAL(BLE_FEM_ANTENNA) +static int +ble_ll_hci_vs_set_antenna(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_vs_set_antenna_cp *cmd = (const void *) cmdbuf; + + if (cmdlen != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (ble_ll_is_busy(0)) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (ble_fem_antenna(cmd->antenna)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return BLE_ERR_SUCCESS; } #endif @@ -280,8 +336,25 @@ static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = { BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_TX_PWR, ble_ll_hci_vs_set_tx_power), #if MYNEWT_VAL(BLE_LL_HCI_VS_CONN_STRICT_SCHED) - BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_CSS, - ble_ll_hci_vs_css), +#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED) + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_CSS_CONFIGURE, + ble_ll_hci_vs_css_configure), +#endif + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_CSS_ENABLE, + ble_ll_hci_vs_css_enable), + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_CSS_SET_NEXT_SLOT, + ble_ll_hci_vs_css_set_next_slot), + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_CSS_SET_CONN_SLOT, + ble_ll_hci_vs_css_set_conn_slot), + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_CSS_READ_CONN_SLOT, + ble_ll_hci_vs_css_read_conn_slot), +#endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_DATA_LEN, + ble_ll_hci_vs_set_data_len), +#endif +#if MYNEWT_VAL(BLE_FEM_ANTENNA) + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_ANTENNA, ble_ll_hci_vs_set_antenna), #endif }; @@ -347,4 +420,4 @@ ble_ll_hci_vs_init(void) #endif -#endif /* !ESP_PLATFORM */ \ No newline at end of file +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_iso.c b/src/nimble/nimble/controller/src/ble_ll_iso.c index ac8ca1e8..08246315 100644 --- a/src/nimble/nimble/controller/src/ble_ll_iso.c +++ b/src/nimble/nimble/controller/src/ble_ll_iso.c @@ -21,7 +21,7 @@ #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_ll_iso.h" +#include "nimble/nimble/controller/include/controller/ble_ll_iso.h" #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) diff --git a/src/nimble/nimble/controller/src/ble_ll_iso_big.c b/src/nimble/nimble/controller/src/ble_ll_iso_big.c new file mode 100644 index 00000000..938a7fc2 --- /dev/null +++ b/src/nimble/nimble/controller/src/ble_ll_iso_big.c @@ -0,0 +1,1379 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef ESP_PLATFORM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ble_ll_priv.h" + +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + +/* XXX make those configurable */ +#define BIG_POOL_SIZE (10) +#define BIS_POOL_SIZE (10) + +#define BIG_HANDLE_INVALID (0xff) + +#define BIG_CONTROL_ACTIVE_CHAN_MAP 1 +#define BIG_CONTROL_ACTIVE_TERM 2 + +struct ble_ll_iso_big; + +struct ble_ll_iso_bis { + struct ble_ll_iso_big *big; + uint8_t num; + uint16_t conn_handle; + + uint32_t aa; + uint32_t crc_init; + uint16_t chan_id; + uint8_t iv[8]; + + struct { + uint16_t prn_sub_lu; + uint16_t remap_idx; + + uint8_t subevent_num; + uint8_t n; + uint8_t g; + } tx; + + struct ble_ll_isoal_mux mux; + uint16_t num_completed_pkt; + + STAILQ_ENTRY(ble_ll_iso_bis) bis_q_next; +}; + +STAILQ_HEAD(ble_ll_iso_bis_q, ble_ll_iso_bis); + +struct big_params { + uint8_t nse; /* 1-31 */ + uint8_t bn; /* 1-7, mandatory 1 */ + uint8_t irc; /* 1-15 */ + uint8_t pto; /* 0-15, mandatory 0 */ + uint32_t sdu_interval; + uint16_t iso_interval; + uint16_t max_transport_latency; + uint16_t max_sdu; + uint8_t max_pdu; + uint8_t phy; + uint8_t interleaved : 1; + uint8_t framed : 1; + uint8_t encrypted : 1; + uint8_t broadcast_code[16]; +}; + +struct ble_ll_iso_big { + struct ble_ll_adv_sm *advsm; + + uint8_t handle; + uint8_t num_bis; + uint16_t iso_interval; + uint16_t bis_spacing; + uint16_t sub_interval; + uint8_t phy; + uint8_t max_pdu; + uint16_t max_sdu; + uint16_t mpt; + uint8_t bn; /* 1-7, mandatory 1 */ + uint8_t pto; /* 0-15, mandatory 0 */ + uint8_t irc; /* 1-15 */ + uint8_t nse; /* 1-31 */ + uint8_t interleaved : 1; + uint8_t framed : 1; + uint8_t encrypted : 1; + uint8_t giv[8]; + uint8_t gskd[16]; + uint8_t gsk[16]; + uint8_t iv[8]; + uint8_t gc; + + uint32_t sdu_interval; + + uint32_t ctrl_aa; + uint16_t crc_init; + uint8_t chan_map[BLE_LL_CHAN_MAP_LEN]; + uint8_t chan_map_used; + + uint8_t biginfo[33]; + + uint64_t big_counter; + uint64_t bis_counter; + + uint32_t sync_delay; + uint32_t event_start; + uint8_t event_start_us; + struct ble_ll_sched_item sch; + struct ble_npl_event event_done; + + struct { + uint16_t subevents_rem; + struct ble_ll_iso_bis *bis; + } tx; + + struct ble_ll_iso_bis_q bis_q; + + uint8_t cstf : 1; + uint8_t cssn : 4; + uint8_t control_active : 3; + uint16_t control_instant; + + uint8_t chan_map_new_pending : 1; + uint8_t chan_map_new[BLE_LL_CHAN_MAP_LEN]; + + uint8_t term_pending : 1; + uint8_t term_reason : 7; +}; + +static struct ble_ll_iso_big big_pool[BIG_POOL_SIZE]; +static struct ble_ll_iso_bis bis_pool[BIS_POOL_SIZE]; +static uint8_t big_pool_free = BIG_POOL_SIZE; +static uint8_t bis_pool_free = BIS_POOL_SIZE; + +static struct ble_ll_iso_big *big_pending; +static struct ble_ll_iso_big *big_active; + +struct ble_ll_iso_bis * +ble_ll_iso_big_find_bis_by_handle(uint16_t conn_handle) +{ + struct ble_ll_iso_bis *bis; + uint8_t bis_idx; + + if (!BLE_LL_CONN_HANDLE_IS_BIS(conn_handle)) { + return NULL; + } + + bis_idx = BLE_LL_CONN_HANDLE_IDX(conn_handle); + + if (bis_idx >= BIS_POOL_SIZE) { + return NULL; + } + + bis = &bis_pool[bis_idx]; + if (!bis->big) { + return NULL; + } + + return bis; +} + +struct ble_ll_isoal_mux * +ble_ll_iso_big_find_mux_by_handle(uint16_t conn_handle) +{ + struct ble_ll_iso_bis *bis; + + bis = ble_ll_iso_big_find_bis_by_handle(conn_handle); + if (bis) { + return &bis->mux; + } + + return NULL; +} + +int +ble_ll_iso_big_last_tx_timestamp_get(struct ble_ll_iso_bis *bis, + uint16_t *packet_seq_num, uint32_t *timestamp) +{ + struct ble_ll_iso_big *big; + + big = bis->big; + + *packet_seq_num = big->bis_counter; + *timestamp = (uint64_t)big->event_start * 1000000 / 32768 + + big->event_start_us; + + return 0; +} + +static void +ble_ll_iso_big_biginfo_calc(struct ble_ll_iso_big *big, uint32_t seed_aa) +{ + uint8_t *buf; + + buf = big->biginfo; + + /* big_offset, big_offset_units, iso_interval, num_bis */ + put_le32(buf, (big->num_bis << 27) | (big->iso_interval << 15)); + buf += 4; + + /* nse, bn */ + *(uint8_t *)buf = (big->bn << 5) | (big->nse); + buf += 1; + + /* sub_interval, pto */ + put_le24(buf,(big->pto << 20) | (big->sub_interval)); + buf += 3; + + /* bis_spacing, irc */ + put_le24(buf, (big->irc << 20) | (big->bis_spacing)); + buf += 3; + + /* max_pdu, rfu */ + put_le16(buf, big->max_pdu); + buf += 2; + + /* seed_access_address */ + put_le32(buf, seed_aa); + buf += 4; + + /* sdu_interval, max_sdu */ + put_le32(buf, (big->max_sdu << 20) | (big->sdu_interval)); + buf += 4; + + /* base_crc_init */ + put_le16(buf, big->crc_init); + buf += 2; + + /* chm, phy */ + memcpy(buf, big->chan_map, 5); + buf[4] |= (big->phy - 1) << 5; + buf += 5; + + /* bis_payload_cnt, framing */ + memset(buf, 0x00, 5); +} + +int +ble_ll_iso_big_biginfo_copy(struct ble_ll_iso_big *big, uint8_t *dptr, + uint32_t base_ticks, uint8_t base_rem_us) +{ + uint8_t *dptr_start; + uint64_t counter; + uint32_t offset_us; + uint32_t offset; + uint32_t d_ticks; + uint8_t d_rem_us; + + dptr_start = dptr; + counter = big->bis_counter; + + d_ticks = big->event_start - base_ticks; + d_rem_us = big->event_start_us; + ble_ll_tmr_sub(&d_ticks, &d_rem_us, base_rem_us); + + offset_us = ble_ll_tmr_t2u(d_ticks) + d_rem_us; + if (offset_us <= 600) { + counter += big->bn; + offset_us += big->iso_interval * 1250; + } + if (offset_us >= 491460) { + offset = 0x4000 | (offset_us / 300); + } else { + offset = offset_us / 30; + } + + *dptr++ = ble_ll_iso_big_biginfo_len(big) - 1; + *dptr++ = 0x2c; + + memcpy(dptr, big->biginfo, 33); + put_le32(dptr, get_le32(dptr) | (offset & 0x7fff)); + dptr += 28; + + *dptr++ = counter & 0xff; + *dptr++ = (counter >> 8) & 0xff; + *dptr++ = (counter >> 16) & 0xff; + *dptr++ = (counter >> 24) & 0xff; + *dptr++ = (counter >> 32) & 0xff; + + if (big->encrypted) { + memcpy(dptr, big->giv, 8); + dptr += 8; + memcpy(dptr, big->gskd, 16); + dptr += 16; + } + + return dptr - dptr_start; +} + +int +ble_ll_iso_big_biginfo_len(struct ble_ll_iso_big *big) +{ + return 2 + sizeof(big->biginfo) + + (big->encrypted ? sizeof(big->giv) + sizeof(big->gskd) : 0); +} + +static void +ble_ll_iso_big_free(struct ble_ll_iso_big *big) +{ + struct ble_ll_iso_bis *bis; + + if (big->handle == BIG_HANDLE_INVALID) { + return; + } + + big->handle = BIG_HANDLE_INVALID; + ble_ll_sched_rmv_elem(&big->sch); + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &big->event_done); + + STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { + ble_ll_isoal_mux_free(&bis->mux); + bis->big = NULL; + bis_pool_free++; + } + + big_pool_free++; +} + +static void +ble_ll_iso_big_terminate_complete(struct ble_ll_iso_big *big) +{ + struct ble_hci_ev *hci_ev; + struct ble_hci_ev_le_subev_terminate_big_complete *evt; + uint8_t big_handle; + uint8_t reason; + + big_handle = big->handle; + reason = big->term_reason; + + ble_ll_iso_big_free(big); + + hci_ev = ble_transport_alloc_evt(0); + if (!hci_ev) { + BLE_LL_ASSERT(0); + return; + } + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*evt); + + evt = (void *)hci_ev->data; + memset(evt, 0, hci_ev->length); + evt->subev_code = BLE_HCI_LE_SUBEV_TERMINATE_BIG_COMPLETE; + evt->big_handle = big_handle; + evt->reason = reason; + + ble_transport_to_hs_evt(hci_ev); +} + +static void +ble_ll_iso_big_chan_map_update_complete(struct ble_ll_iso_big *big) +{ + memcpy(big->chan_map, big->chan_map_new, BLE_LL_CHAN_MAP_LEN); + big->chan_map_used = ble_ll_utils_chan_map_used_get(big->chan_map); +} + +static void +ble_ll_iso_big_update_event_start(struct ble_ll_iso_big *big) +{ + os_sr_t sr; + + OS_ENTER_CRITICAL(sr); + big->event_start = big->sch.start_time + g_ble_ll_sched_offset_ticks; + big->event_start_us = big->sch.remainder; + OS_EXIT_CRITICAL(sr); +} + +static void +ble_ll_iso_big_event_done(struct ble_ll_iso_big *big) +{ + struct ble_ll_iso_bis *bis; + struct ble_hci_ev *hci_ev; + struct ble_hci_ev_num_comp_pkts *hci_ev_ncp; + int num_completed_pkt; + int rc; + + ble_ll_rfmgmt_release(); + + if (big->big_counter == 0) { + BLE_LL_ASSERT(big == big_pending); + ble_ll_iso_big_hci_evt_complete(); + } + + hci_ev = ble_transport_alloc_evt(1); + if (hci_ev) { + hci_ev->opcode = BLE_HCI_EVCODE_NUM_COMP_PKTS; + hci_ev->length = sizeof(*hci_ev_ncp); + hci_ev_ncp = (void *)hci_ev->data; + hci_ev_ncp->count = 0; + } + + STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { + num_completed_pkt = ble_ll_isoal_mux_event_done(&bis->mux); + if (hci_ev && num_completed_pkt) { + hci_ev_ncp->completed[hci_ev_ncp->count].handle = + htole16(bis->conn_handle); + hci_ev_ncp->completed[hci_ev_ncp->count].packets = + htole16(num_completed_pkt + bis->num_completed_pkt); + bis->num_completed_pkt = 0; + hci_ev_ncp->count++; + } else { + bis->num_completed_pkt += num_completed_pkt; + } + } + + if (hci_ev) { + if (hci_ev_ncp->count) { + hci_ev->length = sizeof(*hci_ev_ncp) + + hci_ev_ncp->count * sizeof(hci_ev_ncp->completed[0]); + ble_transport_to_hs_evt(hci_ev); + } else { + ble_transport_free(hci_ev); + } + } + + big->sch.start_time = big->event_start; + big->sch.remainder = big->event_start_us; + + do { + big->big_counter++; + big->bis_counter += big->bn; + + if (big->control_active && + (big->control_instant == (uint16_t)big->big_counter)) { + switch (big->control_active) { + case BIG_CONTROL_ACTIVE_TERM: + ble_ll_iso_big_terminate_complete(big); + return; + case BIG_CONTROL_ACTIVE_CHAN_MAP: + ble_ll_iso_big_chan_map_update_complete(big); + break; + default: + BLE_LL_ASSERT(0); + break; + } + + big->control_active = 0; + big->cstf = 0; + } + + if (!big->control_active) { + if (big->term_pending) { + big->term_pending = 0; + big->control_active = BIG_CONTROL_ACTIVE_TERM; + } else if (big->chan_map_new_pending) { + memcpy(big->chan_map_new, g_ble_ll_data.chan_map, + BLE_LL_CHAN_MAP_LEN); + big->chan_map_new_pending = 0; + big->control_active = BIG_CONTROL_ACTIVE_CHAN_MAP; + } + + if (big->control_active) { + big->control_instant = big->big_counter + 6; + big->cstf = 1; + big->cssn += 1; + } + } + + /* XXX precalculate some data here? */ + + ble_ll_tmr_add(&big->sch.start_time, &big->sch.remainder, + big->iso_interval * 1250); + big->sch.end_time = big->sch.start_time + + ble_ll_tmr_u2t_up(big->sync_delay) + 1; + big->sch.start_time -= g_ble_ll_sched_offset_ticks; + + if (big->control_active) { + /* XXX fixme */ + big->sch.end_time += 10; + } + + /* XXX this should always succeed since we preempt anything for now */ + rc = ble_ll_sched_iso_big(&big->sch, 0); + assert(rc == 0); + } while (rc < 0); + + ble_ll_iso_big_update_event_start(big); +} + +static void +ble_ll_iso_big_event_done_ev(struct ble_npl_event *ev) +{ + struct ble_ll_iso_big *big; + + big = ble_npl_event_get_arg(ev); + + ble_ll_iso_big_event_done(big); +} + +static void +ble_ll_iso_big_event_done_to_ll(struct ble_ll_iso_big *big) +{ + big_active = NULL; + ble_ll_state_set(BLE_LL_STATE_STANDBY); + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &big->event_done); +} + +static uint8_t +ble_ll_iso_big_control_pdu_cb(uint8_t *dptr, void *arg, uint8_t *hdr_byte) +{ + struct ble_ll_iso_big *big; + uint8_t len; + + big = arg; + + /* CSTF shall be set to 0 in Control PDU */ + *hdr_byte = 3 | (big->cssn << 2); + + BLE_LL_ASSERT(big->cstf); + BLE_LL_ASSERT(big->control_active); + + if (big->encrypted) { + ble_phy_encrypt_header_mask_set(BLE_LL_PDU_HEADERMASK_BIS); + ble_phy_encrypt_iv_set(big->iv); + ble_phy_encrypt_counter_set(big->bis_counter, 1); + } + + switch (big->control_active) { + case BIG_CONTROL_ACTIVE_CHAN_MAP: + dptr[0] = 0x00; /* BIG_CHANNEL_MAP_IND */ + memcpy(&dptr[1], big->chan_map_new, BLE_LL_CHAN_MAP_LEN); + put_le16(&dptr[6], big->control_instant); + len = 8; + break; + case BIG_CONTROL_ACTIVE_TERM: + dptr[0] = 0x01; /* BIG_TERMINATE_IND */ + dptr[1] = big->term_reason; + put_le16(&dptr[2], big->control_instant); + len = 4; + break; + default: + BLE_LL_ASSERT(0); + len = 0; + break; + } + + return len; +} + +static void +ble_ll_iso_big_control_txend_cb(void *arg) +{ + struct ble_ll_iso_big *big; + + big = arg; + + ble_ll_iso_big_event_done_to_ll(big); +} + +static int +ble_ll_iso_big_control_tx(struct ble_ll_iso_big *big) +{ + uint16_t chan_idx; + uint16_t chan_id; + uint16_t foo, bar; + int rc; + + chan_id = big->ctrl_aa ^ (big->ctrl_aa >> 16); + + chan_idx = ble_ll_utils_dci_iso_event(big->big_counter, chan_id, + &foo, + big->chan_map_used, + big->chan_map, + &bar); + + ble_phy_set_txend_cb(ble_ll_iso_big_control_txend_cb, big); + ble_phy_setchan(chan_idx, big->ctrl_aa, big->crc_init << 8); + + rc = ble_phy_tx(ble_ll_iso_big_control_pdu_cb, big, BLE_PHY_TRANSITION_NONE); + + return rc; +} + +static uint8_t +ble_ll_iso_big_subevent_pdu_cb(uint8_t *dptr, void *arg, uint8_t *hdr_byte) +{ + struct ble_ll_iso_big *big; + struct ble_ll_iso_bis *bis; + int idx; + uint8_t llid; + uint8_t pdu_len; + + big = arg; + bis = big->tx.bis; + + /* Core 5.3, Vol 6, Part B, 4.4.6.6 */ + if (bis->tx.g < big->irc) { + idx = bis->tx.n; + } else { + idx = big->bn * big->pto * (bis->tx.g - big->irc + 1) + bis->tx.n; + } + + if (big->encrypted) { + ble_phy_encrypt_header_mask_set(BLE_LL_PDU_HEADERMASK_BIS); + ble_phy_encrypt_iv_set(bis->iv); + ble_phy_encrypt_counter_set(big->bis_counter + idx, 1); + } + +#if 1 + pdu_len = ble_ll_isoal_mux_unframed_get(&bis->mux, idx, &llid, dptr); +#else + llid = 0; + pdu_len = big->max_pdu; + /* XXX dummy data for testing */ + memset(dptr, bis->num | (bis->num << 4), pdu_len); + put_be32(dptr, big->big_counter); + put_be32(&dptr[4], big->bis_counter + idx); + dptr[8] = bis->tx.subevent_num; + dptr[9] = bis->tx.g; + dptr[10] = bis->tx.n; + if (bis->tx.g == 0) { + dptr[11] = 'B'; + } else if (bis->tx.g < big->irc) { + dptr[11] = 'R'; + } else { + dptr[11] = 'P'; + } + dptr[12] = 0xff; +#endif + + *hdr_byte = llid | (big->cssn << 2) | (big->cstf << 5); + + return pdu_len; +} + +static int +ble_ll_iso_big_subevent_tx(struct ble_ll_iso_big *big) +{ + struct ble_ll_iso_bis *bis; + uint16_t chan_idx; + int to_tx; + int rc; + + bis = big->tx.bis; + + if (bis->tx.subevent_num == 1) { + chan_idx = ble_ll_utils_dci_iso_event(big->big_counter, bis->chan_id, + &bis->tx.prn_sub_lu, + big->chan_map_used, + big->chan_map, + &bis->tx.remap_idx); + } else { + chan_idx = ble_ll_utils_dci_iso_subevent(bis->chan_id, + &bis->tx.prn_sub_lu, + big->chan_map_used, + big->chan_map, + &bis->tx.remap_idx); + } + + ble_phy_setchan(chan_idx, bis->aa, bis->crc_init); + + to_tx = (big->tx.subevents_rem > 1) || big->cstf; + + rc = ble_phy_tx(ble_ll_iso_big_subevent_pdu_cb, big, + to_tx ? BLE_PHY_TRANSITION_TX_TX + : BLE_PHY_TRANSITION_NONE); + return rc; +} + +static void +ble_ll_iso_big_subevent_txend_cb(void *arg) +{ + struct ble_ll_iso_big *big; + struct ble_ll_iso_bis *bis; + int rc; + + big = arg; + bis = big->tx.bis; + + bis->tx.n++; + if (bis->tx.n == big->bn) { + bis->tx.n = 0; + bis->tx.g++; + } + + /* Switch to next BIS if interleaved or all subevents for current BIS were + * transmitted. + */ + if (big->interleaved || (bis->tx.subevent_num == big->nse)) { + bis = STAILQ_NEXT(bis, bis_q_next); + if (!bis) { + bis = STAILQ_FIRST(&big->bis_q); + } + big->tx.bis = bis; + } + + bis->tx.subevent_num++; + big->tx.subevents_rem--; + + if (big->tx.subevents_rem > 0) { + rc = ble_ll_iso_big_subevent_tx(big); + if (rc) { + ble_phy_disable(); + ble_ll_iso_big_event_done_to_ll(big); + } + return; + } + + if (big->cstf) { + rc = ble_ll_iso_big_control_tx(big); + if (rc) { + ble_phy_disable(); + ble_ll_iso_big_event_done_to_ll(big); + } + return; + } + + ble_ll_iso_big_event_done_to_ll(big); +} + +static int +ble_ll_iso_big_event_sched_cb(struct ble_ll_sched_item *sch) +{ + struct ble_ll_iso_big *big; + struct ble_ll_iso_bis *bis; +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + uint8_t phy_mode; +#endif + int rc; + + big = sch->cb_arg; + + ble_ll_state_set(BLE_LL_STATE_BIG); + big_active = big; + + ble_ll_whitelist_disable(); +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) + ble_phy_resolv_list_disable(); +#endif +#if (BLE_LL_BT5_PHY_SUPPORTED == 1) + phy_mode = ble_ll_phy_to_phy_mode(big->phy, 0); + ble_phy_mode_set(phy_mode, phy_mode); +#endif + + BLE_LL_ASSERT(!big->framed); + + /* XXX calculate this in advance at the end of previous event? */ + big->tx.subevents_rem = big->num_bis * big->nse; + STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { + ble_ll_isoal_mux_event_start(&bis->mux, (uint64_t)big->event_start * + 1000000 / 32768 + + big->event_start_us); + + bis->tx.subevent_num = 0; + bis->tx.n = 0; + bis->tx.g = 0; + } + + /* Select 1st BIS for transmission */ + big->tx.bis = STAILQ_FIRST(&big->bis_q); + big->tx.bis->tx.subevent_num = 1; + + if (big->interleaved) { + ble_phy_tifs_txtx_set(big->bis_spacing, 0); + } else { + ble_phy_tifs_txtx_set(big->sub_interval, 0); + } + + rc = ble_phy_tx_set_start_time(sch->start_time + g_ble_ll_sched_offset_ticks, + sch->remainder); + if (rc) { + ble_phy_disable(); + ble_ll_iso_big_event_done_to_ll(big); + return BLE_LL_SCHED_STATE_DONE; + } + + ble_phy_set_txend_cb(ble_ll_iso_big_subevent_txend_cb, big); + + if (big->encrypted) { + ble_phy_encrypt_enable(big->gsk); + } else { + ble_phy_encrypt_disable(); + } + + rc = ble_ll_iso_big_subevent_tx(big); + if (rc) { + ble_phy_disable(); + ble_ll_iso_big_event_done_to_ll(big); + return BLE_LL_SCHED_STATE_DONE; + } + + return BLE_LL_SCHED_STATE_RUNNING; +} + +static void +ble_ll_iso_big_calculate_gsk(struct ble_ll_iso_big *big, + const uint8_t *broadcast_code) +{ + static const uint8_t big1[16] = {0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x42, 0x49, 0x47, 0x31}; + static const uint8_t big2[4] = {0x42, 0x49, 0x47, 0x32}; + static const uint8_t big3[4] = {0x42, 0x49, 0x47, 0x33}; + uint8_t code[16]; + uint8_t igltk[16]; + uint8_t gltk[16]; + + /* broadcast code is lsb-first in hci, we need msb-first */ + swap_buf(code, broadcast_code, 16); + + ble_ll_rand_data_get(big->gskd, sizeof(big->gskd)); + + ble_ll_crypto_h7(big1, code, igltk); + ble_ll_crypto_h6(igltk, big2, gltk); + ble_ll_crypto_h8(gltk, big->gskd, big3, big->gsk); + + /* need gskd for biginfo, i.e. lsb-first */ + swap_in_place(big->gskd, 16); +} + +static void +ble_ll_iso_big_calculate_iv(struct ble_ll_iso_big *big) +{ + struct ble_ll_iso_bis *bis; + uint8_t *aa; + + ble_ll_rand_data_get(big->giv, sizeof(big->giv)); + STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { + memcpy(&bis->iv[4], &big->giv[4], 4); + aa = (uint8_t *)&bis->aa; + bis->iv[0] = big->giv[0] ^ aa[0]; + bis->iv[1] = big->giv[1] ^ aa[1]; + bis->iv[2] = big->giv[2] ^ aa[2]; + bis->iv[3] = big->giv[3] ^ aa[3]; + } + + memcpy(&big->iv[4], &big->giv[4], 4); + aa = (uint8_t *)&big->ctrl_aa; + big->iv[0] = big->giv[0] ^ aa[0]; + big->iv[1] = big->giv[1] ^ aa[1]; + big->iv[2] = big->giv[2] ^ aa[2]; + big->iv[3] = big->giv[3] ^ aa[3]; +} + +static int +ble_ll_iso_big_create(uint8_t big_handle, uint8_t adv_handle, uint8_t num_bis, + struct big_params *bp) +{ + struct ble_ll_iso_big *big = NULL; + struct ble_ll_iso_bis *bis; + struct ble_ll_adv_sm *advsm; + uint32_t seed_aa; + uint8_t pte; + uint8_t gc; + uint8_t idx; + int rc; + + if ((big_pool_free == 0) || (bis_pool_free < num_bis)) { + return -ENOMEM; + } + + /* Find free BIG */ + for (idx = 0; idx < BIG_POOL_SIZE; idx++) { + if (!big && big_pool[idx].handle == BIG_HANDLE_INVALID) { + big = &big_pool[idx]; + } + if (big_pool[idx].handle == big_handle) { + return -EALREADY; + } + } + + BLE_LL_ASSERT(big); + + advsm = ble_ll_adv_sync_get(adv_handle); + if (!advsm) { + return -ENOENT; + } + + if (ble_ll_adv_sync_big_add(advsm, big) < 0) { + return -ENOENT; + } + + big->advsm = advsm; + big->handle = big_handle; + + big->crc_init = ble_ll_rand(); + memcpy(big->chan_map, g_ble_ll_data.chan_map, BLE_LL_CHAN_MAP_LEN); + big->chan_map_used = g_ble_ll_data.chan_map_used; + + big->big_counter = 0; + big->bis_counter = 0; + + big->cstf = 0; + big->cssn = 0; + big->control_active = 0; + big->control_instant = 0; + big->chan_map_new_pending = 0; + big->term_pending = 0; + big->term_reason = 0; + + /* Calculate number of additional events for pre-transmissions */ + /* Core 5.3, Vol 6, Part B, 4.4.6.6 */ + gc = bp->nse / bp->bn; + if (bp->irc == gc) { + pte = 0; + } else { + pte = bp->pto * (gc - bp->irc); + } + + /* Allocate BISes */ + STAILQ_INIT(&big->bis_q); + big->num_bis = 0; + for (idx = 0; (big->num_bis < num_bis) && (idx < BIS_POOL_SIZE); idx++) { + bis = &bis_pool[idx]; + if (bis->big) { + continue; + } + + big->num_bis++; + STAILQ_INSERT_TAIL(&big->bis_q, bis, bis_q_next); + + bis->big = big; + bis->num = big->num_bis; + bis->crc_init = (big->crc_init << 8) | (big->num_bis); + + BLE_LL_ASSERT(!big->framed); + + ble_ll_isoal_mux_init(&bis->mux, bp->max_pdu, bp->iso_interval * 1250, + bp->sdu_interval, bp->bn, pte); + } + + big_pool_free--; + bis_pool_free -= num_bis; + + /* Calculate AA for each BIS and BIG Control. We have to repeat this process + * until all AAs are valid. + */ + do { + rc = 0; + + seed_aa = ble_ll_utils_calc_seed_aa(); + big->ctrl_aa = ble_ll_utils_calc_big_aa(seed_aa, 0); + + if (!ble_ll_utils_verify_aa(big->ctrl_aa)) { + continue; + } + + rc = 1; + + STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { + bis->aa = ble_ll_utils_calc_big_aa(seed_aa, bis->num); + if (!ble_ll_utils_verify_aa(bis->aa)) { + rc = 0; + break; + } + bis->chan_id = bis->aa ^ (bis->aa >> 16); + } + } while (rc == 0); + + big->bn = bp->bn; + big->pto = bp->pto; + big->irc = bp->irc; + big->nse = bp->nse; + big->interleaved = bp->interleaved; + big->framed = bp->framed; + big->encrypted = bp->encrypted; + big->sdu_interval = bp->sdu_interval; + big->iso_interval = bp->iso_interval; + big->phy = bp->phy; + big->max_pdu = bp->max_pdu; + big->max_sdu = bp->max_sdu; + /* Core 5.3, Vol 6, Part B, 4.4.6.3 */ + big->mpt = ble_ll_pdu_us(big->max_pdu + (big->encrypted ? 4 : 0), + ble_ll_phy_to_phy_mode(big->phy, + BLE_HCI_LE_PHY_CODED_S8_PREF)); + + /* Core 5.3, Vol 6, Part B, 4.4.6.4 */ + if (big->interleaved) { + big->bis_spacing = big->mpt + BLE_LL_MSS; + big->sub_interval = big->num_bis * big->bis_spacing; + } else { + big->sub_interval = big->mpt + BLE_LL_MSS; + big->bis_spacing = big->nse * big->sub_interval; + } + /* Core 5.3, Vol 6, Part B, 4.4.6.5 */ + big->sync_delay = (big->num_bis - 1) * big->bis_spacing + + (big->nse - 1) * big->sub_interval + big->mpt; + + /* Reset PTO if pre-transmissions won't be used */ + big->gc = gc; + if (big->irc == gc) { + big->pto = 0; + } + + if (big->encrypted) { + ble_ll_iso_big_calculate_gsk(big, bp->broadcast_code); + ble_ll_iso_big_calculate_iv(big); + } + + ble_ll_iso_big_biginfo_calc(big, seed_aa); + + /* For now we will schedule complete event as single item. This allows for + * shortest possible subevent space (150us) but can create sequence of long + * events that will block scheduler from other activities. To mitigate this + * we use preempt_none strategy so scheudling is opportunistic and depending + * on other activities this may create gaps in stream. + * Eventually we should allow for some more robust scheduling, e.g. per-BIS + * for sequential arrangement or per-subevent for interleaved, or event + * per-BIS-subevent but this requires larger subevent space since 150us is + * not enough for some phys to run scheduler item. + */ + + /* Schedule 1st event a bit in future */ + /* FIXME schedule 6ms in the future to avoid conflict with periodic + * advertising when both are started at the same time; we should + * select this value in some smart way later... + */ + big->sch.start_time = ble_ll_tmr_get() + ble_ll_tmr_u2t(6000); + big->sch.remainder = 0; + big->sch.end_time = big->sch.start_time + + ble_ll_tmr_u2t_up(big->sync_delay) + 1; + big->sch.start_time -= g_ble_ll_sched_offset_ticks; + + rc = ble_ll_sched_iso_big(&big->sch, 1); + if (rc < 0) { + ble_ll_iso_big_free(big); + return -EFAULT; + } + + ble_ll_iso_big_update_event_start(big); + + big_pending = big; + + return 0; +} + +static int +ble_ll_iso_big_terminate(uint8_t big_handle, uint8_t reason) +{ + struct ble_ll_iso_big *big = NULL; + unsigned idx; + + for (idx = 0; idx < BIG_POOL_SIZE; idx++) { + if (big_pool[idx].handle == big_handle) { + big = &big_pool[idx]; + break; + } + } + + if (!big) { + return -ENOENT; + } + + /* Not sure if this is correct, but let's remove BIGInfo now since there's + * no point for peer to syncing to a BIG that will be disconnected soon. + */ + ble_ll_adv_sync_big_remove(big->advsm, big); + + big->term_reason = reason; + big->term_pending = 1; + + return 0; +} + +void +ble_ll_iso_big_chan_map_update(void) +{ + struct ble_ll_iso_big *big; + int idx; + + for (idx = 0; idx < BIG_POOL_SIZE; idx++) { + big = &big_pool[idx]; + + if (big->handle == BIG_HANDLE_INVALID) { + continue; + } + + big->chan_map_new_pending = 1; + } +} + +void +ble_ll_iso_big_halt(void) +{ + if (big_active) { + ble_ll_iso_big_event_done_to_ll(big_active); + } +} + +void +ble_ll_iso_big_hci_evt_complete(void) +{ + struct ble_ll_iso_big *big; + struct ble_ll_iso_bis *bis; + struct ble_hci_ev_le_subev_create_big_complete *evt; + struct ble_hci_ev *hci_ev; + uint8_t idx; + + big = big_pending; + big_pending = NULL; + + if (!big) { + return; + } + + hci_ev = ble_transport_alloc_evt(0); + if (!hci_ev) { + BLE_LL_ASSERT(0); + /* XXX should we retry later? */ + return; + } + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*evt) + big->num_bis * sizeof(evt->conn_handle[0]); + + evt = (void *)hci_ev->data; + memset(evt, 0, hci_ev->length); + evt->subev_code = BLE_HCI_LE_SUBEV_CREATE_BIG_COMPLETE; + evt->status = 0x00; + + evt->big_handle = big->handle; + put_le24(evt->big_sync_delay, big->sync_delay); + /* Core 5.3, Vol 6, Part G, 3.2.2 */ + put_le24(evt->transport_latency_big, + big->sync_delay + + (big->pto * (big->nse / big->bn - big->irc) + 1) * big->iso_interval * 1250 - + big->sdu_interval); + evt->phy = big->phy; + evt->nse = big->nse; + evt->bn = big->bn; + evt->pto = big->pto; + evt->irc = big->irc; + evt->max_pdu = htole16(big->max_pdu); + evt->iso_interval = htole16(big->iso_interval); + evt->num_bis = big->num_bis; + + idx = 0; + STAILQ_FOREACH(bis, &big->bis_q, bis_q_next) { + evt->conn_handle[idx] = htole16(bis->conn_handle); + idx++; + } + + ble_ll_hci_event_send(hci_ev); +} + +int +ble_ll_iso_big_hci_create(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_create_big_cp *cmd = (void *)cmdbuf; + struct big_params bp; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!IN_RANGE(cmd->big_handle, 0x00, 0xef) || + !IN_RANGE(cmd->adv_handle, 0x00, 0xef) || + !IN_RANGE(cmd->num_bis, 0x01, 0x1f) || + !IN_RANGE(get_le24(cmd->sdu_interval), 0x0000ff, 0x0fffff) || + !IN_RANGE(le16toh(cmd->max_sdu), 0x0001, 0x0fff) || + !IN_RANGE(le16toh(cmd->max_transport_latency), 0x0005, 0x0fa0) || + !IN_RANGE(cmd->rtn, 0x00, 0x1e) || + (cmd->packing > 1) || (cmd->framing > 1) || (cmd->encryption) > 1) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + bp.sdu_interval = get_le24(cmd->sdu_interval); + bp.max_transport_latency = le16toh(cmd->max_transport_latency); + bp.max_sdu = le16toh(cmd->max_sdu); + if (cmd->phy & BLE_HCI_LE_PHY_2M_PREF_MASK) { + bp.phy = BLE_PHY_2M; + } else if (cmd->phy & BLE_HCI_LE_PHY_1M_PREF_MASK) { + bp.phy = BLE_PHY_1M; + } else { + bp.phy = BLE_PHY_CODED; + } + bp.interleaved = cmd->packing; + bp.framed = cmd->framing; + bp.encrypted = cmd->encryption; + memcpy(bp.broadcast_code, cmd->broadcast_code, 16); + + bp.nse = 1; + bp.bn = 1; + bp.irc = 1; + bp.pto = 0; + bp.iso_interval = bp.sdu_interval / 1250; + bp.max_pdu = bp.max_sdu; + + rc = ble_ll_iso_big_create(cmd->big_handle, cmd->adv_handle, cmd->num_bis, + &bp); + switch (rc) { + case 0: + break; + case -EINVAL: + return BLE_ERR_INV_HCI_CMD_PARMS; + case -ENOMEM: + return BLE_ERR_CONN_REJ_RESOURCES; + case -ENOENT: + return BLE_ERR_UNK_ADV_INDENT; + default: + return BLE_ERR_UNSPECIFIED; + } + + return 0; +} + +int +ble_ll_iso_big_hci_create_test(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_create_big_test_cp *cmd = (void *)cmdbuf; + struct big_params bp; + uint32_t iso_interval_us; + int rc; + + if (len != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (!IN_RANGE(cmd->big_handle, 0x00, 0xef) || + !IN_RANGE(cmd->adv_handle, 0x00, 0xef) || + !IN_RANGE(cmd->num_bis, 0x01, 0x1f) || + !IN_RANGE(get_le24(cmd->sdu_interval), 0x0000ff, 0x0fffff) || + !IN_RANGE(le16toh(cmd->iso_interval), 0x0004, 0x0c80) || + !IN_RANGE(cmd->nse, 0x01, 0x1f) || + !IN_RANGE(le16toh(cmd->max_sdu), 0x0001, 0x0fff) || + !IN_RANGE(le16toh(cmd->max_pdu), 0x0001, 0x00fb) || + /* phy */ + (cmd->packing > 1) || (cmd->framing > 1) || + !IN_RANGE(cmd->bn, 0x01, 0x07) || + !IN_RANGE(cmd->irc, 0x01, 0x0f) || + !IN_RANGE(cmd->pto, 0x00, 0x0f) || + (cmd->encryption) > 1) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + bp.nse = cmd->nse; + bp.bn = cmd->bn; + bp.irc = cmd->irc; + bp.pto = cmd->pto; + bp.sdu_interval = get_le24(cmd->sdu_interval); + bp.iso_interval = le16toh(cmd->iso_interval); + bp.max_sdu = le16toh(cmd->max_sdu); + bp.max_pdu = le16toh(cmd->max_pdu); + /* TODO verify phy */ + if (cmd->phy & BLE_HCI_LE_PHY_2M_PREF_MASK) { + bp.phy = BLE_PHY_2M; + } else if (cmd->phy & BLE_HCI_LE_PHY_1M_PREF_MASK) { + bp.phy = BLE_PHY_1M; + } else { + bp.phy = BLE_PHY_CODED; + } + bp.interleaved = cmd->packing; + bp.framed = cmd->framing; + bp.encrypted = cmd->encryption; + memcpy(bp.broadcast_code, cmd->broadcast_code, 16); + + if (bp.nse % bp.bn) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + iso_interval_us = bp.iso_interval * 1250; + + if (!bp.framed) { + /* sdu_interval shall be an integer multiple of iso_interval */ + if (iso_interval_us % bp.sdu_interval) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* bn shall be an integer multiple of (iso_interval / sdu_interval) */ + if (bp.bn % (iso_interval_us / bp.sdu_interval)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + + rc = ble_ll_iso_big_create(cmd->big_handle, cmd->adv_handle, cmd->num_bis, + &bp); + switch (rc) { + case 0: + break; + case -EINVAL: + return BLE_ERR_INV_HCI_CMD_PARMS; + case -ENOMEM: + return BLE_ERR_CONN_REJ_RESOURCES; + case -ENOENT: + return BLE_ERR_UNK_ADV_INDENT; + default: + return BLE_ERR_UNSPECIFIED; + } + + return 0; +} + +int +ble_ll_iso_big_hci_terminate(const uint8_t *cmdbuf, uint8_t len) +{ + const struct ble_hci_le_terminate_big_cp *cmd = (void *)cmdbuf; + int err; + + err = ble_ll_iso_big_terminate(cmd->big_handle, cmd->reason); + switch (err) { + case 0: + break; + case -ENOENT: + return BLE_ERR_UNK_ADV_INDENT; + default: + return BLE_ERR_UNSPECIFIED; + } + + return 0; +} + +void +ble_ll_iso_big_init(void) +{ + struct ble_ll_iso_big *big; + struct ble_ll_iso_bis *bis; + uint8_t idx; + + memset(big_pool, 0, sizeof(big_pool)); + memset(bis_pool, 0, sizeof(bis_pool)); + + for (idx = 0; idx < BIG_POOL_SIZE; idx++) { + big = &big_pool[idx]; + + big->handle = BIG_HANDLE_INVALID; + + big->sch.sched_type = BLE_LL_SCHED_TYPE_BIG; + big->sch.sched_cb = ble_ll_iso_big_event_sched_cb; + big->sch.cb_arg = big; + + ble_npl_event_init(&big->event_done, ble_ll_iso_big_event_done_ev, big); + } + + for (idx = 0; idx < BIS_POOL_SIZE; idx++) { + bis = &bis_pool[idx]; + bis->conn_handle = BLE_LL_CONN_HANDLE(BLE_LL_CONN_HANDLE_TYPE_BIS, idx); + } + + big_pool_free = ARRAY_SIZE(big_pool); + bis_pool_free = ARRAY_SIZE(bis_pool); +} + +void +ble_ll_iso_big_reset(void) +{ + struct ble_ll_iso_big *big; + int idx; + + for (idx = 0; idx < BIG_POOL_SIZE; idx++) { + big = &big_pool[idx]; + ble_ll_iso_big_free(big); + } + + ble_ll_iso_big_init(); +} + +#endif /* BLE_LL_ISO_BROADCASTER */ +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_isoal.c b/src/nimble/nimble/controller/src/ble_ll_isoal.c new file mode 100644 index 00000000..187b04a0 --- /dev/null +++ b/src/nimble/nimble/controller/src/ble_ll_isoal.c @@ -0,0 +1,406 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef ESP_PLATFORM + +#include +#include +#include +#include +#include +#include + +#if MYNEWT_VAL(BLE_LL_ISO) + +STAILQ_HEAD(ble_ll_iso_tx_q, os_mbuf_pkthdr); + +static struct ble_npl_event ll_isoal_tx_pkt_in; +static struct ble_ll_iso_tx_q ll_isoal_tx_q; + +void +ble_ll_isoal_mux_init(struct ble_ll_isoal_mux *mux, uint8_t max_pdu, + uint32_t iso_interval_us, uint32_t sdu_interval_us, + uint8_t bn, uint8_t pte) +{ + memset(mux, 0, sizeof(*mux)); + + mux->max_pdu = max_pdu; + /* Core 5.3, Vol 6, Part G, 2.1 */ + mux->sdu_per_interval = iso_interval_us / sdu_interval_us; + mux->pdu_per_sdu = bn / mux->sdu_per_interval; + + mux->sdu_per_event = (1 + pte) * mux->sdu_per_interval; + + STAILQ_INIT(&mux->sdu_q); +} + +void +ble_ll_isoal_mux_free(struct ble_ll_isoal_mux *mux) +{ + struct os_mbuf_pkthdr *pkthdr; + struct os_mbuf *om; + struct os_mbuf *om_next; + + pkthdr = STAILQ_FIRST(&mux->sdu_q); + while (pkthdr) { + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + + while (om) { + om_next = SLIST_NEXT(om, om_next); + os_mbuf_free(om); + om = om_next; + } + + STAILQ_REMOVE_HEAD(&mux->sdu_q, omp_next); + pkthdr = STAILQ_FIRST(&mux->sdu_q); + } + + STAILQ_INIT(&mux->sdu_q); +} + +static void +ble_ll_isoal_mux_tx_pkt_in(struct ble_ll_isoal_mux *mux, struct os_mbuf *om, + uint8_t pb, uint32_t timestamp) +{ + struct os_mbuf_pkthdr *pkthdr; + struct ble_mbuf_hdr *blehdr; + os_sr_t sr; + + BLE_LL_ASSERT(mux); + + switch (pb) { + case BLE_HCI_ISO_PB_FIRST: + BLE_LL_ASSERT(!mux->frag); + mux->frag = om; + om = NULL; + break; + case BLE_HCI_ISO_PB_CONTINUATION: + BLE_LL_ASSERT(mux->frag); + os_mbuf_concat(mux->frag, om); + om = NULL; + break; + case BLE_HCI_ISO_PB_COMPLETE: + BLE_LL_ASSERT(!mux->frag); + break; + case BLE_HCI_ISO_PB_LAST: + BLE_LL_ASSERT(mux->frag); + os_mbuf_concat(mux->frag, om); + om = mux->frag; + mux->frag = NULL; + break; + default: + BLE_LL_ASSERT(0); + break; + } + + if (!om) { + return; + } + + blehdr = BLE_MBUF_HDR_PTR(om); + blehdr->txiso.packet_seq_num = ++mux->sdu_counter; + + OS_ENTER_CRITICAL(sr); + pkthdr = OS_MBUF_PKTHDR(om); + STAILQ_INSERT_TAIL(&mux->sdu_q, pkthdr, omp_next); + OS_EXIT_CRITICAL(sr); +} + +int +ble_ll_isoal_mux_event_start(struct ble_ll_isoal_mux *mux, uint32_t timestamp) +{ + struct os_mbuf_pkthdr *pkthdr; + uint8_t num_sdu; + + num_sdu = mux->sdu_per_event; + + pkthdr = STAILQ_FIRST(&mux->sdu_q); + while (pkthdr && num_sdu--) { + pkthdr = STAILQ_NEXT(pkthdr, omp_next); + } + + mux->sdu_in_event = mux->sdu_per_event - num_sdu; + mux->event_tx_timestamp = timestamp; + + return mux->sdu_in_event; +} + +int +ble_ll_isoal_mux_event_done(struct ble_ll_isoal_mux *mux) +{ + struct os_mbuf_pkthdr *pkthdr; + struct ble_mbuf_hdr *blehdr; + struct os_mbuf *om; + struct os_mbuf *om_next; + uint8_t num_sdu; + int pkt_freed = 0; + + num_sdu = min(mux->sdu_in_event, mux->sdu_per_interval); + + pkthdr = STAILQ_FIRST(&mux->sdu_q); + if (pkthdr) { + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + blehdr = BLE_MBUF_HDR_PTR(om); + mux->last_tx_timestamp = mux->event_tx_timestamp; + mux->last_tx_packet_seq_num = blehdr->txiso.packet_seq_num; + } + + while (pkthdr && num_sdu--) { + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + + while (om) { + om_next = SLIST_NEXT(om, om_next); + os_mbuf_free(om); + pkt_freed++; + om = om_next; + } + + STAILQ_REMOVE_HEAD(&mux->sdu_q, omp_next); + pkthdr = STAILQ_FIRST(&mux->sdu_q); + } + + mux->sdu_in_event = 0; + + return pkt_freed; +} + +int +ble_ll_isoal_mux_unframed_get(struct ble_ll_isoal_mux *mux, uint8_t idx, + uint8_t *llid, void *dptr) +{ + struct os_mbuf_pkthdr *pkthdr; + struct os_mbuf *om; + uint8_t sdu_idx; + uint8_t pdu_idx; + uint16_t sdu_offset; + uint16_t rem_len; + uint8_t pdu_len; + + sdu_idx = idx / mux->pdu_per_sdu; + pdu_idx = idx - sdu_idx * mux->pdu_per_sdu; + + if (sdu_idx >= mux->sdu_in_event) { + *llid = 1; + return 0; + } + + pkthdr = STAILQ_FIRST(&mux->sdu_q); + while (pkthdr && sdu_idx--) { + pkthdr = STAILQ_NEXT(pkthdr, omp_next); + } + + if (!pkthdr) { + *llid = 1; + return 0; + } + + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + sdu_offset = pdu_idx * mux->max_pdu; + rem_len = OS_MBUF_PKTLEN(om) - sdu_offset; + + if ((int32_t)rem_len <= 0) { + *llid = 1; + pdu_len = 0; + } else { + *llid = (pdu_idx < mux->pdu_per_sdu - 1); + pdu_len = min(mux->max_pdu, rem_len); + } + + os_mbuf_copydata(om, sdu_offset, pdu_len, dptr); + + return pdu_len; +} + +static void +ble_ll_isoal_tx_pkt_in(struct ble_npl_event *ev) +{ + struct os_mbuf *om; + struct os_mbuf_pkthdr *pkthdr; + struct ble_hci_iso *hci_iso; + struct ble_hci_iso_data *hci_iso_data; + struct ble_ll_isoal_mux *mux; + uint16_t data_hdr_len; + uint16_t handle; + uint16_t conn_handle; + uint16_t length; + uint16_t pb_flag; + uint16_t ts_flag; + uint32_t timestamp = 0; + os_sr_t sr; + + while (STAILQ_FIRST(&ll_isoal_tx_q)) { + pkthdr = STAILQ_FIRST(&ll_isoal_tx_q); + om = OS_MBUF_PKTHDR_TO_MBUF(pkthdr); + + OS_ENTER_CRITICAL(sr); + STAILQ_REMOVE_HEAD(&ll_isoal_tx_q, omp_next); + OS_EXIT_CRITICAL(sr); + + hci_iso = (void *)om->om_data; + + handle = le16toh(hci_iso->handle); + conn_handle = BLE_HCI_ISO_CONN_HANDLE(handle); + pb_flag = BLE_HCI_ISO_PB_FLAG(handle); + ts_flag = BLE_HCI_ISO_TS_FLAG(handle); + length = BLE_HCI_ISO_LENGTH(le16toh(hci_iso->length)); + + data_hdr_len = 0; + if ((pb_flag == BLE_HCI_ISO_PB_FIRST) || + (pb_flag == BLE_HCI_ISO_PB_COMPLETE)) { + if (ts_flag) { + timestamp = get_le32(om->om_data + sizeof(*hci_iso)); + data_hdr_len += sizeof(uint32_t); + } + + hci_iso_data = (void *)(om->om_data + sizeof(*hci_iso) + data_hdr_len); + data_hdr_len += sizeof(*hci_iso_data); + } + os_mbuf_adj(om, sizeof(*hci_iso) + data_hdr_len); + + if (OS_MBUF_PKTLEN(om) != length - data_hdr_len) { + os_mbuf_free_chain(om); + continue; + } + + switch (BLE_LL_CONN_HANDLE_TYPE(conn_handle)) { + case BLE_LL_CONN_HANDLE_TYPE_BIS: + mux = ble_ll_iso_big_find_mux_by_handle(conn_handle); + ble_ll_isoal_mux_tx_pkt_in(mux, om, pb_flag, timestamp); + break; + default: + os_mbuf_free_chain(om); + break; + } + } +} + +int +ble_ll_isoal_hci_setup_iso_data_path(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_setup_iso_data_path_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_setup_iso_data_path_rp *rsp = (void *)rspbuf; + struct ble_ll_iso_bis *bis; + uint16_t conn_handle; + + conn_handle = le16toh(cmd->conn_handle); + switch (BLE_LL_CONN_HANDLE_TYPE(conn_handle)) { + case BLE_LL_CONN_HANDLE_TYPE_BIS: + bis = ble_ll_iso_big_find_bis_by_handle(conn_handle); + if (bis) { + break; + } + default: + return BLE_ERR_UNK_CONN_ID; + } + + /* Only input for now since we only support BIS */ + if (cmd->data_path_dir) { + return BLE_ERR_CMD_DISALLOWED; + } + + /* We do not (yet) support any vendor-specific data path */ + if (cmd->data_path_id) { + return BLE_ERR_CMD_DISALLOWED; + } + + rsp->conn_handle = cmd->conn_handle; + *rsplen = sizeof(*rsp); + + return 0; +} + +int +ble_ll_isoal_hci_remove_iso_data_path(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_remove_iso_data_path_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_remove_iso_data_path_rp *rsp = (void *)rspbuf; + + /* XXX accepts anything for now */ + rsp->conn_handle = cmd->conn_handle; + *rsplen = sizeof(*rsp); + + return 0; +} + +int +ble_ll_isoal_hci_read_tx_sync(const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_le_read_iso_tx_sync_cp *cmd = (const void *)cmdbuf; + struct ble_hci_le_read_iso_tx_sync_rp *rsp = (void *)rspbuf; + struct ble_ll_isoal_mux *mux; + uint16_t handle; + + handle = le16toh(cmd->conn_handle); + switch (BLE_LL_CONN_HANDLE_TYPE(handle)) { + case BLE_LL_CONN_HANDLE_TYPE_BIS: + mux = ble_ll_iso_big_find_mux_by_handle(handle); + if (!mux) { + return BLE_ERR_UNK_CONN_ID; + } + break; + default: + return BLE_ERR_UNK_CONN_ID; + } + + rsp->conn_handle = cmd->conn_handle; + rsp->packet_seq_num = htole16(mux->last_tx_packet_seq_num); + rsp->tx_timestamp = htole32(mux->last_tx_timestamp); + put_le24(rsp->time_offset, 0); + + *rsplen = sizeof(*rsp); + + return 0; +} + +void +ble_ll_isoal_init(void) +{ + STAILQ_INIT(&ll_isoal_tx_q); + ble_npl_event_init(&ll_isoal_tx_pkt_in, ble_ll_isoal_tx_pkt_in, NULL); +} + +void +ble_ll_isoal_reset(void) +{ + STAILQ_INIT(&ll_isoal_tx_q); + ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &ll_isoal_tx_pkt_in); +} + +int +ble_ll_isoal_data_in(struct os_mbuf *om) +{ + struct os_mbuf_pkthdr *hdr; + os_sr_t sr; + + hdr = OS_MBUF_PKTHDR(om); + + OS_ENTER_CRITICAL(sr); + STAILQ_INSERT_TAIL(&ll_isoal_tx_q, hdr, omp_next); + OS_EXIT_CRITICAL(sr); + + ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ll_isoal_tx_pkt_in); + + return 0; +} + +#endif /* BLE_LL_ISO */ +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/src/ble_ll_pdu.c b/src/nimble/nimble/controller/src/ble_ll_pdu.c new file mode 100644 index 00000000..bd254199 --- /dev/null +++ b/src/nimble/nimble/controller/src/ble_ll_pdu.c @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +static const uint16_t syncword_len[] = { + [BLE_PHY_MODE_1M] = (BLE_LL_PDU_PREAMBLE_1M_LEN + BLE_LL_PDU_AA_LEN) * 8, + [BLE_PHY_MODE_2M] = (BLE_LL_PDU_PREAMBLE_2M_LEN + BLE_LL_PDU_AA_LEN) * 4, + [BLE_PHY_MODE_CODED_125KBPS] = 80 + 256 + 16 + 24, + [BLE_PHY_MODE_CODED_500KBPS] = 80 + 256 + 16 + 24, +}; + +static const uint16_t payload0_len[] = { + [BLE_PHY_MODE_1M] = (BLE_LL_PDU_PREAMBLE_1M_LEN + BLE_LL_PDU_AA_LEN + + BLE_LL_PDU_HEADER_LEN + BLE_LL_PDU_CRC_LEN) * 8, + [BLE_PHY_MODE_2M] = (BLE_LL_PDU_PREAMBLE_2M_LEN + BLE_LL_PDU_AA_LEN + + BLE_LL_PDU_HEADER_LEN + BLE_LL_PDU_CRC_LEN) * 4, + [BLE_PHY_MODE_CODED_125KBPS] = 80 + 256 + 16 + 24 + + 8 * (BLE_LL_PDU_HEADER_LEN * 8 + 24 + 3), + [BLE_PHY_MODE_CODED_500KBPS] = 80 + 256 + 16 + 24 + + 2 * (BLE_LL_PDU_HEADER_LEN * 8 + 24 + 3), +}; + +static const uint8_t us_per_octet[] = { + [BLE_PHY_MODE_1M] = 8, + [BLE_PHY_MODE_2M] = 4, + [BLE_PHY_MODE_CODED_125KBPS] = 64, + [BLE_PHY_MODE_CODED_500KBPS] = 16, +}; + +uint32_t +ble_ll_pdu_syncword_us(uint8_t phy_mode) +{ + return syncword_len[phy_mode]; +} + +uint32_t +ble_ll_pdu_us(uint8_t payload_len, uint8_t phy_mode) +{ + return payload0_len[phy_mode] + (payload_len * us_per_octet[phy_mode]); +} diff --git a/src/nimble/nimble/controller/src/ble_ll_priv.h b/src/nimble/nimble/controller/src/ble_ll_priv.h index ca8e0829..5b711c95 100644 --- a/src/nimble/nimble/controller/src/ble_ll_priv.h +++ b/src/nimble/nimble/controller/src/ble_ll_priv.h @@ -25,11 +25,39 @@ extern "C" { #endif extern int8_t g_ble_ll_tx_power; +extern int8_t g_ble_ll_tx_power_compensation; +extern int8_t g_ble_ll_rx_power_compensation; + +int ble_ll_tx_power_round(int tx_power); +void ble_ll_tx_power_set(int tx_power); + +static inline int +ble_ll_rx_gain(void) +{ + int gain = g_ble_ll_rx_power_compensation; + +#if MYNEWT_VAL(BLE_FEM_LNA) +#if MYNEWT_VAL(BLE_FEM_LNA_GAIN_TUNABLE) + gain += ble_fem_lna_rx_gain(); +#else + gain += MYNEWT_VAL(BLE_FEM_LNA_GAIN); +#endif +#endif + + return gain; +} + +/* if there is any radio related activity enabled + * (scanning, advertising, connection etc) + */ +#define BLE_LL_BUSY_EXCLUDE_CONNECTIONS 0x01 + +int ble_ll_is_busy(unsigned int flags); #ifdef MYNEWT -#include "syscfg/syscfg.h" -#include "hal/hal_gpio.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/hal/hal_gpio.h" #define BLE_LL_DEBUG_GPIO_INIT(_name) \ if (MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name) >= 0) { \ diff --git a/src/nimble/nimble/controller/src/ble_ll_rand.c b/src/nimble/nimble/controller/src/ble_ll_rand.c index 3bbd1c80..c8ddbb66 100644 --- a/src/nimble/nimble/controller/src/ble_ll_rand.c +++ b/src/nimble/nimble/controller/src/ble_ll_rand.c @@ -28,12 +28,16 @@ #include "nimble/porting/nimble/include/os/os.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" #if MYNEWT_VAL(TRNG) #include "trng/trng.h" #endif +#ifdef RIOT_VERSION +#include "random.h" +#endif + #if BABBLESIM extern void tm_tick(void); #endif @@ -135,6 +139,7 @@ ble_ll_rand_data_get(uint8_t *buf, uint8_t len) uint32_t ble_ll_rand(void) { +#ifndef RIOT_VERSION static unsigned short xsubi[3]; static bool init = true; @@ -144,6 +149,9 @@ ble_ll_rand(void) } return (uint32_t) jrand48(xsubi); +#else + return random_uint32(); +#endif } /** diff --git a/src/nimble/nimble/controller/src/ble_ll_resolv.c b/src/nimble/nimble/controller/src/ble_ll_resolv.c index 00df46ad..a3f111b9 100644 --- a/src/nimble/nimble/controller/src/ble_ll_resolv.c +++ b/src/nimble/nimble/controller/src/ble_ll_resolv.c @@ -25,14 +25,15 @@ #include "nimble/porting/nimble/include/os/os.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_sync.h" -#include "../include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_resolv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_ll_adv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sync.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" #include "ble_ll_conn_priv.h" +#include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) struct ble_ll_resolv_data @@ -49,35 +50,6 @@ struct ble_ll_resolv_data g_ble_ll_resolv_data; __attribute__((aligned(4))) struct ble_ll_resolv_entry g_ble_ll_resolv_list[MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)]; -static int -ble_ll_is_controller_busy(void) -{ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) - if (ble_ll_sync_enabled()) { - return 1; - } -#endif - -#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) - if (ble_ll_adv_enabled()) { - return 1; - } -#endif - -#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) - if (ble_ll_scan_enabled()) { - return 1; - } -#endif - -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) - if (g_ble_ll_conn_create_sm.connsm) { - return 1; - } -#endif - - return 0; -} /** * Called to determine if a change is allowed to the resolving list at this * time. We are not allowed to modify the resolving list if address translation @@ -92,7 +64,7 @@ ble_ll_resolv_list_chg_allowed(void) int rc; if (g_ble_ll_resolv_data.addr_res_enabled && - ble_ll_is_controller_busy()) { + ble_ll_is_busy(BLE_LL_BUSY_EXCLUDE_CONNECTIONS)) { rc = 0; } else { rc = 1; @@ -458,8 +430,8 @@ ble_ll_resolv_enable_cmd(const uint8_t *cmdbuf, uint8_t len) return BLE_ERR_INV_HCI_CMD_PARMS; } - if (ble_ll_is_controller_busy()) { - return BLE_ERR_CMD_DISALLOWED; + if (ble_ll_is_busy(BLE_LL_BUSY_EXCLUDE_CONNECTIONS)) { + return BLE_ERR_CMD_DISALLOWED; } @@ -563,7 +535,7 @@ ble_ll_resolve_set_priv_mode(const uint8_t *cmdbuf, uint8_t len) const struct ble_hci_le_set_privacy_mode_cp *cmd = (const void *) cmdbuf; struct ble_ll_resolv_entry *rl; - if (ble_ll_is_controller_busy()) { + if (ble_ll_is_busy(BLE_LL_BUSY_EXCLUDE_CONNECTIONS)) { return BLE_ERR_CMD_DISALLOWED; } diff --git a/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c b/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c index 6eda7e03..52df894c 100644 --- a/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c +++ b/src/nimble/nimble/controller/src/ble_ll_rfmgmt.c @@ -21,13 +21,12 @@ #include #include #include -#include #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" #include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0 @@ -198,8 +197,7 @@ ble_ll_rfmgmt_ticks_to_enabled(void) break; } rfmgmt->state = RFMGMT_STATE_ENABLED; - /* Else falls through. */ - /* no break */ + /* fall through */ case RFMGMT_STATE_ENABLED: rem_ticks = 0; break; @@ -239,7 +237,7 @@ ble_ll_rfmgmt_reset(void) rfmgmt->timer_scheduled_at = 0; ble_ll_tmr_stop(&rfmgmt->timer); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev); + ble_ll_event_remove(&rfmgmt->release_ev); ble_ll_rfmgmt_disable(); @@ -293,10 +291,10 @@ ble_ll_rfmgmt_release(void) OS_ENTER_CRITICAL(sr); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev); + ble_ll_event_remove(&rfmgmt->release_ev); if (g_ble_ll_rfmgmt_data.state != RFMGMT_STATE_OFF) { - ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev); + ble_ll_event_add(&rfmgmt->release_ev); } OS_EXIT_CRITICAL(sr); diff --git a/src/nimble/nimble/controller/src/ble_ll_scan.c b/src/nimble/nimble/controller/src/ble_ll_scan.c index ce1a02b9..8e5fda9b 100644 --- a/src/nimble/nimble/controller/src/ble_ll_scan.c +++ b/src/nimble/nimble/controller/src/ble_ll_scan.c @@ -27,22 +27,23 @@ #include "nimble/porting/nimble/include/os/os.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#include "../include/controller/ble_ll_scan_aux.h" -#endif -#include "../include/controller/ble_ll_tmr.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_ll_sync.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan_aux.h" +#endif +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_whitelist.h" +#include "nimble/nimble/controller/include/controller/ble_ll_resolv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h" +#include "nimble/nimble/controller/include/controller/ble_ll_trace.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sync.h" #include "ble_ll_conn_priv.h" +#include "ble_ll_priv.h" #if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) @@ -363,11 +364,6 @@ ble_ll_scan_get_ext_adv_report(struct ext_adv_report *copy_from) return hci_ev; } - -void -ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data) -{ -} #endif void @@ -443,7 +439,7 @@ ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd, /* XXX: for now, if we dont have room, just leave */ num_advs = g_ble_ll_scan_num_rsp_advs; - if (num_advs == MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS)) { + if (num_advs >= MYNEWT_VAL(BLE_LL_NUM_SCAN_RSP_ADVS)) { return; } @@ -703,6 +699,14 @@ ble_ll_scan_send_adv_report(uint8_t pdu_type, } if (BLE_MBUF_HDR_TARGETA_RESOLVED(hdr)) { inita_type += 2; + } else { +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (scansm->ext_scanning) { + if (ble_ll_is_rpa(inita, inita_type)) { + inita_type = 0xfe; + } + } +#endif } #endif @@ -710,7 +714,7 @@ ble_ll_scan_send_adv_report(uint8_t pdu_type, if (scansm->ext_scanning) { rc = ble_ll_hci_send_legacy_ext_adv_report(evtype, adva, adva_type, - hdr->rxinfo.rssi, + hdr->rxinfo.rssi - ble_ll_rx_gain(), adv_data_len, om, inita, inita_type); goto done; @@ -719,11 +723,12 @@ goto done; if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) { rc = ble_ll_hci_send_dir_adv_report(adva, adva_type, inita, inita_type, - hdr->rxinfo.rssi); + hdr->rxinfo.rssi - ble_ll_rx_gain()); goto done; } - rc = ble_ll_hci_send_adv_report(evtype, adva, adva_type, hdr->rxinfo.rssi, + rc = ble_ll_hci_send_adv_report(evtype, adva, adva_type, + hdr->rxinfo.rssi - ble_ll_rx_gain(), adv_data_len, om); done: if (!rc && scansm->scan_filt_dups) { @@ -782,6 +787,13 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm) ble_phy_mode_set(phy_mode, phy_mode); #endif + /* if scan is not passive we need to set tx power as we may end up sending + * package + */ + if (scansm->scanp->scan_type != BLE_SCAN_TYPE_PASSIVE) { + ble_ll_tx_power_set(g_ble_ll_tx_power); + } + rc = ble_phy_rx_set_start_time(ble_ll_tmr_get() + g_ble_ll_sched_offset_ticks, 0); if (!rc || rc == BLE_PHY_ERR_RX_LATE) { @@ -882,10 +894,6 @@ ble_ll_scan_sm_stop(int chk_disable) OS_ENTER_CRITICAL(sr); -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) - scansm->connsm = NULL; -#endif - /* Disable scanning state machine */ scansm->scan_enabled = 0; scansm->restart_timer_needed = 0; @@ -897,6 +905,10 @@ ble_ll_scan_sm_stop(int chk_disable) } #endif +#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) + scansm->connsm = NULL; +#endif + /* Update backoff if we failed to receive scan response */ if (scansm->scan_rsp_pending) { scansm->scan_rsp_pending = 0; @@ -1111,6 +1123,11 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev) case BLE_LL_STATE_SCAN_AUX: start_scan = false; break; +#endif +#if MYNEWT_VAL(BLE_LL_EXT) + case BLE_LL_STATE_EXTERNAL: + start_scan = false; + break; #endif case BLE_LL_STATE_SCANNING: /* Must disable PHY since we will move to a new channel */ @@ -1119,6 +1136,11 @@ ble_ll_scan_event_proc(struct ble_npl_event *ev) ble_ll_state_set(BLE_LL_STATE_STANDBY); } break; +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + case BLE_LL_STATE_BIG: + start_scan = false; + break; +#endif case BLE_LL_STATE_STANDBY: break; default: @@ -1269,17 +1291,17 @@ ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, switch (ble_ll_addr_subtype(addrd->adva, addrd->adva_type)) { case BLE_LL_ADDR_SUBTYPE_RPA: - if (addrd->rpa_index < 0) { + if (addrd->rpa_index >= 0) { + addrd->adva_resolved = 1; + + /* Use resolved identity address as advertiser address */ + rl = &g_ble_ll_resolv_list[addrd->rpa_index]; + addrd->adv_addr = rl->rl_identity_addr; + addrd->adv_addr_type = rl->rl_addr_type; break; } - addrd->adva_resolved = 1; - - /* Use resolved identity address as advertiser address */ - rl = &g_ble_ll_resolv_list[addrd->rpa_index]; - addrd->adv_addr = rl->rl_identity_addr; - addrd->adv_addr_type = rl->rl_addr_type; - break; + /* fall-through */ case BLE_LL_ADDR_SUBTYPE_IDENTITY: /* If AdvA is an identity address, we need to check if that device was * added to RL in order to use proper privacy mode. @@ -1327,7 +1349,8 @@ ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, } /* Ignore if not directed to us */ - if (!ble_ll_is_our_devaddr(addrd->targeta, addrd->targeta_type)) { + if ((addrd->targeta_type != (own_addr_type & 0x01)) || + !ble_ll_is_our_devaddr(addrd->targeta, addrd->targeta_type)) { return -1; } break; @@ -1341,7 +1364,8 @@ ble_ll_scan_rx_filter(uint8_t own_addr_type, uint8_t scan_filt_policy, #else /* Ignore if not directed to us */ if (addrd->targeta && - !ble_ll_is_our_devaddr(addrd->targeta, addrd->targeta_type)) { + ((addrd->targeta_type != (own_addr_type & 0x01)) || + !ble_ll_is_our_devaddr(addrd->targeta, addrd->targeta_type))) { return -1; } @@ -1527,10 +1551,8 @@ ble_ll_scan_send_scan_req(uint8_t pdu_type, uint8_t *rxbuf, BLE_LL_ASSERT(scansm->scan_rsp_pending == 0); /* We want to send a request. See if backoff allows us */ - if (scansm->backoff_count > 0) { - if (--scansm->backoff_count != 0) { - return false; - } + if (ble_ll_scan_backoff_kick() != 0) { + return false; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) @@ -1676,7 +1698,7 @@ ble_ll_scan_chk_resume(void) OS_ENTER_CRITICAL(sr); if (scansm->restart_timer_needed) { scansm->restart_timer_needed = 0; - ble_ll_event_send(&scansm->scan_sched_ev); + ble_ll_event_add(&scansm->scan_sched_ev); STATS_INC(ble_ll_stats, scan_timer_restarted); OS_EXIT_CRITICAL(sr); return; @@ -1706,13 +1728,13 @@ ble_ll_scan_timer_cb(void *arg) struct ble_ll_scan_sm *scansm; scansm = (struct ble_ll_scan_sm *)arg; - ble_ll_event_send(&scansm->scan_sched_ev); + ble_ll_event_add(&scansm->scan_sched_ev); } void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm) { - ble_ll_event_send(&scansm->scan_interrupted_ev); + ble_ll_event_add(&scansm->scan_interrupted_ev); } /** @@ -2100,17 +2122,15 @@ ble_ll_scan_check_phy_params(uint8_t type, uint16_t itvl, uint16_t window) return BLE_ERR_INV_HCI_CMD_PARMS; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wtype-limits" /* Check interval and window */ if ((itvl < BLE_HCI_SCAN_ITVL_MIN) || - (itvl > BLE_HCI_SCAN_ITVL_MAX_EXT) || + // (itvl > BLE_HCI_SCAN_ITVL_MAX_EXT) || (window < BLE_HCI_SCAN_WINDOW_MIN) || - (window > BLE_HCI_SCAN_WINDOW_MAX_EXT) || + // (window > BLE_HCI_SCAN_WINDOW_MAX_EXT) || (itvl < window)) { return BLE_ERR_INV_HCI_CMD_PARMS; } -#pragma GCC diagnostic pop + return 0; } @@ -2303,6 +2323,27 @@ ble_ll_scan_set_enable(uint8_t enable, uint8_t filter_dups, uint16_t period, scansm = &g_ble_ll_scan_sm; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (ext) { + /* + * If Enable is set to 0x01 and the Host has not issued the + * HCI_LE_Set_Extended_Scan_Parameters command, the Controller shall + * either use vendor-specified parameters or return the error code + * Command Disallowed (0x0C) + * + * To keep things simple for devices without public address we + * reject in such case. + */ + for (i = 0; i < BLE_LL_SCAN_PHY_NUMBER; i++) { + if (g_ble_ll_scan_params.scan_phys[i].configured) { + break; + } + } + + if (i == BLE_LL_SCAN_PHY_NUMBER) { + return BLE_ERR_CMD_DISALLOWED; + } + } + /* we can do that here since value will never change until reset */ scansm->ext_scanning = ext; diff --git a/src/nimble/nimble/controller/src/ble_ll_scan_aux.c b/src/nimble/nimble/controller/src/ble_ll_scan_aux.c index 2253d45f..77eaaf76 100644 --- a/src/nimble/nimble/controller/src/ble_ll_scan_aux.c +++ b/src/nimble/nimble/controller/src/ble_ll_scan_aux.c @@ -17,9 +17,7 @@ * under the License. */ -#ifndef ESP_PLATFORM - -#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include #if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) && MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) @@ -30,16 +28,19 @@ #include "nimble/porting/nimble/include/os/os.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_hw.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_scan_aux.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_sync.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_pdu.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan_aux.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_whitelist.h" +#include "nimble/nimble/controller/include/controller/ble_ll_resolv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sync.h" +#include "ble_ll_priv.h" #define BLE_LL_SCAN_AUX_F_AUX_ADV 0x0001 #define BLE_LL_SCAN_AUX_F_AUX_CHAIN 0x0002 @@ -58,10 +59,6 @@ #define BLE_LL_SCAN_AUX_H_DONE 0x02 #define BLE_LL_SCAN_AUX_H_TRUNCATED 0x04 -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - struct ble_ll_scan_aux_data { uint16_t flags; uint8_t hci_state; @@ -71,7 +68,7 @@ struct ble_ll_scan_aux_data { uint8_t pri_phy; uint8_t sec_phy; uint8_t chan; - uint8_t offset_unit : 1; + uint16_t wfr_us; uint32_t aux_ptr; struct ble_ll_sched_item sch; struct ble_npl_event break_ev; @@ -114,7 +111,6 @@ static int ble_ll_scan_aux_sched_cb(struct ble_ll_sched_item *sch) { struct ble_ll_scan_aux_data *aux = sch->cb_arg; - uint32_t wfr_us; #if BLE_LL_BT5_PHY_SUPPORTED uint8_t phy_mode; #endif @@ -146,6 +142,14 @@ ble_ll_scan_aux_sched_cb(struct ble_ll_sched_item *sch) ble_phy_mode_set(phy_mode, phy_mode); #endif + /* if scan is not passive we need to set tx power as we may end up sending + * package + */ + /* TODO do this only on first AUX? */ + if (aux->scan_type != BLE_SCAN_TYPE_PASSIVE) { + ble_ll_tx_power_set(g_ble_ll_tx_power); + } + rc = ble_phy_rx_set_start_time(sch->start_time + g_ble_ll_sched_offset_ticks, sch->remainder); if (rc != 0 && rc != BLE_PHY_ERR_RX_LATE) { @@ -161,8 +165,7 @@ ble_ll_scan_aux_sched_cb(struct ble_ll_sched_item *sch) ble_ll_whitelist_disable(); } - wfr_us = aux->offset_unit ? 300 : 30; - ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, wfr_us); + ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, 0, aux->wfr_us); aux_data_current = aux; @@ -204,21 +207,6 @@ ble_ll_scan_aux_free(struct ble_ll_scan_aux_data *aux) os_memblock_put(&aux_data_pool, aux); } -static void -ble_ll_scan_aux_update_scan_backoff(struct ble_ll_scan_aux_data *aux) -{ - if (!(aux->flags & BLE_LL_SCAN_AUX_F_W4_SCAN_RSP) && - !(aux->flags & BLE_LL_SCAN_AUX_F_SCANNED)) { - return; - } - - if ((aux->hci_state & BLE_LL_SCAN_AUX_H_DONE) && - !(aux->hci_state & BLE_LL_SCAN_AUX_H_TRUNCATED)) { - ble_ll_scan_backoff_update(1); - } else { - ble_ll_scan_backoff_update(0); - } -} static inline bool ble_ll_scan_aux_need_truncation(struct ble_ll_scan_aux_data *aux) @@ -276,6 +264,8 @@ ble_ll_hci_ev_alloc_ext_adv_report_for_aux(struct ble_ll_scan_addr_data *addrd, #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) if (addrd->targeta_resolved) { report->dir_addr_type += 2; + } else if (ble_ll_is_rpa(addrd->targeta, addrd->targeta_type)) { + report->dir_addr_type = 0xfe; } #endif } @@ -427,7 +417,7 @@ ble_ll_hci_ev_update_ext_adv_report_from_ext(struct ble_hci_ev *hci_ev, report->pri_phy = rxinfo->phy; report->sec_phy = 0; report->sid = 0xff; - report->rssi = rxhdr->rxinfo.rssi; + report->rssi = rxhdr->rxinfo.rssi - ble_ll_rx_gain(); report->periodic_itvl = 0; report->data_len = 0; @@ -457,7 +447,12 @@ ble_ll_hci_ev_update_ext_adv_report_from_ext(struct ble_hci_ev *hci_ev, report->dir_addr_type = (ble_ll_scan_get_own_addr_type() & 1) + 2; memcpy(report->dir_addr, ble_ll_scan_aux_get_own_addr(), 6); } else { - report->dir_addr_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_MASK); + if (ble_ll_is_rpa(eh_data, pdu_hdr & BLE_ADV_PDU_HDR_RXADD_MASK)) { + report->dir_addr_type = 0xfe; + } else { + report->dir_addr_type = !!(pdu_hdr & + BLE_ADV_PDU_HDR_RXADD_MASK); + } memcpy(report->dir_addr, eh_data, 6); } #else @@ -543,9 +538,9 @@ ble_ll_hci_ev_send_ext_adv_report(struct os_mbuf *rxpdu, hci_subev = (void *)(*hci_ev)->data; report = hci_subev->reports; - report->rssi = rxinfo->rssi; + report->rssi = rxinfo->rssi - ble_ll_rx_gain(); - report->data_len = min(max_data_len, data_len - offset); + report->data_len = MIN(max_data_len, data_len - offset); os_mbuf_copydata(rxpdu, offset, report->data_len, report->data); (*hci_ev)->length += report->data_len; @@ -563,12 +558,14 @@ ble_ll_hci_ev_send_ext_adv_report(struct os_mbuf *rxpdu, } else { report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; } + } else if (rxinfo->flags & BLE_MBUF_HDR_F_AUX_PTR_FAILED) { + report->evt_type |= BLE_HCI_ADV_DATA_STATUS_TRUNCATED; } switch (report->evt_type & BLE_HCI_ADV_DATA_STATUS_MASK) { case BLE_HCI_ADV_DATA_STATUS_TRUNCATED: truncated = true; - /* Else falls through. */ + /* fall through */ case BLE_HCI_ADV_DATA_STATUS_COMPLETE: BLE_LL_ASSERT(!hci_ev_next); break; @@ -599,6 +596,7 @@ ble_ll_hci_ev_send_ext_adv_report_for_aux(struct os_mbuf *rxpdu, int rc; if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_EXT_ADV_RPT)) { + aux->hci_state = BLE_LL_SCAN_AUX_H_DONE; return -1; } @@ -613,6 +611,7 @@ ble_ll_hci_ev_send_ext_adv_report_for_aux(struct os_mbuf *rxpdu, } else { hci_ev = ble_ll_hci_ev_alloc_ext_adv_report_for_aux(addrd, aux); if (!hci_ev) { + aux->hci_state = BLE_LL_SCAN_AUX_H_DONE; return -1; } } @@ -667,7 +666,10 @@ ble_ll_scan_aux_break_ev(struct ble_npl_event *ev) ble_ll_hci_ev_send_ext_adv_truncated_report(aux); } - ble_ll_scan_aux_update_scan_backoff(aux); + /* Update backoff if we were waiting for scan response */ + if (aux->flags & BLE_LL_SCAN_AUX_F_W4_SCAN_RSP) { + ble_ll_scan_backoff_update(0); + } ble_ll_scan_aux_free(aux); ble_ll_scan_chk_resume(); @@ -683,81 +685,91 @@ ble_ll_scan_aux_break(struct ble_ll_scan_aux_data *aux) #endif ble_npl_event_init(&aux->break_ev, ble_ll_scan_aux_break_ev, aux); - ble_ll_event_send(&aux->break_ev); + ble_ll_event_add(&aux->break_ev); } static int -ble_ll_scan_aux_parse_aux_ptr(struct ble_ll_scan_aux_data *aux, - uint32_t aux_ptr, uint32_t *offset_us) +ble_ll_scan_aux_phy_to_phy(uint8_t aux_phy, uint8_t *phy) { - uint8_t offset_unit; - uint32_t offset; - uint8_t chan; - uint8_t phy; - - phy = (aux_ptr >> 21) & 0x07; - switch (phy) { + switch (aux_phy) { case 0: - phy = BLE_PHY_1M; + *phy = BLE_PHY_1M; break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) case 1: - phy = BLE_PHY_2M; + *phy = BLE_PHY_2M; break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) case 2: - phy = BLE_PHY_CODED; + *phy = BLE_PHY_CODED; break; #endif default: return -1; } + return 0; +} + +int +ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_ticks, + uint8_t pdu_rem_us, uint32_t aux_ptr) +{ + struct ble_ll_sched_item *sch; + uint32_t aux_offset; + uint8_t offset_unit; + uint8_t aux_phy; + uint8_t chan; + uint8_t ca; + uint8_t phy; + uint32_t offset_us; + uint16_t pdu_rx_us; + uint16_t aux_ww_us; + uint16_t aux_tx_win_us; + + /* Parse AuxPtr */ chan = aux_ptr & 0x3f; + ca = aux_ptr & 0x40; + offset_unit = aux_ptr & 0x80; + aux_offset = (aux_ptr >> 8) & 0x1fff; + aux_phy = (aux_ptr >> 21) & 0x07; + if (chan >= BLE_PHY_NUM_DATA_CHANS) { return -1; } - offset = 30 * ((aux_ptr >> 8) & 0x1fff); - if ((aux_ptr >> 7) & 0x01) { - offset *= 10; - offset_unit = 1; - } else { - offset_unit = 0; - } - - if (offset < BLE_LL_MAFS) { + if (ble_ll_scan_aux_phy_to_phy(aux_phy, &phy) < 0) { return -1; } + /* Actual offset */ + offset_us = aux_offset * (offset_unit ? 300 : 30); + /* Time to scan aux PDU */ + pdu_rx_us = ble_ll_pdu_us(MYNEWT_VAL(BLE_LL_SCHED_SCAN_AUX_PDU_LEN), + ble_ll_phy_to_phy_mode(phy, 0)); + /* Transmit window */ + aux_tx_win_us = offset_unit ? 300 : 30; + /* Window widening to include drift due to sleep clock accuracy and jitter */ + aux_ww_us = offset_us * (ca ? 50 : 500) / 1000000 + BLE_LL_JITTER_USECS; + aux->sec_phy = phy; aux->chan = chan; - aux->offset_unit = offset_unit; + aux->wfr_us = aux_ww_us + aux_tx_win_us; - *offset_us = offset; + sch = &aux->sch; - return 0; -} + sch->start_time = pdu_ticks; + sch->remainder = pdu_rem_us; + ble_ll_tmr_add(&sch->start_time, &sch->remainder, offset_us - aux_ww_us); -int -ble_ll_scan_aux_sched(struct ble_ll_scan_aux_data *aux, uint32_t pdu_time, - uint8_t pdu_time_rem, uint32_t aux_ptr) -{ - uint32_t offset_us; - int rc; + sch->end_time = sch->start_time + + ble_ll_tmr_u2t_up(sch->remainder + 2 * aux_ww_us + + aux_tx_win_us + pdu_rx_us); - rc = ble_ll_scan_aux_parse_aux_ptr(aux, aux_ptr, &offset_us); - if (rc < 0) { - return -1; - } + sch->start_time -= g_ble_ll_sched_offset_ticks; - rc = ble_ll_sched_scan_aux(&aux->sch, pdu_time, pdu_time_rem, offset_us); - if (rc < 0) { - return -1; - } - - return 0; + return ble_ll_sched_scan_aux(&aux->sch); } int @@ -1243,7 +1255,10 @@ ble_ll_scan_aux_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok) rxinfo = &rxhdr->rxinfo; rxinfo->user_data = aux; - if (!crcok) { + /* It's possible that we received aux while scan was just being disabled in + * LL task. In such case simply ignore aux. + */ + if (!crcok || !ble_ll_scan_enabled()) { rxinfo->flags |= BLE_MBUF_HDR_F_IGNORED; goto done; } @@ -1491,6 +1506,7 @@ ble_ll_scan_aux_check_connect_rsp(uint8_t *rxbuf, #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) struct ble_ll_resolv_entry *rl = NULL; #endif + uint8_t match_adva = 1; pdu_hdr = rxbuf[0]; pdu_len = rxbuf[1]; @@ -1523,34 +1539,34 @@ ble_ll_scan_aux_check_connect_rsp(uint8_t *rxbuf, targeta_type = !!(pdu_hdr & BLE_ADV_PDU_HDR_RXADD_RAND); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) - /* If we have IRK for peer and AdvA is an RPA, we need to check if current - * RPA resolves using that IRK. This is to verify AdvA in case RPS changed - * due to timeout or AdvA in advertising was an identity address but is an - * RPA in AUX_CONNECT_RSP. - * Otherwise, it shall be the same as in AUX_CONNECT_REQ. + /* If AdvA is an RPA and we have peer IRK, we need to check if it resolves + * using that RPA because peer can change RPA between advertising PDU and + * AUX_CONNECT_RSP. In other case, we expect AdvA to be the same as in + * advertising PDU. */ if ((addrd->rpa_index >= 0) && ble_ll_is_rpa(adva, adva_type)) { rl = &g_ble_ll_resolv_list[addrd->rpa_index]; - if (!ble_ll_resolv_rpa(adva, rl->rl_peer_irk)) { - return -1; - } + if (rl->rl_has_peer) { + if (!ble_ll_resolv_rpa(adva, rl->rl_peer_irk)) { + return -1; + } - addrd->adva_resolved = 1; - addrd->adva = adva; - addrd->adva_type = adva_type; - } else if ((adva_type != - !!(pdu_data->hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK)) || - (memcmp(adva, pdu_data->adva, 6) != 0)) { - return -1; - } -#else - if ((adva_type != !!(pdu_data->hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK)) || - (memcmp(adva, pdu_data->adva, 6) != 0)) { - return -1; + addrd->adva_resolved = 1; + addrd->adva = adva; + addrd->adva_type = adva_type; + + match_adva = 0; + } } #endif /* BLE_LL_CFG_FEAT_LL_PRIVACY */ + if (match_adva && + ((adva_type != !!(pdu_data->hdr_byte & BLE_ADV_PDU_HDR_RXADD_MASK)) || + (memcmp(adva, pdu_data->adva, 6) != 0))) { + return -1; + } + if ((targeta_type != !!(pdu_data->hdr_byte & BLE_ADV_PDU_HDR_TXADD_MASK)) || (memcmp(targeta, pdu_data->inita, 6) != 0)) { return -1; @@ -1571,6 +1587,9 @@ ble_ll_scan_aux_rx_pkt_in_for_initiator(struct os_mbuf *rxpdu, aux = rxinfo->user_data; if (rxinfo->flags & BLE_MBUF_HDR_F_IGNORED) { + if (aux->flags & BLE_LL_SCAN_AUX_F_W4_CONNECT_RSP) { + ble_ll_conn_send_connect_req_cancel(); + } ble_ll_scan_aux_free(aux); ble_ll_scan_chk_resume(); return; @@ -1643,7 +1662,15 @@ ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr) aux->hci_state |= BLE_LL_SCAN_AUX_H_DONE; } - ble_ll_scan_aux_update_scan_backoff(aux); + /* Update backoff if we were waiting for scan response */ + if (aux->flags & BLE_LL_SCAN_AUX_F_W4_SCAN_RSP) { + ble_ll_scan_backoff_update(0); + } + } else if (rxinfo->flags & BLE_MBUF_HDR_F_SCAN_RSP_RXD) { + /* We assume scan success when AUX_SCAN_RSP is received, no need to + * wait for complete chain (Core 5.3, Vol 6, Part B, 4.4.3.1). + */ + ble_ll_scan_backoff_update(1); } if (aux->hci_state & BLE_LL_SCAN_AUX_H_DONE) { @@ -1658,6 +1685,7 @@ ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr) aux->aux_ptr); if (rc < 0) { rxinfo->flags &= ~BLE_MBUF_HDR_F_AUX_PTR_WAIT; + rxinfo->flags |= BLE_MBUF_HDR_F_AUX_PTR_FAILED; } } @@ -1712,15 +1740,16 @@ ble_ll_scan_aux_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *rxhdr) aux->hci_state |= BLE_LL_SCAN_AUX_H_DONE; } - /* - * If we are done processing this chain and aux scan was not scheduled or - * we removed it from scheduler, we can remove aux_data now. Otherwise we - * will remove on next pkt_in. + /* If we are done processing this chain we can remove aux_data now if: + * - we did not send AUX_SCAN_REQ for this PDU + * - there was no aux scan scheduled from this PDU + * - there was aux scan scheduled from this PDU but we removed it + * In other cases, we'll remove aux_data on next pkt_in. */ if ((aux->hci_state & BLE_LL_SCAN_AUX_H_DONE) && + !(rxinfo->flags & BLE_MBUF_HDR_F_SCAN_REQ_TXD) && (!(rxinfo->flags & BLE_MBUF_HDR_F_AUX_PTR_WAIT) || (ble_ll_sched_rmv_elem(&aux->sch) == 0))) { - ble_ll_scan_aux_update_scan_backoff(aux); ble_ll_scan_aux_free(aux); } @@ -1767,5 +1796,3 @@ ble_ll_scan_aux_init(void) } #endif /* BLE_LL_CFG_FEAT_LL_EXT_ADV */ - -#endif /* !ESP_PLATFORM */ \ No newline at end of file diff --git a/src/nimble/nimble/controller/src/ble_ll_sched.c b/src/nimble/nimble/controller/src/ble_ll_sched.c index 692d58b8..ac795aa0 100644 --- a/src/nimble/nimble/controller/src/ble_ll_sched.c +++ b/src/nimble/nimble/controller/src/ble_ll_sched.c @@ -22,22 +22,22 @@ #include #include #include -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) #include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" -#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) -#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" +#include "nimble/nimble/controller/include/controller/ble_phy.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_pdu.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_adv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan_aux.h" +#include "nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h" +#include "nimble/nimble/controller/include/controller/ble_ll_trace.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sync.h" +#include "nimble/nimble/controller/include/controller/ble_ll_iso_big.h" +#if MYNEWT_VAL(BLE_LL_EXT) +#include "nimble/nimble/controller/include/controller/ble_ll_ext.h" #endif - -#include "../include/controller/ble_phy.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_scan_aux.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_ll_trace.h" -#include "../include/controller/ble_ll_tmr.h" -#include "../include/controller/ble_ll_sync.h" #include "ble_ll_priv.h" #include "ble_ll_conn_priv.h" @@ -54,6 +54,7 @@ int32_t g_ble_ll_sched_max_early; #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) struct ble_ll_sched_css { + uint8_t enabled; #if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED) uint32_t slot_us; uint32_t period_slots; @@ -72,9 +73,6 @@ static struct ble_ll_sched_css g_ble_ll_sched_css = { }; #endif -typedef int (* ble_ll_sched_preempt_cb_t)(struct ble_ll_sched_item *sch, - struct ble_ll_sched_item *item); - /* XXX: TODO: * 1) Add some accounting to the schedule code to see how late we are * (min/max?) @@ -151,7 +149,7 @@ ble_ll_sched_preempt(struct ble_ll_sched_item *sch, #if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) || MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) case BLE_LL_SCHED_TYPE_CONN: connsm = (struct ble_ll_conn_sm *)entry->cb_arg; - ble_ll_event_send(&connsm->conn_ev_end); + ble_ll_event_add(&connsm->conn_ev_end); break; #endif #if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) @@ -175,6 +173,17 @@ ble_ll_sched_preempt(struct ble_ll_sched_item *sch, break; #endif #endif +#endif +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + case BLE_LL_SCHED_TYPE_BIG: + /* FIXME sometimes it may be useful to preempt... */ + BLE_LL_ASSERT(0); + break; +#endif +#if MYNEWT_VAL(BLE_LL_EXT) + case BLE_LL_SCHED_TYPE_EXTERNAL: + ble_ll_ext_sched_removed(entry); + break; #endif default: BLE_LL_ASSERT(0); @@ -197,7 +206,7 @@ ble_ll_sched_q_head_changed(void) ble_ll_tmr_stop(&g_ble_ll_sched_timer); } -static inline void +void ble_ll_sched_restart(void) { struct ble_ll_sched_item *first; @@ -217,7 +226,7 @@ ble_ll_sched_restart(void) } } -static int +int ble_ll_sched_insert(struct ble_ll_sched_item *sch, uint32_t max_delay, ble_ll_sched_preempt_cb_t preempt_cb) { @@ -415,16 +424,15 @@ ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm, { #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) struct ble_ll_sched_css *css = &g_ble_ll_sched_css; - struct ble_ll_conn_sm *connsm_ref; + uint8_t rem_us; #endif struct ble_ll_sched_item *sch; uint32_t orig_start_time; - uint32_t earliest_start; -#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + uint32_t earliest_start = 0; uint32_t min_win_offset; -#endif uint32_t max_delay; uint32_t adv_rxend; + bool calc_sch = true; os_sr_t sr; int rc; @@ -507,61 +515,77 @@ ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm, orig_start_time = earliest_start - g_ble_ll_sched_offset_ticks; #if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) - uint8_t rem_us; - - OS_ENTER_CRITICAL(sr); - - connsm_ref = g_ble_ll_conn_css_ref; - if (!connsm_ref) { - g_ble_ll_conn_css_ref = connsm; + if (ble_ll_sched_css_is_enabled()) { + OS_ENTER_CRITICAL(sr); - css->period_anchor_slot_idx = connsm->css_slot_idx; - css->period_anchor_idx = 0; - css->period_anchor_ticks = adv_rxend; - css->period_anchor_rem_us = 0; + if (!g_ble_ll_conn_css_ref) { + css->period_anchor_ticks = earliest_start; + css->period_anchor_rem_us = 0; + css->period_anchor_idx = 0; + css->period_anchor_slot_idx = connsm->css_slot_idx; - connsm->css_period_idx = 1; - } else { - connsm->css_period_idx = css->period_anchor_idx + 1; - } + connsm->css_period_idx = 0; + max_delay = connsm->conn_itvl_ticks; + } else { + /* Reference connection may be already at next period if it has + * slot index lower than our, so we first try schedule one period + * earlier since our slot index in that period may not yet have + * passed. This avoids scheduling 1st connection event too far in + * the future, i.e. more than conn interval. + */ + if (connsm->css_slot_idx > css->period_anchor_slot_idx) { + connsm->css_period_idx = css->period_anchor_idx - 1; + } else { + connsm->css_period_idx = css->period_anchor_idx; + } + max_delay = 0; + } - ble_ll_sched_css_set_conn_anchor(connsm); + /* Calculate anchor point and move to next period if scheduled too + * early. + */ + connsm->css_period_idx--; + do { + connsm->css_period_idx++; + ble_ll_sched_css_set_conn_anchor(connsm); + sch->start_time = + connsm->anchor_point - g_ble_ll_sched_offset_ticks; + } while (LL_TMR_LT(sch->start_time, orig_start_time)); + + sch->end_time = connsm->anchor_point; + sch->remainder = connsm->anchor_point_usecs; - sch->start_time = connsm->anchor_point - g_ble_ll_sched_offset_ticks; - sch->remainder = connsm->anchor_point_usecs; + OS_EXIT_CRITICAL(sr); - OS_EXIT_CRITICAL(sr); + rem_us = sch->remainder; + ble_ll_tmr_add(&sch->end_time, &rem_us, ble_ll_sched_css_get_slot_us()); + if (rem_us == 0) { + sch->end_time--; + } - sch->end_time = sch->start_time; - rem_us = sch->remainder; - ble_ll_tmr_add(&sch->end_time, &rem_us, ble_ll_sched_css_get_period_slots()); - if (rem_us == 0) { - sch->end_time--; + calc_sch = false; } +#endif - max_delay = 0; - -#else - - sch->start_time = earliest_start - g_ble_ll_sched_offset_ticks; - sch->end_time = earliest_start + - ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * - BLE_LL_SCHED_USECS_PER_SLOT); - - min_win_offset = ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) * - BLE_LL_SCHED_USECS_PER_SLOT); - sch->start_time += min_win_offset; - sch->end_time += min_win_offset; - sch->remainder = 0; - - max_delay = connsm->conn_itvl_ticks - min_win_offset; + if (calc_sch) { + sch->start_time = earliest_start - g_ble_ll_sched_offset_ticks; + sch->end_time = earliest_start + + ble_ll_tmr_u2t(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * + BLE_LL_SCHED_USECS_PER_SLOT); + + min_win_offset = ble_ll_tmr_u2t( + MYNEWT_VAL(BLE_LL_CONN_INIT_MIN_WIN_OFFSET) * + BLE_LL_SCHED_USECS_PER_SLOT); + sch->start_time += min_win_offset; + sch->end_time += min_win_offset; + sch->remainder = 0; -#endif + max_delay = connsm->conn_itvl_ticks - min_win_offset; + } OS_ENTER_CRITICAL(sr); rc = ble_ll_sched_insert(sch, max_delay, preempt_none); - if (rc == 0) { connsm->tx_win_off = ble_ll_tmr_t2u(sch->start_time - orig_start_time) / BLE_LL_CONN_TX_OFF_USECS; @@ -569,7 +593,6 @@ ble_ll_sched_conn_central_new(struct ble_ll_conn_sm *connsm, connsm->anchor_point = sch->start_time + g_ble_ll_sched_offset_ticks; connsm->anchor_point_usecs = sch->remainder; connsm->ce_end_time = sch->end_time; - } OS_EXIT_CRITICAL(sr); @@ -650,38 +673,13 @@ ble_ll_sched_sync_overlaps_current(struct ble_ll_sched_item *sch) } int -ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, - uint32_t anchor_point, uint8_t anchor_point_usecs, - uint32_t window_widening, - int8_t phy_mode) +ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, uint32_t ww_us) { - uint8_t start_time_rem_usecs; - uint32_t start_time; - uint32_t end_time; - uint32_t dur; - int rc = 0; os_sr_t sr; + int rc = 0; - start_time = anchor_point; - start_time_rem_usecs = anchor_point_usecs; - - ble_ll_tmr_sub(&start_time, &start_time_rem_usecs, window_widening); - - dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_SYNC_PDU_LEN), - phy_mode); - end_time = start_time + ble_ll_tmr_u2t(dur); - - start_time -= g_ble_ll_sched_offset_ticks; - - /* Set schedule start and end times */ - sch->start_time = start_time; - sch->remainder = start_time_rem_usecs; - sch->end_time = end_time; - - /* Better be past current time or we just leave */ - if (LL_TMR_LEQ(sch->start_time, ble_ll_tmr_get())) { - return -1; - } + /* Adjust start time to include window widening */ + ble_ll_tmr_sub(&sch->start_time, &sch->remainder, ww_us); OS_ENTER_CRITICAL(sr); @@ -700,32 +698,11 @@ ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch, } int -ble_ll_sched_sync(struct ble_ll_sched_item *sch, - uint32_t beg_cputime, uint32_t rem_usecs, - uint32_t offset, int8_t phy_mode) +ble_ll_sched_sync(struct ble_ll_sched_item *sch) { - uint8_t start_time_rem_usecs; - uint32_t start_time; - uint32_t end_time; - uint32_t dur; os_sr_t sr; int rc = 0; - start_time = beg_cputime; - start_time_rem_usecs = rem_usecs; - - ble_ll_tmr_add(&start_time, &start_time_rem_usecs, offset); - - dur = ble_ll_pdu_tx_time_get(MYNEWT_VAL(BLE_LL_SCHED_SCAN_SYNC_PDU_LEN), - phy_mode); - end_time = start_time + ble_ll_tmr_u2t(dur); - - start_time -= g_ble_ll_sched_offset_ticks; - - sch->start_time = start_time; - sch->remainder = start_time_rem_usecs; - sch->end_time = end_time; - OS_ENTER_CRITICAL(sr); rc = ble_ll_sched_insert(sch, 0, preempt_none); @@ -734,8 +711,6 @@ ble_ll_sched_sync(struct ble_ll_sched_item *sch, ble_ll_sched_restart(); - STATS_INC(ble_ll_stats, sync_scheduled); - return rc; } #endif @@ -869,6 +844,30 @@ ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch) return rc; } +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) +int +ble_ll_sched_iso_big(struct ble_ll_sched_item *sch, int first) +{ + os_sr_t sr; + int rc; + + OS_ENTER_CRITICAL(sr); + + if (first) { + rc = ble_ll_sched_insert(sch, BLE_LL_SCHED_MAX_DELAY_ANY, preempt_none); + } else { + /* XXX provide better strategy for preemption */ + rc = ble_ll_sched_insert(sch, 0, preempt_any); + } + + OS_EXIT_CRITICAL(sr); + + ble_ll_sched_restart(); + + return rc; +} +#endif /* BLE_LL_ISO_BROADCASTER */ + /** * Remove a schedule element * @@ -1008,6 +1007,16 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch) STATS_INC(ble_ll_stats, sched_state_conn_errs); ble_ll_conn_event_halt(); break; +#endif +#if MYNEWT_VAL(BLE_LL_ISO_BROADCASTER) + case BLE_LL_STATE_BIG: + ble_ll_iso_big_halt(); + break; +#endif +#if MYNEWT_VAL(BLE_LL_EXT) + case BLE_LL_STATE_EXTERNAL: + ble_ll_ext_halt(); + break; #endif default: BLE_LL_ASSERT(0); @@ -1100,21 +1109,11 @@ ble_ll_sched_next_time(uint32_t *next_event_time) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) int -ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch, uint32_t pdu_time, - uint8_t pdu_time_rem, uint32_t offset_us) +ble_ll_sched_scan_aux(struct ble_ll_sched_item *sch) { - uint32_t offset_ticks; os_sr_t sr; int rc; - offset_us += pdu_time_rem; - offset_ticks = ble_ll_tmr_u2t(offset_us); - - sch->start_time = pdu_time + offset_ticks - g_ble_ll_sched_offset_ticks; - sch->remainder = offset_us - ble_ll_tmr_t2u(offset_ticks); - /* TODO: make some sane slot reservation */ - sch->end_time = sch->start_time + ble_ll_tmr_u2t(5000); - OS_ENTER_CRITICAL(sr); rc = ble_ll_sched_insert(sch, 0, preempt_none); @@ -1182,9 +1181,6 @@ ble_ll_sched_init(void) * This is the offset from the start of the scheduled item until the actual * tx/rx should occur, in ticks. We also "round up" to the nearest tick. */ -#ifndef XCVR_TX_SCHED_DELAY_USECS -#define XCVR_TX_SCHED_DELAY_USECS 160 -#endif g_ble_ll_sched_offset_ticks = ble_ll_tmr_u2t_up(XCVR_TX_SCHED_DELAY_USECS); /* Initialize cputimer for the scheduler */ @@ -1192,6 +1188,17 @@ ble_ll_sched_init(void) g_ble_ll_sched_q_head_changed = 0; +#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED) + memset(&g_ble_ll_sched_css, 0, sizeof (g_ble_ll_sched_css)); +#if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED) + g_ble_ll_sched_css.slot_us = MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_SLOT_US); + g_ble_ll_sched_css.period_slots = MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_PERIOD_SLOTS); +#endif +#if !MYNEWT_VAL(BLE_LL_HCI_VS_CONN_STRICT_SCHED) + g_ble_ll_sched_css.enabled = 1; +#endif +#endif + return 0; } @@ -1205,6 +1212,24 @@ ble_ll_sched_css_set_params(uint32_t slot_us, uint32_t period_slots) } #endif +void +ble_ll_sched_css_set_enabled(uint8_t enabled) +{ + g_ble_ll_sched_css.enabled = enabled; +} + +void +ble_ll_sched_css_update_anchor(struct ble_ll_conn_sm *connsm) +{ + struct ble_ll_sched_css *css = &g_ble_ll_sched_css; + + if (!g_ble_ll_conn_css_ref) { + g_ble_ll_conn_css_ref = connsm; + css->period_anchor_ticks = connsm->anchor_point; + css->period_anchor_rem_us = connsm->anchor_point_usecs; + } +} + void ble_ll_sched_css_set_conn_anchor(struct ble_ll_conn_sm *connsm) { @@ -1232,6 +1257,12 @@ ble_ll_sched_css_set_conn_anchor(struct ble_ll_conn_sm *connsm) } #if !MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED_FIXED) +inline bool +ble_ll_sched_css_is_enabled(void) +{ + return g_ble_ll_sched_css.enabled; +} + inline uint32_t ble_ll_sched_css_get_slot_us(void) { diff --git a/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c b/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c deleted file mode 100644 index f2aeb14c..00000000 --- a/src/nimble/nimble/controller/src/ble_ll_supp_cmd.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#ifndef ESP_PLATFORM - -#include -#include - -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" - -/* Octet 0 */ -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_DISCONNECT (1 << 5) -#else -#define BLE_SUPP_CMD_DISCONNECT (0 << 5) -#endif -#define BLE_LL_SUPP_CMD_OCTET_0 (BLE_SUPP_CMD_DISCONNECT) - -/* Octet 2*/ -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_READ_REM_VER_INFO (1 << 7) -#else -#define BLE_SUPP_CMD_READ_REM_VER_INFO (0 << 7) -#endif -#define BLE_LL_SUPP_CMD_OCTET_2 (BLE_SUPP_CMD_READ_REM_VER_INFO) - -/* Octet 5 */ -#define BLE_SUPP_CMD_SET_EVENT_MASK (1 << 6) -#define BLE_SUPP_CMD_RESET (1 << 7) -#define BLE_LL_SUPP_CMD_OCTET_5 \ -( \ - BLE_SUPP_CMD_SET_EVENT_MASK | \ - BLE_SUPP_CMD_RESET \ -) - -/* Octet 10 */ -#define BLE_SUPP_CMD_RD_TX_PWR (0 << 2) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) -#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (1 << 5) -#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (1 << 6) -#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (1 << 7) -#else -#define BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW (0 << 5) -#define BLE_SUPP_CMD_HOST_BUFFER_SIZE (0 << 6) -#define BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS (0 << 7) -#endif -#define BLE_LL_SUPP_CMD_OCTET_10 \ -( \ - BLE_SUPP_CMD_RD_TX_PWR | \ - BLE_SUPP_CMD_SET_CTRL_TO_HOST_FLOW | \ - BLE_SUPP_CMD_HOST_BUFFER_SIZE | \ - BLE_SUPP_CMD_HOST_NUM_COMP_PACKETS \ -) - -/* Octet 14 */ -#define BLE_SUPP_CMD_RD_LOC_VER (1 << 3) -#define BLE_SUPP_CMD_RD_LOC_SUPP_FEAT (1 << 5) -#define BLE_LL_SUPP_CMD_OCTET_14 \ -( \ - BLE_SUPP_CMD_RD_LOC_VER | \ - BLE_SUPP_CMD_RD_LOC_SUPP_FEAT \ -) - -/* Octet 15 */ -#define BLE_SUPP_CMD_RD_BD_ADDR (1 << 1) - -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_RD_RSSI (1 << 5) -#else -#define BLE_SUPP_CMD_RD_RSSI (0 << 5) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_15 \ -( \ - BLE_SUPP_CMD_RD_BD_ADDR | \ - BLE_SUPP_CMD_RD_RSSI \ -) - -/* Octet 25 */ -#define BLE_SUPP_CMD_LE_SET_EV_MASK (1 << 0) -#define BLE_SUPP_CMD_LE_RD_BUF_SIZE (1 << 1) -#define BLE_SUPP_CMD_LE_RD_LOC_FEAT (1 << 2) -#define BLE_SUPP_CMD_LE_SET_RAND_ADDR (1 << 4) -#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#define BLE_SUPP_CMD_LE_SET_ADV_PARAMS (1 << 5) -#define BLE_SUPP_CMD_LE_SET_ADV_TX_PWR (1 << 6) -#define BLE_SUPP_CMD_LE_SET_ADV_DATA (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_ADV_PARAMS (0 << 5) -#define BLE_SUPP_CMD_LE_SET_ADV_TX_PWR (0 << 6) -#define BLE_SUPP_CMD_LE_SET_ADV_DATA (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_25 \ -( \ - BLE_SUPP_CMD_LE_SET_EV_MASK | \ - BLE_SUPP_CMD_LE_RD_BUF_SIZE | \ - BLE_SUPP_CMD_LE_RD_LOC_FEAT | \ - BLE_SUPP_CMD_LE_SET_RAND_ADDR | \ - BLE_SUPP_CMD_LE_SET_ADV_PARAMS | \ - BLE_SUPP_CMD_LE_SET_ADV_TX_PWR | \ - BLE_SUPP_CMD_LE_SET_ADV_DATA \ -) - -/* Octet 26 */ -#if MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#define BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA (1 << 0) -#define BLE_SUPP_CMD_LE_SET_ADV_ENABLE (1 << 1) -#else -#define BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA (0 << 0) -#define BLE_SUPP_CMD_LE_SET_ADV_ENABLE (0 << 1) -#endif -#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) -#define BLE_SUPP_CMD_LE_SET_SCAN_PARAMS (1 << 2) -#define BLE_SUPP_CMD_LE_SET_SCAN_ENABLE (1 << 3) -#else -#define BLE_SUPP_CMD_LE_SET_SCAN_PARAMS (0 << 2) -#define BLE_SUPP_CMD_LE_SET_SCAN_ENABLE (0 << 3) -#endif -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_CREATE_CONN (1 << 4) -#define BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL (1 << 5) -#else -#define BLE_SUPP_CMD_LE_CREATE_CONN (0 << 4) -#define BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL (0 << 5) - -#endif -#define BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE (1 << 6) -#define BLE_SUPP_CMD_LE_CLR_WHITELIST (1 << 7) - -#define BLE_LL_SUPP_CMD_OCTET_26 \ -( \ - BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA | \ - BLE_SUPP_CMD_LE_SET_ADV_ENABLE | \ - BLE_SUPP_CMD_LE_SET_SCAN_PARAMS | \ - BLE_SUPP_CMD_LE_SET_SCAN_ENABLE | \ - BLE_SUPP_CMD_LE_CREATE_CONN | \ - BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL | \ - BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE | \ - BLE_SUPP_CMD_LE_CLR_WHITELIST \ -) - -/* Octet 27 */ -#define BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST (1 << 0) -#define BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST (1 << 1) -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_CONN_UPDATE (1 << 2) -#else -#define BLE_SUPP_CMD_LE_CONN_UPDATE (0 << 2) -#endif -#define BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS (1 << 3) -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_RD_CHAN_MAP (1 << 4) -#define BLE_SUPP_CMD_LE_RD_REM_USED_FEAT (1 << 5) -#else -#define BLE_SUPP_CMD_LE_RD_CHAN_MAP (0 << 4) -#define BLE_SUPP_CMD_LE_RD_REM_USED_FEAT (0 << 5) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -#define BLE_SUPP_CMD_LE_ENCRYPT (1 << 6) -#else -#define BLE_SUPP_CMD_LE_ENCRYPT (0 << 6) -#endif -#define BLE_SUPP_CMD_LE_RAND (1 << 7) - -#define BLE_LL_SUPP_CMD_OCTET_27 \ -( \ - BLE_SUPP_CMD_LE_ENCRYPT | \ - BLE_SUPP_CMD_LE_RAND | \ - BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST | \ - BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST | \ - BLE_SUPP_CMD_LE_CONN_UPDATE | \ - BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS | \ - BLE_SUPP_CMD_LE_RD_CHAN_MAP | \ - BLE_SUPP_CMD_LE_RD_REM_USED_FEAT \ -) - -/* Octet 28 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_START_ENCRYPT (1 << 0) -#else -#define BLE_SUPP_CMD_LE_START_ENCRYPT (0 << 0) -#endif -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) -#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (1 << 1) -#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (1 << 2) -#else -#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (0 << 1) -#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (0 << 2) -#endif -#else -#define BLE_SUPP_CMD_LE_START_ENCRYPT (0 << 0) -#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (0 << 1) -#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (0 << 2) -#endif -#define BLE_SUPP_CMD_LE_READ_SUPP_STATES (1 << 3) - -#if MYNEWT_VAL(BLE_LL_DTM) -#define BLE_SUPP_CMD_LE_RX_TEST (1 << 4) -#define BLE_SUPP_CMD_LE_TX_TEST (1 << 5) -#define BLE_SUPP_CMD_LE_TEST_END (1 << 6) - -#else -#define BLE_SUPP_CMD_LE_RX_TEST (0 << 4) -#define BLE_SUPP_CMD_LE_TX_TEST (0 << 5) -#define BLE_SUPP_CMD_LE_TEST_END (0 << 6) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_28 \ -( \ - BLE_SUPP_CMD_LE_START_ENCRYPT | \ - BLE_SUPP_CMD_LE_LTK_REQ_REPLY | \ - BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY | \ - BLE_SUPP_CMD_LE_READ_SUPP_STATES | \ - BLE_SUPP_CMD_LE_RX_TEST | \ - BLE_SUPP_CMD_LE_TX_TEST | \ - BLE_SUPP_CMD_LE_TEST_END \ -) - -/* Octet 33 */ -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_REM_CONN_PRR (1 << 4) -#define BLE_SUPP_CMD_LE_REM_CONN_PRNR (1 << 5) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) -#define BLE_SUPP_CMD_LE_SET_DATALEN (1 << 6) -#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_DATALEN (0 << 6) -#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (0 << 7) -#endif -#else -#define BLE_SUPP_CMD_LE_REM_CONN_PRR (0 << 4) -#define BLE_SUPP_CMD_LE_REM_CONN_PRNR (0 << 5) -#define BLE_SUPP_CMD_LE_SET_DATALEN (0 << 6) -#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (0 << 7) -#endif - - -#define BLE_LL_SUPP_CMD_OCTET_33 \ -( \ - BLE_SUPP_CMD_LE_REM_CONN_PRR | \ - BLE_SUPP_CMD_LE_REM_CONN_PRNR | \ - BLE_SUPP_CMD_LE_SET_DATALEN | \ - BLE_SUPP_CMD_LE_RD_SUGG_DATALEN \ -) - -/* Octet 34 */ -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) -#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (1 << 0) -#else -#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (0 << 0) -#endif -#else -#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (0 << 0) -#endif -#define BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK (0 << 1) -#define BLE_SUPP_CMD_LE_GENERATE_DH_KEY (0 << 2) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (1 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (1 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (1 << 5) -#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (1 << 6) -#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (1 << 7) -#else -#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (0 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (0 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (0 << 5) -#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (0 << 6) -#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_34 \ -( \ - BLE_SUPP_CMD_LE_WR_SUGG_DATALEN | \ - BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK | \ - BLE_SUPP_CMD_LE_GENERATE_DH_KEY | \ - BLE_SUPP_CMD_LE_ADD_RESOLV_LIST | \ - BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST | \ - BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST | \ - BLE_SUPP_CMD_LE_RD_RESOLV_SIZE | \ - BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR \ -) - -/* Octet 35 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (1 << 0) -#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (1 << 1) -#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (1 << 2) -#else -#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (0 << 0) -#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (0 << 1) -#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (0 << 2) -#endif -#define BLE_SUPP_CMD_LE_RD_MAX_DATALEN (1 << 3) -#if (BLE_LL_BT5_PHY_SUPPORTED == 1) -#if MYNEWT_VAL(BLE_LL_ROLE_PERIPHERAL) || MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_READ_PHY (1 << 4) -#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (1 << 5) -#define BLE_SUPP_CMD_LE_SET_PHY (1 << 6) -#else -#define BLE_SUPP_CMD_LE_READ_PHY (0 << 4) -#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (0 << 5) -#define BLE_SUPP_CMD_LE_SET_PHY (0 << 6) -#endif -#else -#define BLE_SUPP_CMD_LE_READ_PHY (0 << 4) -#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (0 << 5) -#define BLE_SUPP_CMD_LE_SET_PHY (0 << 6) -#endif - -#if MYNEWT_VAL(BLE_LL_DTM) -#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (1 << 7) -#else -#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_35 \ -( \ - BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR | \ - BLE_SUPP_CMD_LE_SET_ADDR_RES_EN | \ - BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO | \ - BLE_SUPP_CMD_LE_RD_MAX_DATALEN | \ - BLE_SUPP_CMD_LE_READ_PHY | \ - BLE_SUPP_CMD_LE_SET_DEFAULT_PHY | \ - BLE_SUPP_CMD_LE_SET_PHY | \ - BLE_SUPP_CMD_LE_ENHANCED_RX_TEST \ -) - -/* Octet 36 */ -#if MYNEWT_VAL(BLE_LL_DTM) -#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (1 << 0) -#else -#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (0 << 0) -#endif - -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (1 << 1) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (1 << 2) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (1 << 3) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (1 << 4) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (1 << 5) -#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (1 << 6) -#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (0 << 1) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (0 << 2) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (0 << 3) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (0 << 4) -#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (0 << 5) -#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (0 << 6) -#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_36 \ -( \ - BLE_SUPP_CMD_LE_ENHANCED_TX_TEST | \ - BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR | \ - BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM | \ - BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA | \ - BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP | \ - BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE | \ - BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN | \ - BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS \ -) - -/* Octet 37 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#define BLE_SUPP_CMD_LE_REMOVE_ADVS (1 << 0) -#define BLE_SUPP_CMD_LE_CLEAR_ADVS (1 << 1) -#else -#define BLE_SUPP_CMD_LE_REMOVE_ADVS (0 << 0) -#define BLE_SUPP_CMD_LE_CLEAR_ADVS (0 << 1) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_BROADCASTER) -#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (1 << 2) -#define BLE_SUPP_CMD_LE_SET_PADV_DATA (1 << 3) -#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (1 << 4) -#else -#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (0 << 2) -#define BLE_SUPP_CMD_LE_SET_PADV_DATA (0 << 3) -#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (0 << 4) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#if MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (1 << 5) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (1 << 6) -#else -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (0 << 5) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (0 << 6) -#endif -#if MYNEWT_VAL(BLE_LL_ROLE_CENTRAL) -#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (1 << 7) -#else -#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (0 << 7) -#endif -#else -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (0 << 5) -#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (0 << 6) -#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_37 \ -( \ - BLE_SUPP_CMD_LE_REMOVE_ADVS | \ - BLE_SUPP_CMD_LE_CLEAR_ADVS | \ - BLE_SUPP_CMD_LE_SET_PADV_PARAM | \ - BLE_SUPP_CMD_LE_SET_PADV_DATA | \ - BLE_SUPP_CMD_LE_SET_PADV_ENABLE | \ - BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM | \ - BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE | \ - BLE_SUPP_CMD_LE_EXT_CREATE_CONN \ -) - -/* Octet 38 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (1 << 0) -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (1 << 1) -#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (1 << 2) -#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (1 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (1 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (1 << 5) -#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (1 << 6) -#else -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (0 << 0) -#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (0 << 1) -#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (0 << 2) -#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (0 << 3) -#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (0 << 4) -#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (0 << 5) -#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (0 << 6) -#endif -#define BLE_SUPP_CMD_LE_RD_TX_POWER (1 << 7) - -#define BLE_LL_SUPP_CMD_OCTET_38 \ -( \ - BLE_SUPP_CMD_LE_PADV_CREATE_SYNC | \ - BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C | \ - BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC | \ - BLE_SUPP_CMD_LE_ADD_PADV_LIST | \ - BLE_SUPP_CMD_LE_REMOVE_PADV_LIST | \ - BLE_SUPP_CMD_LE_CLEAR_PADV_LIST | \ - BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE | \ - BLE_SUPP_CMD_LE_RD_TX_POWER \ -) - -/* Octet 39 */ -#define BLE_SUPP_CMD_LE_RD_RF_PATH_COMP (1 << 0) -#define BLE_SUPP_CMD_LE_WR_RF_PATH_COMP (1 << 1) -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) -#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (1 << 2) -#else -#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (0 << 2) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_39 \ -( \ - BLE_SUPP_CMD_LE_RD_RF_PATH_COMP | \ - BLE_SUPP_CMD_LE_WR_RF_PATH_COMP | \ - BLE_SUPP_CMD_LE_SET_PRIVACY_MODE \ -) - -/* Octet 40 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_VERSION) >= 51 && \ - MYNEWT_VAL(BLE_LL_ROLE_OBSERVER) -#define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (1 << 5) -#else -#define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (0 << 5) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER (1 << 6) -#define BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER (1 << 7) -#else -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER (0 << 6) -#define BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_40 \ -( \ - BLE_SUPP_CMD_LE_PADV_RECV_ENABLE | \ - BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER | \ - BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER \ -) - -/* Octet 41 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER) -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (1 << 0) -#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (1 << 1) -#else -#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (0 << 0) -#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (0 << 1) -#endif -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) -#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (1 << 5) -#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (1 << 6) -#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (1 << 7) -#else -#define BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 (0 << 5) -#define BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC (0 << 6) -#define BLE_SUPP_CMD_LE_SET_CIG_PARAM (0 << 7) -#endif - -#define BLE_LL_SUPP_CMD_OCTET_41 \ -( \ - BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \ - BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS | \ - BLE_SUPP_CMD_LE_READ_BUF_SIZE_V2 | \ - BLE_SUPP_CMD_LE_READ_ISO_TX_SYNC | \ - BLE_SUPP_CMD_LE_SET_CIG_PARAM \ -) - -/* Octet 42 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ISO) -#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (1 << 0) -#define BLE_SUPP_CMD_LE_CREATE_CIS (1 << 1) -#define BLE_SUPP_CMD_LE_REMOVE_CIG (1 << 2) -#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (1 << 3) -#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (1 << 4) -#define BLE_SUPP_CMD_LE_CREATE_BIG (1 << 5) -#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (1 << 6) -#define BLE_SUPP_CMD_LE_TERMINATE_BIG (1 << 7) -#else -#define BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST (0 << 0) -#define BLE_SUPP_CMD_LE_CREATE_CIS (0 << 1) -#define BLE_SUPP_CMD_LE_REMOVE_CIG (0 << 2) -#define BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ (0 << 3) -#define BLE_SUPP_CMD_LE_REJECT_CIS_REQ (0 << 4) -#define BLE_SUPP_CMD_LE_CREATE_BIG (0 << 5) -#define BLE_SUPP_CMD_LE_CREATE_BIG_TEST (0 << 6) -#define BLE_SUPP_CMD_LE_TERMINATE_BIG (0 << 7) -#endif -#define BLE_LL_SUPP_CMD_OCTET_42 \ -( \ - BLE_SUPP_CMD_LE_SET_CIG_PARAM_TEST | \ - BLE_SUPP_CMD_LE_CREATE_CIS | \ - BLE_SUPP_CMD_LE_REMOVE_CIG | \ - BLE_SUPP_CMD_LE_ACCEPT_CIS_REQ | \ - BLE_SUPP_CMD_LE_REJECT_CIS_REQ | \ - BLE_SUPP_CMD_LE_CREATE_BIG | \ - BLE_SUPP_CMD_LE_CREATE_BIG_TEST | \ - BLE_SUPP_CMD_LE_TERMINATE_BIG \ -) - -/* Octet 43 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_SCA_UPDATE) -#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (1 << 2) -#else -#define BLE_SUPP_CMD_LE_REQUEST_PEER_SCA (0 << 0) -#endif -#define BLE_LL_SUPP_CMD_OCTET_43 \ -( \ - BLE_SUPP_CMD_LE_REQUEST_PEER_SCA \ -) - -/* Octet 44 */ -#if MYNEWT_VAL(BLE_VERSION) >= 52 -#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (1 << 1) -#else -#define BLE_SUPP_CMD_LE_SET_HOST_FEATURE (0 << 1) -#endif -#define BLE_LL_SUPP_CMD_OCTET_44 \ -( \ - BLE_SUPP_CMD_LE_SET_HOST_FEATURE \ -) - -/* Octet 46 */ -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_ENHANCED_CONN_UPDATE) -#define BLE_SUPP_CMD_LE_SET_DEFAULT_SUBRATE (1 << 0) -#define BLE_SUPP_CMD_LE_SUBRATE_REQ (1 << 1) -#else -#define BLE_SUPP_CMD_LE_SET_DEFAULT_SUBRATE (0 << 0) -#define BLE_SUPP_CMD_LE_SUBRATE_REQ (0 << 1) -#endif -#define BLE_LL_SUPP_CMD_OCTET_46 \ -( \ - BLE_SUPP_CMD_LE_SET_DEFAULT_SUBRATE | \ - BLE_SUPP_CMD_LE_SUBRATE_REQ \ -) - -/* Defines the array of supported commands */ -const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] = -{ - BLE_LL_SUPP_CMD_OCTET_0, /* Octet 0 */ - 0, - BLE_LL_SUPP_CMD_OCTET_2, /* Octet 2 */ - 0, - 0, - BLE_LL_SUPP_CMD_OCTET_5, - 0, - 0, - 0, /* Octet 8 */ - 0, - BLE_LL_SUPP_CMD_OCTET_10, - 0, - 0, - 0, - BLE_LL_SUPP_CMD_OCTET_14, - BLE_LL_SUPP_CMD_OCTET_15, - 0, /* Octet 16 */ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, /* Octet 24 */ - BLE_LL_SUPP_CMD_OCTET_25, - BLE_LL_SUPP_CMD_OCTET_26, - BLE_LL_SUPP_CMD_OCTET_27, - BLE_LL_SUPP_CMD_OCTET_28, - 0, - 0, - 0, - 0, /* Octet 32 */ - BLE_LL_SUPP_CMD_OCTET_33, - BLE_LL_SUPP_CMD_OCTET_34, - BLE_LL_SUPP_CMD_OCTET_35, - BLE_LL_SUPP_CMD_OCTET_36, - BLE_LL_SUPP_CMD_OCTET_37, - BLE_LL_SUPP_CMD_OCTET_38, - BLE_LL_SUPP_CMD_OCTET_39, - BLE_LL_SUPP_CMD_OCTET_40, /* Octet 40 */ - BLE_LL_SUPP_CMD_OCTET_41, - BLE_LL_SUPP_CMD_OCTET_42, - BLE_LL_SUPP_CMD_OCTET_43, - BLE_LL_SUPP_CMD_OCTET_44, - 0, - BLE_LL_SUPP_CMD_OCTET_46, -}; - -#endif diff --git a/src/nimble/nimble/controller/src/ble_ll_sync.c b/src/nimble/nimble/controller/src/ble_ll_sync.c index 5732cb59..76f96ec6 100644 --- a/src/nimble/nimble/controller/src/ble_ll_sync.c +++ b/src/nimble/nimble/controller/src/ble_ll_sync.c @@ -25,16 +25,17 @@ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_sync.h" -#include "../include/controller/ble_ll_utils.h" -#include "../include/controller/ble_ll_sched.h" -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_ll_resolv.h" -#include "../include/controller/ble_ll_rfmgmt.h" -#include "../include/controller/ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_pdu.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sync.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" +#include "nimble/nimble/controller/include/controller/ble_ll_sched.h" +#include "nimble/nimble/controller/include/controller/ble_ll_whitelist.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_ll_resolv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_rfmgmt.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/hci_common.h" @@ -65,9 +66,11 @@ #define BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP 0x0200 #define BLE_LL_SYNC_SM_FLAG_CHAIN 0x0400 -#define BLE_LL_SYNC_CHMAP_LEN 5 #define BLE_LL_SYNC_ITVL_USECS 1250 +#define BLE_LL_SYNC_BIGINFO_LEN 33 +#define BLE_LL_SYNC_BIGINFO_LEN_ENC 57 + struct ble_ll_sync_sm { uint16_t flags; @@ -76,11 +79,11 @@ struct ble_ll_sync_sm { uint8_t adv_addr_type; uint8_t sca; - uint8_t chanmap[BLE_LL_SYNC_CHMAP_LEN]; - uint8_t num_used_chans; + uint8_t chan_map[BLE_LL_CHAN_MAP_LEN]; + uint8_t chan_map_used; - uint8_t chanmap_new[BLE_LL_SYNC_CHMAP_LEN]; - uint16_t chanmap_new_instant; + uint8_t chan_map_new[BLE_LL_CHAN_MAP_LEN]; + uint16_t chan_map_new_instant; uint8_t chan_index; uint8_t chan_chain; @@ -145,7 +148,7 @@ static int ble_ll_sync_event_start_cb(struct ble_ll_sched_item *sch); static int ble_ll_sync_on_list(const uint8_t *addr, uint8_t addr_type, uint8_t sid) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { if ((g_ble_ll_sync_adv_list[i].adv_sid == sid) && @@ -161,7 +164,7 @@ ble_ll_sync_on_list(const uint8_t *addr, uint8_t addr_type, uint8_t sid) static int ble_ll_sync_list_get_free(void) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { if (g_ble_ll_sync_adv_list[i].adv_sid == 0xff) { @@ -174,7 +177,7 @@ ble_ll_sync_list_get_free(void) static bool ble_ll_sync_list_empty(void) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { if (g_ble_ll_sync_adv_list[i].adv_sid != 0xff) { @@ -198,7 +201,7 @@ ble_ll_sync_sm_clear(struct ble_ll_sync_sm *sm) if (sm->flags & (BLE_LL_SYNC_SM_FLAG_ESTABLISHING | BLE_LL_SYNC_SM_FLAG_ESTABLISHED)) { ble_ll_sched_rmv_elem(&sm->sch); - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &sm->sync_ev_end); + ble_ll_event_remove(&sm->sync_ev_end); } if (sm->next_report) { @@ -213,8 +216,7 @@ ble_ll_sync_sm_clear(struct ble_ll_sync_sm *sm) } ble_ll_rfmgmt_release(); - - BLE_LL_ASSERT(sm->sync_ev_end.ev.ev_queued == 0); + BLE_LL_ASSERT(ble_npl_event_is_queued(&sm->sync_ev_end) == 0); BLE_LL_ASSERT(sm->sch.enqueued == 0); memset(sm, 0, sizeof(*sm)); @@ -482,7 +484,7 @@ ble_ll_sync_event_start_cb(struct ble_ll_sched_item *sch) rc = ble_phy_rx_set_start_time(start, sch->remainder); if (rc && rc != BLE_PHY_ERR_RX_LATE) { STATS_INC(ble_ll_stats, sync_event_failed); - ble_ll_event_send(&sm->sync_ev_end); + ble_ll_event_add(&sm->sync_ev_end); ble_ll_sync_current_sm_over(); rc = BLE_LL_SCHED_STATE_DONE; } else { @@ -535,7 +537,7 @@ ble_ll_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr) /* this also handles chains as those have same PDU type */ if (pdu_type != BLE_ADV_PDU_TYPE_AUX_SYNC_IND) { - ble_ll_event_send(&g_ble_ll_sync_sm_current->sync_ev_end); + ble_ll_event_add(&g_ble_ll_sync_sm_current->sync_ev_end); ble_ll_sync_current_sm_over(); STATS_INC(ble_ll_stats, sched_invalid_pdu); return -1; @@ -664,6 +666,70 @@ ble_ll_sync_send_truncated_per_adv_rpt(struct ble_ll_sync_sm *sm, uint8_t *evbuf ble_ll_hci_event_send(hci_ev); } +#if MYNEWT_VAL(BLE_LL_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) +static void +ble_ll_sync_parse_biginfo_to_ev(struct ble_hci_ev_le_subev_biginfo_adv_report *ev, + const uint8_t *biginfo, uint8_t biginfo_len) +{ + uint32_t fields_buf; + + fields_buf = get_le32(&biginfo[0]); + ev->iso_interval = (fields_buf >> 15) & 0x0FFF; + ev->bis_cnt = (fields_buf >> 27) & 0x1F; + + fields_buf = get_le32(&biginfo[4]); + ev->nse = fields_buf & 0x1F; + ev->bn = (fields_buf >> 5) & 0x07; + ev->pto = (fields_buf >> 28) & 0x0F; + + fields_buf = get_le32(&biginfo[8]); + ev->irc = (fields_buf >> 20) & 0x0F; + ev->max_pdu = (fields_buf >> 24) & 0xFF; + + fields_buf = get_le32(&biginfo[17]); + ev->sdu_interval[0] = fields_buf & 0xFF; + ev->sdu_interval[1] = (fields_buf >> 8) & 0xFF; + ev->sdu_interval[2] = (fields_buf >> 16) & 0x0F; + ev->max_sdu = (fields_buf >> 20) & 0x0FFF; + + ev->phy = (biginfo[27] >> 5) & 0x07; + + ev->framing = (biginfo[32] >> 7) & 0x01; + + if (biginfo_len == BLE_LL_SYNC_BIGINFO_LEN_ENC) { + ev->encryption = 1; + } else { + ev->encryption = 0; + } +} + +static void +ble_ll_sync_send_biginfo_adv_rpt(struct ble_ll_sync_sm *sm, const uint8_t *biginfo, uint8_t biginfo_len) +{ + struct ble_hci_ev_le_subev_biginfo_adv_report *ev; + struct ble_hci_ev *hci_ev; + + if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT)) { + return; + } + + hci_ev = ble_transport_alloc_evt(1); + if (!hci_ev) { + return; + } + + hci_ev->opcode = BLE_HCI_EVCODE_LE_META; + hci_ev->length = sizeof(*ev); + ev = (void *) hci_ev->data; + + ev->subev_code = BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT; + ev->sync_handle = htole16(ble_ll_sync_get_handle(sm)); + ble_ll_sync_parse_biginfo_to_ev(ev, biginfo, biginfo_len); + + ble_ll_hci_event_send(hci_ev); +} +#endif + static void ble_ll_sync_send_per_adv_rpt(struct ble_ll_sync_sm *sm, struct os_mbuf *rxpdu, int8_t rssi, int8_t tx_power, int datalen, @@ -706,7 +772,7 @@ ble_ll_sync_send_per_adv_rpt(struct ble_ll_sync_sm *sm, struct os_mbuf *rxpdu, ev->rssi = rssi; ev->cte_type = 0xff; - ev->data_len = min(max_data_len, datalen - offset); + ev->data_len = MIN(max_data_len, datalen - offset); /* adjust event length */ hci_ev->length += ev->data_len; @@ -787,7 +853,7 @@ ble_ll_sync_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr) ble_ll_rx_pdu_in(rxpdu); } else { STATS_INC(ble_ll_stats, sync_rx_buf_err); - ble_ll_event_send(&g_ble_ll_sync_sm_current->sync_ev_end); + ble_ll_event_add(&g_ble_ll_sync_sm_current->sync_ev_end); } /* PHY is disabled here */ @@ -810,7 +876,7 @@ ble_ll_sync_wfr_timer_exp(void) STATS_INC(ble_ll_stats, sync_missed_err); ble_ll_sync_current_sm_over(); - ble_ll_event_send(&sm->sync_ev_end); + ble_ll_event_add(&sm->sync_ev_end); } /** @@ -827,7 +893,7 @@ ble_ll_sync_halt(void) ble_ll_sync_current_sm_over(); if (sm) { - ble_ll_event_send(&sm->sync_ev_end); + ble_ll_event_add(&sm->sync_ev_end); } } @@ -882,6 +948,26 @@ ble_ll_sync_parse_aux_ptr(const uint8_t *buf, uint8_t *chan, uint32_t *offset, *phy = (aux_ptr_field >> 21) & 0x07; } +static void +ble_ll_sync_sched_set(struct ble_ll_sched_item *sch, uint32_t start_ticks, + uint8_t start_rem_us, uint32_t offset, uint8_t phy_mode) +{ + uint32_t duration_us; + uint32_t duration; + + if (offset > 0) { + ble_ll_tmr_add(&start_ticks, &start_rem_us, offset); + } + + duration_us = ble_ll_pdu_us(MYNEWT_VAL(BLE_LL_SCHED_SCAN_SYNC_PDU_LEN), + phy_mode); + duration = ble_ll_tmr_u2t(duration_us); + + sch->start_time = start_ticks - g_ble_ll_sched_offset_ticks; + sch->remainder = start_rem_us; + sch->end_time = start_ticks + duration; +} + static int ble_ll_sync_schedule_chain(struct ble_ll_sync_sm *sm, struct ble_mbuf_hdr *hdr, const uint8_t *aux) @@ -916,8 +1002,10 @@ ble_ll_sync_schedule_chain(struct ble_ll_sync_sm *sm, struct ble_mbuf_hdr *hdr, sm->flags |= BLE_LL_SYNC_SM_FLAG_CHAIN; - return ble_ll_sched_sync(&sm->sch, hdr->beg_cputime, hdr->rem_usecs, - offset, sm->phy_mode); + ble_ll_sync_sched_set(&sm->sch, hdr->beg_cputime, hdr->rem_usecs, offset, + sm->phy_mode); + + return ble_ll_sched_sync(&sm->sch); } static void @@ -966,7 +1054,8 @@ ble_ll_sync_check_failed(struct ble_ll_sync_sm *sm) static bool ble_ll_sync_check_acad(struct ble_ll_sync_sm *sm, - const uint8_t *acad, uint8_t acad_len) + const uint8_t *acad, uint8_t acad_len, + const uint8_t **biginfo, uint8_t *biginfo_len) { const struct ble_ll_acad_channel_map_update_ind *chmu; unsigned int ad_len; @@ -998,20 +1087,32 @@ ble_ll_sync_check_acad(struct ble_ll_sync_sm *sm, /* Channels Mask (37 bits) * TODO should we check this? */ - sm->chanmap_new[0] = chmu->map[0]; - sm->chanmap_new[1] = chmu->map[1]; - sm->chanmap_new[2] = chmu->map[2]; - sm->chanmap_new[3] = chmu->map[3]; - sm->chanmap_new[4] = chmu->map[4] & 0x1f; + sm->chan_map_new[0] = chmu->map[0]; + sm->chan_map_new[1] = chmu->map[1]; + sm->chan_map_new[2] = chmu->map[2]; + sm->chan_map_new[3] = chmu->map[3]; + sm->chan_map_new[4] = chmu->map[4] & 0x1f; /* drop if channel map is invalid */ - if (ble_ll_utils_calc_num_used_chans(sm->chanmap_new) == 0) { + if (ble_ll_utils_chan_map_used_get(sm->chan_map_new) == 0) { return false; } - sm->chanmap_new_instant = le16toh(chmu->instant); + sm->chan_map_new_instant = le16toh(chmu->instant); sm->flags |= BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP; break; + +#if MYNEWT_VAL(BLE_LL_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) + case BLE_LL_ACAD_BIGINFO: + if ((ad_len - 1 == BLE_LL_SYNC_BIGINFO_LEN) || (ad_len - 1 == BLE_LL_SYNC_BIGINFO_LEN_ENC)) { + *biginfo = &acad[2]; + *biginfo_len = ad_len - 1; + } else { + return false; + } + break; +#endif + default: break; } @@ -1037,6 +1138,8 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) uint8_t *aux = NULL; uint8_t *acad = NULL; uint8_t acad_len; + const uint8_t *biginfo = NULL; + uint8_t biginfo_len = 0; int datalen; bool reports_enabled; @@ -1102,7 +1205,7 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) } /* check ACAD, needs to be done before rxpdu is adjusted for ADV data */ - if (acad && !ble_ll_sync_check_acad(sm, acad, acad_len)) { + if (acad && !ble_ll_sync_check_acad(sm, acad, acad_len, &biginfo, &biginfo_len)) { /* we got bad packet (bad ACAD data), end event */ goto end_event; } @@ -1120,6 +1223,12 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) /* send reports from this PDU */ ble_ll_sync_send_per_adv_rpt(sm, rxpdu, hdr->rxinfo.rssi, tx_power, datalen, aux, aux_scheduled); + +#if MYNEWT_VAL(BLE_LL_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) + if (biginfo) { + ble_ll_sync_send_biginfo_adv_rpt(sm, biginfo, biginfo_len); + } +#endif } /* if chain was scheduled we don't end event yet */ @@ -1131,7 +1240,7 @@ ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr) } end_event: - ble_ll_event_send(&sm->sync_ev_end); + ble_ll_event_add(&sm->sync_ev_end); ble_ll_rfmgmt_release(); } @@ -1166,21 +1275,21 @@ ble_ll_sync_next_event(struct ble_ll_sync_sm *sm, uint32_t cur_ww_adjust) /* update channel map if needed */ if (sm->flags & BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP) { - if (((int16_t)(sm->event_cntr - sm->chanmap_new_instant)) >= 0) { + if (((int16_t)(sm->event_cntr - sm->chan_map_new_instant)) >= 0) { /* map was verified on reception */ - sm->chanmap[0] = sm->chanmap_new[0]; - sm->chanmap[1] = sm->chanmap_new[1]; - sm->chanmap[2] = sm->chanmap_new[2]; - sm->chanmap[3] = sm->chanmap_new[3]; - sm->chanmap[4] = sm->chanmap_new[4]; - sm->num_used_chans = ble_ll_utils_calc_num_used_chans(sm->chanmap); + sm->chan_map[0] = sm->chan_map_new[0]; + sm->chan_map[1] = sm->chan_map_new[1]; + sm->chan_map[2] = sm->chan_map_new[2]; + sm->chan_map[3] = sm->chan_map_new[3]; + sm->chan_map[4] = sm->chan_map_new[4]; + sm->chan_map_used = ble_ll_utils_chan_map_used_get(sm->chan_map); sm->flags &= ~BLE_LL_SYNC_SM_FLAG_NEW_CHANMAP; } } /* Calculate channel index of next event */ sm->chan_index = ble_ll_utils_dci_csa2(sm->event_cntr, sm->channel_id, - sm->num_used_chans, sm->chanmap); + sm->chan_map_used, sm->chan_map); cur_ww = ble_ll_utils_calc_window_widening(sm->anchor_point, sm->last_anchor_point, @@ -1235,7 +1344,7 @@ ble_ll_sync_event_end(struct ble_npl_event *ev) ble_ll_scan_chk_resume(); /* Remove any end events that might be enqueued */ - ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &sm->sync_ev_end); + ble_ll_event_remove(&sm->sync_ev_end); /* don't schedule next event if sync is not established nor establishing * at this point SM is no longer valid @@ -1273,9 +1382,10 @@ ble_ll_sync_event_end(struct ble_npl_event *ev) ble_ll_sync_sm_clear(sm); return; } - } while (ble_ll_sched_sync_reschedule(&sm->sch, sm->anchor_point, - sm->anchor_point_usecs, - sm->window_widening, sm->phy_mode)); + + ble_ll_sync_sched_set(&sm->sch, sm->anchor_point, + sm->anchor_point_usecs, 0, sm->phy_mode); + } while (ble_ll_sched_sync_reschedule(&sm->sch, sm->window_widening)); } void @@ -1374,12 +1484,12 @@ ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd, sm->itvl_ticks = ble_ll_tmr_u2t_r(usecs, &sm->itvl_usecs); /* Channels Mask (37 bits) */ - sm->chanmap[0] = syncinfo[4]; - sm->chanmap[1] = syncinfo[5]; - sm->chanmap[2] = syncinfo[6]; - sm->chanmap[3] = syncinfo[7]; - sm->chanmap[4] = syncinfo[8] & 0x1f; - sm->num_used_chans = ble_ll_utils_calc_num_used_chans(sm->chanmap); + sm->chan_map[0] = syncinfo[4]; + sm->chan_map[1] = syncinfo[5]; + sm->chan_map[2] = syncinfo[6]; + sm->chan_map[3] = syncinfo[7]; + sm->chan_map[4] = syncinfo[8] & 0x1f; + sm->chan_map_used = ble_ll_utils_chan_map_used_get(sm->chan_map); /* SCA (3 bits) */ sm->sca = syncinfo[8] >> 5; @@ -1411,10 +1521,12 @@ ble_ll_sync_info_event(struct ble_ll_scan_addr_data *addrd, /* Calculate channel index of first event */ sm->chan_index = ble_ll_utils_dci_csa2(sm->event_cntr, sm->channel_id, - sm->num_used_chans, sm->chanmap); + sm->chan_map_used, sm->chan_map); - if (ble_ll_sched_sync(&sm->sch, rxhdr->beg_cputime, rxhdr->rem_usecs, - offset, sm->phy_mode)) { + ble_ll_sync_sched_set(&sm->sch, rxhdr->beg_cputime, rxhdr->rem_usecs, + offset, sm->phy_mode); + + if (ble_ll_sched_sync(&sm->sch)) { return; } @@ -1561,13 +1673,13 @@ ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len) } static void -ble_ll_sync_cancel_complete_event(void) +ble_ll_sync_cancel_complete_event(void *user_data) { ble_ll_sync_est_event_failed(BLE_ERR_OPERATION_CANCELLED); } int -ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) +ble_ll_sync_cancel(void) { struct ble_ll_sync_sm *sm; os_sr_t sr; @@ -1598,7 +1710,7 @@ ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb) OS_EXIT_CRITICAL(sr); /* g_ble_ll_sync_create_comp_ev will be cleared by this callback */ - *post_cmd_cb = ble_ll_sync_cancel_complete_event; + ble_ll_hci_post_cmd_cb_set(ble_ll_sync_cancel_complete_event, NULL); return BLE_ERR_SUCCESS; } @@ -1718,7 +1830,7 @@ ble_ll_sync_list_remove(const uint8_t *cmdbuf, uint8_t len) int ble_ll_sync_list_clear(void) { - int i; + unsigned int i; if (g_ble_ll_sync_create_comp_ev) { return BLE_ERR_CMD_DISALLOWED; @@ -1946,12 +2058,12 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, sm->itvl_ticks = ble_ll_tmr_u2t_r(itvl_usecs, &sm->itvl_usecs); /* Channels Mask (37 bits) */ - sm->chanmap[0] = syncinfo[4]; - sm->chanmap[1] = syncinfo[5]; - sm->chanmap[2] = syncinfo[6]; - sm->chanmap[3] = syncinfo[7]; - sm->chanmap[4] = syncinfo[8] & 0x1f; - sm->num_used_chans = ble_ll_utils_calc_num_used_chans(sm->chanmap); + sm->chan_map[0] = syncinfo[4]; + sm->chan_map[1] = syncinfo[5]; + sm->chan_map[2] = syncinfo[6]; + sm->chan_map[3] = syncinfo[7]; + sm->chan_map[4] = syncinfo[8] & 0x1f; + sm->chan_map_used = ble_ll_utils_chan_map_used_get(sm->chan_map); /* SCA (3 bits) */ sm->sca = syncinfo[8] >> 5; @@ -1979,7 +2091,7 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, /* Calculate channel index of first event */ sm->chan_index = ble_ll_utils_dci_csa2(sm->event_cntr, sm->channel_id, - sm->num_used_chans, sm->chanmap); + sm->chan_map_used, sm->chan_map); /* get anchor for specified conn event */ conn_event_count = get_le16(sync_ind + 20); @@ -2008,8 +2120,10 @@ ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm, } } - if (ble_ll_sched_sync(&sm->sch, sm->anchor_point, sm->anchor_point_usecs, - offset, sm->phy_mode)) { + ble_ll_sync_sched_set(&sm->sch, sm->anchor_point, sm->anchor_point_usecs, + offset, sm->phy_mode); + + if (ble_ll_sched_sync(&sm->sch)) { /* release SM if this failed */ ble_ll_sync_transfer_received(sm, BLE_ERR_CONN_ESTABLISHMENT); memset(sm, 0, sizeof(*sm)); @@ -2076,11 +2190,11 @@ ble_ll_sync_put_syncinfo(struct ble_ll_sync_sm *syncsm, put_le16(&dptr[2], syncsm->itvl); /* Channels Mask (37 bits) */ - dptr[4] = syncsm->chanmap[0]; - dptr[5] = syncsm->chanmap[1]; - dptr[6] = syncsm->chanmap[2]; - dptr[7] = syncsm->chanmap[3]; - dptr[8] = syncsm->chanmap[4] & 0x1f; + dptr[4] = syncsm->chan_map[0]; + dptr[5] = syncsm->chan_map[1]; + dptr[6] = syncsm->chan_map[2]; + dptr[7] = syncsm->chan_map[3]; + dptr[8] = syncsm->chan_map[4] & 0x1f; /* SCA (3 bits) */ dptr[8] |= syncsm->sca << 5; @@ -2187,32 +2301,30 @@ ble_ll_sync_transfer(const uint8_t *cmdbuf, uint8_t len, if (!(sm->flags & BLE_LL_SYNC_SM_FLAG_ESTABLISHED)) { rc = BLE_ERR_UNK_ADV_INDENT; - OS_EXIT_CRITICAL(sr); - goto done; + goto exit_crit; } handle = le16toh(cmd->conn_handle); if (handle > 0xeff) { rc = BLE_ERR_INV_HCI_CMD_PARMS; - OS_EXIT_CRITICAL(sr); - goto done; + goto exit_crit; } connsm = ble_ll_conn_find_by_handle(handle); if (!connsm) { rc = BLE_ERR_UNK_CONN_ID; - OS_EXIT_CRITICAL(sr); - goto done; + goto exit_crit; } /* Allow initiate LL procedure only if remote supports it. */ if (!ble_ll_conn_rem_feature_check(connsm, BLE_LL_FEAT_SYNC_TRANS_RECV)) { rc = BLE_ERR_UNSUPP_REM_FEATURE; - goto done; + goto exit_crit; } rc = ble_ll_sync_send_sync_ind(sm, connsm, cmd->service_data); +exit_crit: OS_EXIT_CRITICAL(sr); done: rsp->conn_handle = cmd->conn_handle; @@ -2228,7 +2340,7 @@ ble_ll_sync_transfer(const uint8_t *cmdbuf, uint8_t len, void ble_ll_sync_rmvd_from_sched(struct ble_ll_sync_sm *sm) { - ble_ll_event_send(&sm->sync_ev_end); + ble_ll_event_add(&sm->sync_ev_end); } bool @@ -2245,7 +2357,7 @@ ble_ll_sync_enabled(void) void ble_ll_sync_reset(void) { - int i; + unsigned int i; for (i = 0; i < BLE_LL_SYNC_CNT; i++) { ble_ll_sync_sm_clear(&g_ble_ll_sync_sm[i]); @@ -2271,7 +2383,7 @@ ble_ll_sync_reset(void) void ble_ll_sync_init(void) { - int i; + unsigned int i; for (i = 0; i < ARRAY_SIZE(g_ble_ll_sync_adv_list); i++) { g_ble_ll_sync_adv_list[i].adv_sid = 0xff; diff --git a/src/nimble/nimble/controller/src/ble_ll_trace.c b/src/nimble/nimble/controller/src/ble_ll_trace.c index 52985426..7be5a0be 100644 --- a/src/nimble/nimble/controller/src/ble_ll_trace.c +++ b/src/nimble/nimble/controller/src/ble_ll_trace.c @@ -20,7 +20,7 @@ #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os_trace_api.h" -#include "../include/controller/ble_ll_trace.h" +#include "nimble/nimble/controller/include/controller/ble_ll_trace.h" #if MYNEWT_VAL(BLE_LL_SYSVIEW) diff --git a/src/nimble/nimble/controller/src/ble_ll_utils.c b/src/nimble/nimble/controller/src/ble_ll_utils.c index e8cb85a7..acf15849 100644 --- a/src/nimble/nimble/controller/src/ble_ll_utils.c +++ b/src/nimble/nimble/controller/src/ble_ll_utils.c @@ -21,17 +21,9 @@ #include #include #include "nimble/nimble/include/nimble/ble.h" -#include "../include/controller/ble_ll.h" -#include "../include/controller/ble_ll_tmr.h" -#include "../include/controller/ble_ll_utils.h" - -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/nimble/controller/include/controller/ble_ll_tmr.h" +#include "nimble/nimble/controller/include/controller/ble_ll_utils.h" /* 37 bits require 5 bytes */ #define BLE_LL_CHMAP_LEN (5) @@ -41,10 +33,9 @@ static const uint16_t g_ble_sca_ppm_tbl[8] = { 500, 250, 150, 100, 75, 50, 30, 20 }; -uint32_t -ble_ll_utils_calc_access_addr(void) +int +ble_ll_utils_verify_aa(uint32_t aa) { - uint32_t aa; uint16_t aa_low; uint16_t aa_high; uint32_t temp; @@ -56,105 +47,175 @@ ble_ll_utils_calc_access_addr(void) uint8_t ones; int tmp; - /* Calculate a random access address */ - aa = 0; - while (1) { - /* Get two, 16-bit random numbers */ - aa_low = ble_ll_rand() & 0xFFFF; - aa_high = ble_ll_rand() & 0xFFFF; + aa_low = aa & 0xffff; + aa_high = aa >> 16; - /* All four bytes cannot be equal */ - if (aa_low == aa_high) { - continue; - } + /* All four bytes cannot be equal */ + if (aa_low == aa_high) { + return 0; + } - /* Upper 6 bits must have 2 transitions */ - tmp = (int16_t)aa_high >> 10; - if (__builtin_popcount(tmp ^ (tmp >> 1)) < 2) { - continue; - } + /* Upper 6 bits must have 2 transitions */ + tmp = (int16_t)aa_high >> 10; + if (__builtin_popcount(tmp ^ (tmp >> 1)) < 2) { + return 0; + } - /* Cannot be access address or be 1 bit different */ - aa = aa_high; - aa = (aa << 16) | aa_low; - bits_diff = 0; - temp = aa ^ BLE_ACCESS_ADDR_ADV; - for (mask = 0x00000001; mask != 0; mask <<= 1) { - if (mask & temp) { - ++bits_diff; - if (bits_diff > 1) { - break; - } + /* Cannot be access address or be 1 bit different */ + aa = aa_high; + aa = (aa << 16) | aa_low; + bits_diff = 0; + temp = aa ^ BLE_ACCESS_ADDR_ADV; + for (mask = 0x00000001; mask != 0; mask <<= 1) { + if (mask & temp) { + ++bits_diff; + if (bits_diff > 1) { + break; } } - if (bits_diff <= 1) { - continue; - } + } + if (bits_diff <= 1) { + return 0; + } - /* Cannot have more than 24 transitions */ - transitions = 0; - consecutive = 1; - ones = 0; - mask = 0x00000001; - while (mask < 0x80000000) { - prev_bit = aa & mask; - mask <<= 1; - if (mask & aa) { - if (prev_bit == 0) { - ++transitions; - consecutive = 1; - } else { - ++consecutive; - } + /* Cannot have more than 24 transitions */ + transitions = 0; + consecutive = 1; + ones = 0; + mask = 0x00000001; + while (mask < 0x80000000) { + prev_bit = aa & mask; + mask <<= 1; + if (mask & aa) { + if (prev_bit == 0) { + ++transitions; + consecutive = 1; } else { - if (prev_bit == 0) { - ++consecutive; - } else { - ++transitions; - consecutive = 1; - } + ++consecutive; } - - if (prev_bit) { - ones++; + } else { + if (prev_bit == 0) { + ++consecutive; + } else { + ++transitions; + consecutive = 1; } + } - /* 8 lsb should have at least three 1 */ - if (mask == 0x00000100 && ones < 3) { - break; - } + if (prev_bit) { + ones++; + } - /* 16 lsb should have no more than 11 transitions */ - if (mask == 0x00010000 && transitions > 11) { - break; - } + /* 8 lsb should have at least three 1 */ + if (mask == 0x00000100 && ones < 3) { + break; + } - /* This is invalid! */ - if (consecutive > 6) { - /* Make sure we always detect invalid sequence below */ - mask = 0; - break; - } + /* 16 lsb should have no more than 11 transitions */ + if (mask == 0x00010000 && transitions > 11) { + break; + } + + /* This is invalid! */ + if (consecutive > 6) { + /* Make sure we always detect invalid sequence below */ + mask = 0; + break; + } + } + + /* Invalid sequence found */ + if (mask != 0x80000000) { + return 0; + } + + /* Cannot be more than 24 transitions */ + if (transitions > 24) { + return 0; + } + + return 1; +} + +uint32_t +ble_ll_utils_calc_aa(void) +{ + uint32_t aa; + + do { + aa = ble_ll_rand(); + } while (!ble_ll_utils_verify_aa(aa)); + + return aa; +} + +uint32_t +ble_ll_utils_calc_seed_aa(void) +{ + uint32_t seed_aa; + + while (1) { + seed_aa = ble_ll_rand(); + + /* saa(19) == saa(15) */ + if (!!(seed_aa & (1 << 19)) != !!(seed_aa & (1 << 15))) { + continue; } - /* Invalid sequence found */ - if (mask != 0x80000000) { + /* saa(22) = saa(16) */ + if (!!(seed_aa & (1 << 22)) != !!(seed_aa & (1 << 16))) { continue; } - /* Cannot be more than 24 transitions */ - if (transitions > 24) { + /* saa(22) != saa(15) */ + if (!!(seed_aa & (1 << 22)) == !!(seed_aa & (1 << 15))) { + continue; + } + + /* saa(25) == 0 */ + if (seed_aa & (1 << 25)) { + continue; + } + + /* saa(23) == 1 */ + if (!(seed_aa & (1 << 23))) { continue; } - /* We have a valid access address */ break; } - return aa; + + return seed_aa; +} + +uint32_t +ble_ll_utils_calc_big_aa(uint32_t seed_aa, uint32_t n) +{ + uint32_t d; + uint32_t dw; + + /* Core 5.3, Vol 6, Part B, 2.1.2 */ + /* TODO simplify? */ + d = ((35 * n) + 42) % 128; + dw = (!!(d & (1 << 0)) << 31) | + (!!(d & (1 << 0)) << 30) | + (!!(d & (1 << 0)) << 29) | + (!!(d & (1 << 0)) << 28) | + (!!(d & (1 << 0)) << 27) | + (!!(d & (1 << 0)) << 26) | + (!!(d & (1 << 1)) << 25) | + (!!(d & (1 << 6)) << 24) | + (!!(d & (1 << 1)) << 23) | + (!!(d & (1 << 5)) << 21) | + (!!(d & (1 << 4)) << 20) | + (!!(d & (1 << 3)) << 18) | + (!!(d & (1 << 2)) << 17); + + return seed_aa ^ dw; } uint8_t -ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap) +ble_ll_utils_chan_map_remap(const uint8_t *chan_map, uint8_t remap_index) { uint8_t cntr; uint8_t mask; @@ -169,7 +230,7 @@ ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap) chan = 0; cntr = 0; for (i = 0; i < BLE_LL_CHMAP_LEN; i++) { - usable_chans = chanmap[i]; + usable_chans = chan_map[i]; if (usable_chans != 0) { mask = 0x01; for (j = 0; j < 8; j++) { @@ -191,23 +252,10 @@ ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap) } uint8_t -ble_ll_utils_calc_num_used_chans(const uint8_t *chan_map) +ble_ll_utils_chan_map_used_get(const uint8_t *chan_map) { - uint32_t u32 = 0; - uint32_t num_used_chans = 0; - unsigned idx; - - for (idx = 0; idx < 37; idx++) { - if ((idx % 8) == 0) { - u32 = chan_map[idx / 8]; - } - if (u32 & 1) { - num_used_chans++; - } - u32 >>= 1; - } - - return num_used_chans; + return __builtin_popcountll(((uint64_t)(chan_map[4] & 0x1f) << 32) | + get_le32(chan_map)); } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2) @@ -365,7 +413,7 @@ ble_ll_utils_dci_csa2(uint16_t counter, uint16_t chan_id, uint16_t ble_ll_utils_dci_iso_event(uint16_t counter, uint16_t chan_id, - uint16_t *prn_sub_lu, uint8_t num_used_chans, + uint16_t *prn_sub_lu, uint8_t chan_map_used, const uint8_t *chan_map, uint16_t *remap_idx) { uint16_t prn_s; @@ -377,7 +425,7 @@ ble_ll_utils_dci_iso_event(uint16_t counter, uint16_t chan_id, *prn_sub_lu = prn_s; - chan_idx = ble_ll_utils_csa2_calc_chan_idx(prn_e, num_used_chans, chan_map, + chan_idx = ble_ll_utils_csa2_calc_chan_idx(prn_e, chan_map_used, chan_map, remap_idx); return chan_idx; @@ -385,7 +433,7 @@ ble_ll_utils_dci_iso_event(uint16_t counter, uint16_t chan_id, uint16_t ble_ll_utils_dci_iso_subevent(uint16_t chan_id, uint16_t *prn_sub_lu, - uint8_t num_used_chans, const uint8_t *chan_map, + uint8_t chan_map_used, const uint8_t *chan_map, uint16_t *remap_idx) { uint16_t prn_sub_se; @@ -398,10 +446,10 @@ ble_ll_utils_dci_iso_subevent(uint16_t chan_id, uint16_t *prn_sub_lu, /* Core 5.3, Vol 6, Part B, 4.5.8.3.6 (enjoy!) */ /* TODO optimize this somehow */ - d = max(1, max(min(3, num_used_chans - 5), - min(11, (num_used_chans - 10) / 2))); + d = MAX(1, MAX(MIN(3, chan_map_used - 5), + MIN(11, (chan_map_used - 10) / 2))); *remap_idx = (*remap_idx + d + prn_sub_se * - (num_used_chans - 2 * d + 1) / 65536) % num_used_chans; + (chan_map_used - 2 * d + 1) / 65536) % chan_map_used; chan_idx = ble_ll_utils_csa2_remap2chan(*remap_idx, chan_map); diff --git a/src/nimble/nimble/controller/src/ble_ll_whitelist.c b/src/nimble/nimble/controller/src/ble_ll_whitelist.c index 1af49ed9..1cbfda06 100644 --- a/src/nimble/nimble/controller/src/ble_ll_whitelist.c +++ b/src/nimble/nimble/controller/src/ble_ll_whitelist.c @@ -25,25 +25,16 @@ #include "nimble/porting/nimble/include/os/os.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" - -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) #include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" -#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) -#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h" -#endif - -#include "../include/controller/ble_ll_whitelist.h" -#include "../include/controller/ble_ll_hci.h" -#include "../include/controller/ble_ll_adv.h" -#include "../include/controller/ble_ll_scan.h" -#include "../include/controller/ble_hw.h" +#include "nimble/nimble/controller/include/controller/ble_ll_whitelist.h" +#include "nimble/nimble/controller/include/controller/ble_ll_hci.h" +#include "nimble/nimble/controller/include/controller/ble_ll_adv.h" +#include "nimble/nimble/controller/include/controller/ble_ll_scan.h" +#include "nimble/nimble/controller/include/controller/ble_hw.h" #if (MYNEWT_VAL(BLE_LL_WHITELIST_SIZE) < BLE_HW_WHITE_LIST_SIZE) #define BLE_LL_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE) #else -#ifndef BLE_HW_WHITE_LIST_SIZE -#define BLE_HW_WHITE_LIST_SIZE 0 -#endif #define BLE_LL_WHITELIST_SIZE BLE_HW_WHITE_LIST_SIZE #endif diff --git a/src/nimble/nimble/drivers/nrf51/include/ble/xcvr.h b/src/nimble/nimble/drivers/nrf51/include/ble/xcvr.h index 6c1fb7b2..848c8cc8 100644 --- a/src/nimble/nimble/drivers/nrf51/include/ble/xcvr.h +++ b/src/nimble/nimble/drivers/nrf51/include/ble/xcvr.h @@ -17,8 +17,6 @@ * under the License. */ - #if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) - #ifndef H_BLE_XCVR_ #define H_BLE_XCVR_ @@ -48,4 +46,3 @@ extern "C" { #endif #endif /* H_BLE_XCVR_ */ -#endif diff --git a/src/nimble/nimble/drivers/nrf51/src/ble_hw.c b/src/nimble/nimble/drivers/nrf51/src/ble_hw.c index f2b56978..04195d2b 100644 --- a/src/nimble/nimble/drivers/nrf51/src/ble_hw.c +++ b/src/nimble/nimble/drivers/nrf51/src/ble_hw.c @@ -24,16 +24,16 @@ #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os.h" -#include "../include/ble/xcvr.h" +#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nrf.h" +#include "nrfx.h" #include "nimble/nimble/controller/include/controller/ble_hw.h" #if MYNEWT #include "mcu/cmsis_nvic.h" #else #include "core_cm0.h" -#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h" +#include #endif #include "nimble/porting/nimble/include/os/os_trace_api.h" @@ -90,11 +90,17 @@ ble_hw_get_public_addr(ble_addr_t *addr) int ble_hw_get_static_addr(ble_addr_t *addr) { + uint32_t addr_high; + uint32_t addr_low; int rc; if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) { - memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4); - memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2); + addr_low = NRF_FICR->DEVICEADDR[0]; + addr_high = NRF_FICR->DEVICEADDR[1]; + + memcpy(addr->val, &addr_low, 4); + memcpy(&addr->val[4], &addr_high, 2); + addr->val[5] |= 0xc0; addr->type = BLE_ADDR_RANDOM; rc = 0; @@ -483,4 +489,5 @@ ble_hw_resolv_list_match(void) return -1; } #endif -#endif + +#endif /* ARDUINO_ARCH_NRF5 && NRF51 */ diff --git a/src/nimble/nimble/drivers/nrf51/src/ble_phy.c b/src/nimble/nimble/drivers/nrf51/src/ble_phy.c index e3fcd26b..9b44ace0 100644 --- a/src/nimble/nimble/drivers/nrf51/src/ble_phy.c +++ b/src/nimble/nimble/drivers/nrf51/src/ble_phy.c @@ -17,7 +17,7 @@ * under the License. */ - #if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51) #include #include @@ -26,13 +26,13 @@ #include "nimble/porting/nimble/include/os/os.h" /* Keep os_cputime explicitly to enable build on non-Mynewt platforms */ #include "nimble/porting/nimble/include/os/os_cputime.h" -#include "../include/ble/xcvr.h" +#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" #include "nimble/nimble/controller/include/controller/ble_phy.h" #include "nimble/nimble/controller/include/controller/ble_phy_trace.h" #include "nimble/nimble/controller/include/controller/ble_ll.h" -#include "nrf.h" +#include "nrfx.h" #if MYNEWT #include "mcu/nrf51_clock.h" @@ -49,9 +49,11 @@ #error LE Coded PHY cannot be enabled on nRF51 #endif -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif +static uint32_t +ble_phy_mode_pdu_start_off(int phy_mode) +{ + return 40; +} /* XXX: 4) Make sure RF is higher priority interrupt than schedule */ @@ -102,7 +104,6 @@ struct ble_phy_obj uint8_t phy_privacy; uint8_t phy_tx_pyld_len; uint8_t *rxdptr; - int8_t rx_pwr_compensation; uint32_t phy_aar_scratch; uint32_t phy_access_address; struct ble_mbuf_hdr rxhdr; @@ -626,8 +627,7 @@ ble_phy_rx_end_isr(void) /* Set RSSI and CRC status flag in header */ ble_hdr = &g_ble_phy_data.rxhdr; assert(NRF_RADIO->EVENTS_RSSIEND != 0); - ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE) + - g_ble_phy_data.rx_pwr_compensation; + ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE); dptr = g_ble_phy_data.rxdptr; @@ -855,8 +855,6 @@ ble_phy_init(void) /* Set phy channel to an invalid channel so first set channel works */ g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS; - g_ble_phy_data.rx_pwr_compensation = 0; - /* Toggle peripheral power to reset (just in case) */ NRF_RADIO->POWER = 0; NRF_RADIO->POWER = 1; @@ -987,24 +985,10 @@ ble_phy_rx(void) } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/** - * Called to enable encryption at the PHY. Note that this state will persist - * in the PHY; in other words, if you call this function you have to call - * disable so that future PHY transmits/receives will not be encrypted. - * - * @param pkt_counter - * @param iv - * @param key - * @param is_master - */ void -ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, - uint8_t is_master) +ble_phy_encrypt_enable(const uint8_t *key) { memcpy(g_nrf_ccm_data.key, key, 16); - g_nrf_ccm_data.pkt_counter = pkt_counter; - memcpy(g_nrf_ccm_data.iv, iv, 8); - g_nrf_ccm_data.dir_bit = is_master; g_ble_phy_data.phy_encrypted = 1; /* Encryption uses LFLEN=5, S1LEN = 3. */ @@ -1018,10 +1002,16 @@ ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, } void -ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir) +ble_phy_encrypt_iv_set(const uint8_t *iv) +{ + memcpy(g_nrf_ccm_data.iv, iv, 8); +} + +void +ble_phy_encrypt_counter_set(uint64_t counter, uint8_t dir_bit) { - g_nrf_ccm_data.pkt_counter = pkt_counter; - g_nrf_ccm_data.dir_bit = dir; + g_nrf_ccm_data.pkt_counter = counter; + g_nrf_ccm_data.dir_bit = dir_bit; } void @@ -1262,7 +1252,7 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) * @return int 0: success; anything else is an error */ int -ble_phy_txpwr_set(int dbm) +ble_phy_tx_power_set(int dbm) { /* Check valid range */ assert(dbm <= BLE_PHY_MAX_PWR_DBM); @@ -1291,7 +1281,8 @@ ble_phy_txpwr_set(int dbm) * * @return int Rounded power in dBm */ -int ble_phy_txpower_round(int dbm) +int +ble_phy_tx_power_round(int dbm) { /* "Rail" power level if outside supported range */ if (dbm > NRF_TX_PWR_MAX_DBM) { @@ -1313,17 +1304,11 @@ int ble_phy_txpower_round(int dbm) * @return int The current PHY transmit power, in dBm */ int -ble_phy_txpwr_get(void) +ble_phy_tx_power_get(void) { return g_ble_phy_data.phy_txpwr_dbm; } -void -ble_phy_set_rx_pwr_compensation(int8_t compensation) -{ - g_ble_phy_data.rx_pwr_compensation = compensation; -} - /** * ble phy setchan * @@ -1382,6 +1367,12 @@ ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit) return 0; } +uint8_t +ble_phy_chan_get(void) +{ + return g_ble_phy_data.phy_chan; +} + /** * Stop the timer used to count microseconds when using RTC for cputime */ @@ -1530,4 +1521,5 @@ ble_phy_rfclk_disable(void) NRF_CLOCK->TASKS_HFCLKSTOP = 1; #endif } -#endif + +#endif /* ARDUINO_ARCH_NRF5 && NRF51 */ diff --git a/src/nimble/nimble/drivers/nrf52/include/ble/xcvr.h b/src/nimble/nimble/drivers/nrf5x/include/ble/xcvr.h similarity index 69% rename from src/nimble/nimble/drivers/nrf52/include/ble/xcvr.h rename to src/nimble/nimble/drivers/nrf5x/include/ble/xcvr.h index fd8e1e89..7c28fd3b 100644 --- a/src/nimble/nimble/drivers/nrf52/include/ble/xcvr.h +++ b/src/nimble/nimble/drivers/nrf5x/include/ble/xcvr.h @@ -17,7 +17,7 @@ * under the License. */ -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) +#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) #ifndef H_BLE_XCVR_ #define H_BLE_XCVR_ @@ -26,14 +26,23 @@ extern "C" { #endif +#include + #define XCVR_RX_RADIO_RAMPUP_USECS (40) #define XCVR_TX_RADIO_RAMPUP_USECS (40) -/* - * NOTE: we have to account for the RTC output compare issue. We want it to be - * 5 ticks. +/* We need to account for the RTC compare issue, we want it to be 5 ticks. + * In case FEM turn on time is more than radio enable (i.e. 2 ticks) we want + * to add 1 more tick to compensate for additional delay. + * + * TODO this file should be refactored... */ +#if (MYNEWT_VAL(BLE_FEM_PA) && (MYNEWT_VAL(BLE_FEM_PA_TURN_ON_US) > 60)) || \ + (MYNEWT_VAL(BLE_FEM_LNA) && (MYNEWT_VAL(BLE_FEM_LNA_TURN_ON_US) > 60)) +#define XCVR_PROC_DELAY_USECS (183) +#else #define XCVR_PROC_DELAY_USECS (153) +#endif #define XCVR_RX_START_DELAY_USECS (XCVR_RX_RADIO_RAMPUP_USECS) #define XCVR_TX_START_DELAY_USECS (XCVR_TX_RADIO_RAMPUP_USECS) #define XCVR_TX_SCHED_DELAY_USECS \ @@ -52,4 +61,4 @@ extern "C" { #endif #endif /* H_BLE_XCVR_ */ -#endif +#endif /* defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) */ diff --git a/src/nimble/nimble/drivers/nrf52/src/ble_hw.c b/src/nimble/nimble/drivers/nrf5x/src/ble_hw.c similarity index 95% rename from src/nimble/nimble/drivers/nrf52/src/ble_hw.c rename to src/nimble/nimble/drivers/nrf5x/src/ble_hw.c index a91d0404..e7cf010a 100644 --- a/src/nimble/nimble/drivers/nrf52/src/ble_hw.c +++ b/src/nimble/nimble/drivers/nrf5x/src/ble_hw.c @@ -17,23 +17,25 @@ * under the License. */ -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) +#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) #include #include #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os.h" -#include "../include/ble/xcvr.h" +#include "nimble/nimble/drivers/nrf5x/include/ble/xcvr.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" -#include "nrf.h" +#include "nrfx.h" #include "nimble/nimble/controller/include/controller/ble_hw.h" #if MYNEWT #include "mcu/cmsis_nvic.h" #else +#ifdef NRF52_SERIES #include "core_cm4.h" -#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h" +#endif +#include #endif #include "nimble/porting/nimble/include/os/os_trace_api.h" #include @@ -114,11 +116,17 @@ ble_hw_get_public_addr(ble_addr_t *addr) int ble_hw_get_static_addr(ble_addr_t *addr) { + uint32_t addr_high; + uint32_t addr_low; int rc; if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) { - memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4); - memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2); + addr_low = NRF_FICR->DEVICEADDR[0]; + addr_high = NRF_FICR->DEVICEADDR[1]; + + memcpy(addr->val, &addr_low, 4); + memcpy(&addr->val[4], &addr_high, 2); + addr->val[5] |= 0xc0; addr->type = BLE_ADDR_RANDOM; rc = 0; @@ -511,4 +519,5 @@ ble_hw_resolv_list_match(void) return -1; } #endif -#endif + +#endif /* defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) */ diff --git a/src/nimble/nimble/drivers/nrf52/src/ble_phy.c b/src/nimble/nimble/drivers/nrf5x/src/ble_phy.c similarity index 77% rename from src/nimble/nimble/drivers/nrf52/src/ble_phy.c rename to src/nimble/nimble/drivers/nrf5x/src/ble_phy.c index fa9af150..960fcc4e 100644 --- a/src/nimble/nimble/drivers/nrf52/src/ble_phy.c +++ b/src/nimble/nimble/drivers/nrf5x/src/ble_phy.c @@ -17,53 +17,63 @@ * under the License. */ - #if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) +#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) #include #include #include +#include #include #include #include #include -#include #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os.h" /* Keep os_cputime explicitly to enable build on non-Mynewt platforms */ #include "nimble/porting/nimble/include/os/os_cputime.h" -#include "../include/ble/xcvr.h" +#include "nimble/nimble/drivers/nrf5x/include/ble/xcvr.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" #include "nimble/nimble/include/nimble/nimble_npl.h" #include "nimble/nimble/controller/include/controller/ble_phy.h" #include "nimble/nimble/controller/include/controller/ble_phy_trace.h" #include "nimble/nimble/controller/include/controller/ble_ll.h" -#include "nimble/nimble/controller/include/controller/ble_ll_plna.h" #include "nrfx.h" #if MYNEWT -#include "mcu/nrf52_clock.h" +#ifdef NRF52_SERIES +#include +#endif +#ifdef NRF53_SERIES +#include +#endif #include "mcu/cmsis_nvic.h" -#include "hal/hal_gpio.h" +#include "nimble/porting/nimble/include/hal/hal_gpio.h" #else +#include +#ifdef NRF52_SERIES #include "core_cm4.h" #endif +#endif +#include +#include "phy_priv.h" #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) -#if !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52840) && !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52811) && \ - !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52833) && !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52820) -#error LE Coded PHY can only be enabled on nRF52811, nRF52840, nRF52833 or nRF52820 +#if !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52840) && \ + !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52811) && \ + !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF5340_NET) && \ + !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52833) && \ + !MYNEWT_VAL_CHOICE(MCU_TARGET, nRF52820) +#error LE Coded PHY can only be enabled on nRF52811, nRF52820, nRF52833, nRF52840 or nRF5340 #endif #endif -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - #if BABBLESIM extern void tm_tick(void); #endif +#include + /* * NOTE: This code uses a couple of PPI channels so care should be taken when * using PPI somewhere else. @@ -134,21 +144,30 @@ struct ble_phy_obj uint8_t phy_transition_late; uint8_t phy_rx_started; uint8_t phy_encrypted; +#if PHY_USE_HEADERMASK_WORKAROUND + uint8_t phy_headermask; + uint8_t phy_headerbyte; +#endif uint8_t phy_privacy; uint8_t phy_tx_pyld_len; uint8_t phy_cur_phy_mode; uint8_t phy_tx_phy_mode; uint8_t phy_rx_phy_mode; uint8_t phy_bcc_offset; - int8_t rx_pwr_compensation; uint32_t phy_aar_scratch; uint32_t phy_access_address; struct ble_mbuf_hdr rxhdr; void *txend_arg; ble_phy_tx_end_func txend_cb; uint32_t phy_start_cputime; +#if MYNEWT_VAL(BLE_PHY_VARIABLE_TIFS) + uint16_t tifs; +#endif + + uint16_t txtx_time_us; + uint8_t txtx_time_anchor; }; -struct ble_phy_obj g_ble_phy_data; +static struct ble_phy_obj g_ble_phy_data; /* XXX: if 27 byte packets desired we can make this smaller */ /* Global transmit/receive buffer */ @@ -310,7 +329,7 @@ STATS_NAME_END(ble_phy_stats) //#define NRF_ENC_SCRATCH_WORDS (((MYNEWT_VAL(BLE_LL_MAX_PKT_SIZE) + 16) + 3) / 4) #define NRF_ENC_SCRATCH_WORDS (67) -uint32_t g_nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS]; +static uint32_t g_nrf_encrypt_scratchpad[NRF_ENC_SCRATCH_WORDS]; struct nrf_ccm_data { @@ -323,52 +342,18 @@ struct nrf_ccm_data struct nrf_ccm_data g_nrf_ccm_data; #endif -static int g_ble_phy_gpiote_idx; - -#if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA) - -#define PLNA_SINGLE_GPIO \ - (!MYNEWT_VAL(BLE_LL_PA) || !MYNEWT_VAL(BLE_LL_LNA) || \ - (MYNEWT_VAL(BLE_LL_PA_GPIO) == MYNEWT_VAL(BLE_LL_LNA_GPIO))) - -#if PLNA_SINGLE_GPIO -static uint8_t plna_idx; -#else -#if MYNEWT_VAL(BLE_LL_PA) -static uint8_t plna_pa_idx; -#endif -#if MYNEWT_VAL(BLE_LL_LNA) -static uint8_t plna_lna_idx; -#endif -#endif - -#endif - -#ifndef BABBLESIM -static void -ble_phy_apply_errata_102_106_107(void) -{ - /* [102] RADIO: PAYLOAD/END events delayed or not triggered after ADDRESS - * [106] RADIO: Higher CRC error rates for some access addresses - * [107] RADIO: Immediate address match for access addresses containing MSBs 0x00 - */ - *(volatile uint32_t *)0x40001774 = ((*(volatile uint32_t *)0x40001774) & - 0xfffffffe) | 0x01000000; -} -#endif - #if (BLE_LL_BT5_PHY_SUPPORTED == 1) /* Packet start offset (in usecs). This is the preamble plus access address. * For LE Coded PHY this also includes CI and TERM1. */ -uint32_t +static uint32_t ble_phy_mode_pdu_start_off(int phy_mode) { return g_ble_phy_mode_pkt_start_off[phy_mode]; } -#if NRF52840_XXAA -static inline bool +#if NRF52_ERRATA_191_ENABLE_WORKAROUND +static bool ble_phy_mode_is_coded(uint8_t phy_mode) { return (phy_mode == BLE_PHY_MODE_CODED_125KBPS) || @@ -376,48 +361,26 @@ ble_phy_mode_is_coded(uint8_t phy_mode) } static void -ble_phy_apply_nrf52840_errata(uint8_t new_phy_mode) +phy_nrf52_errata_191(uint8_t new_phy_mode) { - bool new_coded = ble_phy_mode_is_coded(new_phy_mode); - bool cur_coded = ble_phy_mode_is_coded(g_ble_phy_data.phy_cur_phy_mode); + bool from_coded = ble_phy_mode_is_coded(g_ble_phy_data.phy_cur_phy_mode); + bool to_coded = ble_phy_mode_is_coded(new_phy_mode); - /* - * Workarounds should be applied only when switching to/from LE Coded PHY - * so no need to apply them every time. - * - * nRF52840 Engineering A Errata v1.2 - * [164] RADIO: Low sensitivity in long range mode - * - * nRF52840 Rev 1 Errata - * [191] RADIO: High packet error rate in BLE Long Range mode + /* [191] RADIO: High packet error rate in BLE Long Range mode + * Should be applied only if switching to/from LE Coded, no need to apply + * on each mode change. */ - if (new_coded == cur_coded) { + if (from_coded == to_coded) { return; } - if (new_coded) { -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_164) - /* [164] */ - *(volatile uint32_t *)0x4000173C |= 0x80000000; - *(volatile uint32_t *)0x4000173C = - ((*(volatile uint32_t *)0x4000173C & 0xFFFFFF00) | 0x5C); -#endif -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_191) - /* [191] */ - *(volatile uint32_t *) 0x40001740 = - ((*((volatile uint32_t *) 0x40001740)) & 0x7FFF00FF) | - 0x80000000 | (((uint32_t)(196)) << 8); -#endif + if (to_coded) { + *(volatile uint32_t *)0x40001740 = + ((*((volatile uint32_t *)0x40001740)) & 0x7fff00ff) | + 0x80000000 | (((uint32_t)(196)) << 8); } else { -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_164) - /* [164] */ - *(volatile uint32_t *)0x4000173C &= ~0x80000000; -#endif -#if MYNEWT_VAL(BLE_PHY_NRF52840_ERRATA_191) - /* [191] */ *(volatile uint32_t *) 0x40001740 = - ((*((volatile uint32_t *) 0x40001740)) & 0x7FFFFFFF); -#endif + ((*((volatile uint32_t *) 0x40001740)) & 0x7fffffff); } } #endif @@ -429,28 +392,42 @@ ble_phy_mode_apply(uint8_t phy_mode) return; } -#if NRF52840_XXAA - ble_phy_apply_nrf52840_errata(phy_mode); +#if NRF52_ERRATA_191_ENABLE_WORKAROUND + if (nrf52_errata_191()) { + phy_nrf52_errata_191(phy_mode); + } #endif switch (phy_mode) { case BLE_PHY_MODE_1M: NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_1Mbit; +#ifdef NRF53_SERIES + *((volatile uint32_t *)0x41008588) = *((volatile uint32_t *)0x01FF0080); +#endif NRF_RADIO->PCNF0 = NRF_PCNF0_1M; break; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) case BLE_PHY_MODE_2M: NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_2Mbit; +#ifdef NRF53_SERIES + *((volatile uint32_t *)0x41008588) = *((volatile uint32_t *)0x01FF0084); +#endif NRF_RADIO->PCNF0 = NRF_PCNF0_2M; break; #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) case BLE_PHY_MODE_CODED_125KBPS: NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR125Kbit; +#ifdef NRF53_SERIES + *((volatile uint32_t *)0x41008588) = *((volatile uint32_t *)0x01FF0080); +#endif NRF_RADIO->PCNF0 = NRF_PCNF0_CODED; break; case BLE_PHY_MODE_CODED_500KBPS: NRF_RADIO->MODE = RADIO_MODE_MODE_Ble_LR500Kbit; +#ifdef NRF53_SERIES + *((volatile uint32_t *)0x41008588) = *((volatile uint32_t *)0x01FF0080); +#endif NRF_RADIO->PCNF0 = NRF_PCNF0_CODED; break; #endif @@ -467,39 +444,15 @@ ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode) g_ble_phy_data.phy_tx_phy_mode = tx_phy_mode; g_ble_phy_data.phy_rx_phy_mode = rx_phy_mode; } -#endif - -static void -ble_phy_plna_enable_pa(void) +#else +static uint32_t +ble_phy_mode_pdu_start_off(int phy_mode) { -#if MYNEWT_VAL(BLE_LL_PA) - ble_ll_plna_pa_enable(); - -#if !PLNA_SINGLE_GPIO - NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[plna_pa_idx]); - NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[plna_pa_idx]); -#endif - - NRF_PPI->CHENSET = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; -#endif + return 40; } - -static void -ble_phy_plna_enable_lna(void) -{ -#if MYNEWT_VAL(BLE_LL_LNA) - ble_ll_plna_lna_enable(); - -#if !PLNA_SINGLE_GPIO - NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[plna_lna_idx]); - NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[plna_lna_idx]); #endif - NRF_PPI->CHENSET = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; -#endif -} - -int +static int ble_phy_get_cur_phy(void) { #if (BLE_LL_BT5_PHY_SUPPORTED == 1) @@ -649,46 +602,78 @@ nrf_wait_disabled(void) } } +#if MYNEWT_VAL(BLE_PHY_VARIABLE_TIFS) +void +ble_phy_tifs_set(uint16_t tifs) +{ + g_ble_phy_data.tifs = tifs; +} +#endif + /** * * */ static int -ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx) +ble_phy_set_start_time(uint32_t cputime, uint8_t rem_us, bool tx) { uint32_t next_cc; uint32_t cur_cc; uint32_t cntr; uint32_t delta; + int radio_rem_us; +#if PHY_USE_FEM + int fem_rem_us = 0; +#endif + int rem_us_corr; + int min_rem_us; - /* - * We need to adjust start time to include radio ramp-up and TX pipeline - * delay (the latter only if applicable, so only for TX). - * - * Radio ramp-up time is 40 usecs and TX delay is 3 or 5 usecs depending on - * phy, thus we'll offset RTC by 2 full ticks (61 usecs) and then compensate - * using TIMER0 with 1 usec precision. + /* Calculate rem_us for radio and FEM enable. The result may be a negative + * value, but we'll adjust later. */ - - cputime -= 2; - rem_usecs += 61; if (tx) { - rem_usecs -= BLE_PHY_T_TXENFAST; - rem_usecs -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; + radio_rem_us = rem_us - BLE_PHY_T_TXENFAST - + g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; +#if PHY_USE_FEM_PA + fem_rem_us = rem_us - MYNEWT_VAL(BLE_FEM_PA_TURN_ON_US); +#endif } else { - rem_usecs -= BLE_PHY_T_RXENFAST; + radio_rem_us = rem_us - BLE_PHY_T_TXENFAST; +#if PHY_USE_FEM_LNA + fem_rem_us = rem_us - MYNEWT_VAL(BLE_FEM_LNA_TURN_ON_US); +#endif } - /* - * rem_usecs will be no more than 2 ticks, but if it is more than single - * tick then we should better count one more low-power tick rather than - * 30 high-power usecs. Also make sure we don't set TIMER0 CC to 0 as the - * compare won't occur. +#if PHY_USE_FEM + min_rem_us = min(radio_rem_us, fem_rem_us); +#else + min_rem_us = radio_rem_us; +#endif + + /* We need to adjust rem_us values, so they are >=1 for TIMER0 compare + * event to be triggered. + * + * If FEM is not enabled, calculated rem_us is -45<=rem_us<=-15 since we + * only had to adjust earlier for ramp-up and txdelay, i.e. 40+5=45us in + * worst case, so we adjust by 1 or 2 tick(s) only. + * + * If FEM is enabled, turn on time may be a bit longer, so we also allow to + * adjust by 3 ticks so up to 90us which should be enough. If needed, we + * can extend this by another tick but having FEM with turn on time >90us + * means transition may become tricky. */ - if (rem_usecs > 30) { - cputime++; - rem_usecs -= 30; + if ((PHY_USE_FEM) && (min_rem_us <= -61)) { + cputime -= 3; + rem_us_corr = 91; + } else if (min_rem_us <= -30) { + /* rem_us is -60..-30 */ + cputime -= 2; + rem_us_corr = 61; + } else { + /* rem_us is -29..0 */ + cputime -= 1; + rem_us_corr = 30; } /* @@ -716,8 +701,14 @@ ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx) /* Clear and set TIMER0 to fire off at proper time */ nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR); - nrf_timer_cc_set(NRF_TIMER0, 0, rem_usecs); + nrf_timer_cc_set(NRF_TIMER0, 0, radio_rem_us + rem_us_corr); NRF_TIMER0->EVENTS_COMPARE[0] = 0; +#if PHY_USE_FEM + if (fem_rem_us) { + nrf_timer_cc_set(NRF_TIMER0, 2, fem_rem_us + rem_us_corr); + NRF_TIMER0->EVENTS_COMPARE[2] = 0; + } +#endif /* Set RTC compare to start TIMER0 */ NRF_RTC0->EVENTS_COMPARE[0] = 0; @@ -725,7 +716,20 @@ ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs, bool tx) nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE0_Msk); /* Enable PPI */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH31_Msk); +#if PHY_USE_FEM + if (fem_rem_us) { + if (tx) { +#if PHY_USE_FEM_PA + phy_fem_enable_pa(); +#endif + } else { +#if PHY_USE_FEM_LNA + phy_fem_enable_lna(); +#endif + } + } +#endif + phy_ppi_rtc0_compare0_to_timer0_start_enable(); /* Store the cputime at which we set the RTC */ g_ble_phy_data.phy_start_cputime = cputime; @@ -738,16 +742,41 @@ ble_phy_set_start_now(void) { os_sr_t sr; uint32_t now; + uint32_t radio_rem_us; +#if PHY_USE_FEM_LNA + uint32_t fem_rem_us; +#endif OS_ENTER_CRITICAL(sr); - /* - * Set TIMER0 to fire immediately. We can't set CC to 0 as compare will not - * occur in such case. + /* We need to set TIMER0 compare registers to at least 1 as otherwise + * compare event won't be triggered. Event (FEM/radio) that have to be + * triggered first is set to 1, other event is set to 1+diff. + * + * Note that this is only used for rx, so only need to handle LNA. */ + +#if PHY_USE_FEM_LNA + if (MYNEWT_VAL(BLE_FEM_LNA_TURN_ON_US) > BLE_PHY_T_RXENFAST) { + radio_rem_us = 1 + MYNEWT_VAL(BLE_FEM_LNA_TURN_ON_US) - + BLE_PHY_T_RXENFAST; + fem_rem_us = 1; + } else { + radio_rem_us = 1; + fem_rem_us = 1 + BLE_PHY_T_RXENFAST - + MYNEWT_VAL(BLE_FEM_LNA_TURN_ON_US); + } +#else + radio_rem_us = 1; +#endif + nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CLEAR); - nrf_timer_cc_set(NRF_TIMER0, 0, 1); + nrf_timer_cc_set(NRF_TIMER0, 0, radio_rem_us); NRF_TIMER0->EVENTS_COMPARE[0] = 0; +#if PHY_USE_FEM_LNA + nrf_timer_cc_set(NRF_TIMER0, 2, fem_rem_us); + NRF_TIMER0->EVENTS_COMPARE[2] = 0; +#endif /* * Set RTC compare to start TIMER0. We need to set it to at least N+2 ticks @@ -757,11 +786,16 @@ ble_phy_set_start_now(void) */ now = os_cputime_get32(); NRF_RTC0->EVENTS_COMPARE[0] = 0; - nrf_rtc_cc_set(NRF_RTC0, 0, now + 3); + nrf_rtc_cc_set(NRF_RTC0, 0, (now + 3) & 0xffffff); nrf_rtc_event_enable(NRF_RTC0, RTC_EVTENSET_COMPARE0_Msk); +#if PHY_USE_FEM_LNA + phy_fem_enable_lna(); +#endif + /* Enable PPI */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH31_Msk); + phy_ppi_rtc0_compare0_to_timer0_start_enable(); + /* * Store the cputime at which we set the RTC * @@ -798,12 +832,19 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) { uint32_t end_time; uint8_t phy; + uint16_t tifs; phy = g_ble_phy_data.phy_cur_phy_mode; +#if MYNEWT_VAL(BLE_PHY_VARIABLE_TIFS) + tifs = g_ble_phy_data.tifs; +#else + tifs = BLE_LL_IFS; +#endif + if (txrx == BLE_PHY_WFR_ENABLE_TXRX) { /* RX shall start exactly T_IFS after TX end captured in CC[2] */ - end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; + end_time = NRF_TIMER0->CC[2] + tifs; /* Adjust for delay between EVENT_END and actual TX end time */ end_time += g_ble_phy_t_txenddelay[tx_phy_mode]; /* Wait a bit longer due to allowed active clock accuracy */ @@ -840,7 +881,7 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) NRF_TIMER0->EVENTS_COMPARE[3] = 0; /* Enable wait for response PPI */ - nrf_ppi_channels_enable(NRF_PPI, (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk)); + phy_ppi_wfr_enable(); /* * It may happen that if CPU is halted for a brief moment (e.g. during flash @@ -856,7 +897,7 @@ ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs) */ nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE1); if (NRF_TIMER0->CC[1] > NRF_TIMER0->CC[3]) { - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); + phy_ppi_wfr_disable(); nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE); } } @@ -911,7 +952,7 @@ ble_phy_rx_xcvr_setup(void) NRF_CCM->EVENTS_ERROR = 0; NRF_CCM->EVENTS_ENDCRYPT = 0; nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN); - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH25_Msk); + phy_ppi_radio_address_to_ccm_crypt_enable(); } else { NRF_RADIO->PACKETPTR = (uint32_t)dptr; } @@ -935,7 +976,8 @@ ble_phy_rx_xcvr_setup(void) #endif /* Turn off trigger TXEN on output compare match and AAR on bcmatch */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk | PPI_CHEN_CH23_Msk); + phy_ppi_timer0_compare0_to_radio_txen_disable(); + phy_ppi_radio_bcmatch_to_aar_start_disable(); /* Reset the rx started flag. Used for the wait for response */ g_ble_phy_data.phy_rx_started = 0; @@ -984,6 +1026,12 @@ ble_phy_tx_end_isr(void) uint8_t was_encrypted; uint8_t transition; uint32_t rx_time; + uint32_t tx_time; +#if PHY_USE_FEM + uint32_t fem_time; +#endif + uint32_t radio_time; + uint16_t tifs; /* Store PHY on which we've just transmitted smth */ tx_phy_mode = g_ble_phy_data.phy_cur_phy_mode; @@ -1008,14 +1056,19 @@ ble_phy_tx_end_isr(void) } #endif - /* Call transmit end callback */ +#if MYNEWT_VAL(BLE_PHY_VARIABLE_TIFS) + tifs = g_ble_phy_data.tifs; + g_ble_phy_data.tifs = BLE_LL_IFS; +#else + tifs = BLE_LL_IFS; +#endif + transition = g_ble_phy_data.phy_transition; + if (g_ble_phy_data.txend_cb) { g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg); } - transition = g_ble_phy_data.phy_transition; if (transition == BLE_PHY_TRANSITION_TX_RX) { - #if (BLE_LL_BT5_PHY_SUPPORTED == 1) ble_phy_mode_apply(g_ble_phy_data.phy_rx_phy_mode); #endif @@ -1026,19 +1079,76 @@ ble_phy_tx_end_isr(void) ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, tx_phy_mode, 0); /* Schedule RX exactly T_IFS after TX end captured in CC[2] */ - rx_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; + rx_time = NRF_TIMER0->CC[2] + tifs; /* Adjust for delay between EVENT_END and actual TX end time */ rx_time += g_ble_phy_t_txenddelay[tx_phy_mode]; - /* Adjust for radio ramp-up */ - rx_time -= BLE_PHY_T_RXENFAST; /* Start listening a bit earlier due to allowed active clock accuracy */ rx_time -= 2; - nrf_timer_cc_set(NRF_TIMER0, 0, rx_time); +#if PHY_USE_FEM_LNA + fem_time = rx_time - MYNEWT_VAL(BLE_FEM_LNA_TURN_ON_US); + nrf_timer_cc_set(NRF_TIMER0, 2, fem_time); + NRF_TIMER0->EVENTS_COMPARE[2] = 0; + phy_fem_enable_lna(); +#endif + + radio_time = rx_time - BLE_PHY_T_RXENFAST; + nrf_timer_cc_set(NRF_TIMER0, 0, radio_time); + NRF_TIMER0->EVENTS_COMPARE[0] = 0; + phy_ppi_timer0_compare0_to_radio_rxen_enable(); + + /* In case TIMER0 did already count past CC[0] and/or CC[2], radio + * and/or LNA may not be enabled. In any case we won't be stuck since + * wfr will cancel rx if needed. + * + * FIXME failing to enable LNA may result in unexpected RSSI drop in + * case we still rxd something, so perhaps we could check it here + */ + } else if (transition == BLE_PHY_TRANSITION_TX_TX) { + if (g_ble_phy_data.txtx_time_anchor) { + /* Schedule next TX relative to current TX end. TX end timestamp is + * captured in CC[2]. + */ + tx_time = NRF_TIMER0->CC[2] + g_ble_phy_data.txtx_time_us; + } else { + /* Schedule next TX relative to current TX start. AA timestamp is + * captured in CC[1], we need to adjust for sync word to get TX + * start. + */ + tx_time = NRF_TIMER0->CC[1] - ble_ll_pdu_syncword_us(tx_phy_mode) + + g_ble_phy_data.txtx_time_us; + /* Adjust for delay between EVENT_ADDRESS and actual address TX time */ + /* FIXME assume this is the same as EVENT_END to end, but we should + * measure this to be sure */ + tx_time += g_ble_phy_t_txenddelay[tx_phy_mode]; + } + + /* Adjust for delay between EVENT_END and actual TX end time */ + tx_time += g_ble_phy_t_txenddelay[tx_phy_mode]; + +#if PHY_USE_FEM_PA + fem_time = tx_time - MYNEWT_VAL(BLE_FEM_PA_TURN_ON_US); +#endif + + /* Adjust for delay between EVENT_READY and actual TX start time */ + tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; + + radio_time = tx_time - BLE_PHY_T_TXENFAST; + nrf_timer_cc_set(NRF_TIMER0, 0, radio_time); NRF_TIMER0->EVENTS_COMPARE[0] = 0; - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk); + phy_ppi_timer0_compare0_to_radio_txen_enable(); - ble_phy_plna_enable_lna(); +#if PHY_USE_FEM_PA + nrf_timer_cc_set(NRF_TIMER0, 2, fem_time); + NRF_TIMER0->EVENTS_COMPARE[2] = 0; + phy_fem_enable_pa(); +#endif + + nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3); + if (NRF_TIMER0->CC[3] > NRF_TIMER0->CC[0]) { + phy_ppi_timer0_compare0_to_radio_txen_disable(); + g_ble_phy_data.phy_transition_late = 1; + } } else { /* * XXX: not sure we need to stop the timer here all the time. Or that @@ -1046,8 +1156,9 @@ ble_phy_tx_end_isr(void) */ nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_STOP); NRF_TIMER0->TASKS_SHUTDOWN = 1; - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | - PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk); + phy_ppi_wfr_disable(); + phy_ppi_timer0_compare0_to_radio_txen_disable(); + phy_ppi_rtc0_compare0_to_timer0_start_disable(); assert(transition == BLE_PHY_TRANSITION_NONE); } } @@ -1084,16 +1195,21 @@ ble_phy_rx_end_isr(void) uint8_t *dptr; uint8_t crcok; uint32_t tx_time; +#if PHY_USE_FEM_PA + uint32_t fem_time; +#endif + uint32_t radio_time; + uint16_t tifs; struct ble_mbuf_hdr *ble_hdr; + bool is_late; /* Disable automatic RXEN */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH21_Msk); + phy_ppi_timer0_compare0_to_radio_rxen_disable(); /* Set RSSI and CRC status flag in header */ ble_hdr = &g_ble_phy_data.rxhdr; assert(NRF_RADIO->EVENTS_RSSIEND != 0); - ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE) + - g_ble_phy_data.rx_pwr_compensation; + ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE); dptr = (uint8_t *)&g_ble_phy_rx_buf[0]; dptr += 3; @@ -1107,6 +1223,10 @@ ble_phy_rx_end_isr(void) ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) if (g_ble_phy_data.phy_encrypted) { + while (NRF_CCM->EVENTS_ENDCRYPT == 0) { + /* Make sure CCM finished */ + }; + /* Only set MIC failure flag if frame is not zero length */ if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) { ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE; @@ -1122,16 +1242,6 @@ ble_phy_rx_end_isr(void) STATS_INC(ble_phy_stats, rx_hw_err); ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; } - - /* - * XXX: This is a total hack work-around for now but I dont - * know what else to do. If ENDCRYPT is not set and we are - * encrypted we need to not trust this frame and drop it. - */ - if (NRF_CCM->EVENTS_ENDCRYPT == 0) { - STATS_INC(ble_phy_stats, rx_hw_err); - ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK; - } } #endif } @@ -1154,36 +1264,50 @@ ble_phy_rx_end_isr(void) * enough. */ +#if MYNEWT_VAL(BLE_PHY_VARIABLE_TIFS) + tifs = g_ble_phy_data.tifs; + g_ble_phy_data.tifs = BLE_LL_IFS; +#else + tifs = BLE_LL_IFS; +#endif + /* Schedule TX exactly T_IFS after RX end captured in CC[2] */ - tx_time = NRF_TIMER0->CC[2] + BLE_LL_IFS; + tx_time = NRF_TIMER0->CC[2] + tifs; /* Adjust for delay between actual RX end time and EVENT_END */ tx_time -= g_ble_phy_t_rxenddelay[ble_hdr->rxinfo.phy_mode]; - /* Adjust for radio ramp-up */ - tx_time -= BLE_PHY_T_TXENFAST; + +#if PHY_USE_FEM_PA + fem_time = tx_time - MYNEWT_VAL(BLE_FEM_PA_TURN_ON_US); +#endif + /* Adjust for delay between EVENT_READY and actual TX start time */ tx_time -= g_ble_phy_t_txdelay[g_ble_phy_data.phy_cur_phy_mode]; - nrf_timer_cc_set(NRF_TIMER0, 0, tx_time); + radio_time = tx_time - BLE_PHY_T_TXENFAST; + nrf_timer_cc_set(NRF_TIMER0, 0, radio_time); NRF_TIMER0->EVENTS_COMPARE[0] = 0; - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk); + phy_ppi_timer0_compare0_to_radio_txen_enable(); - ble_phy_plna_enable_pa(); +#if PHY_USE_FEM_PA + nrf_timer_cc_set(NRF_TIMER0, 2, fem_time); + NRF_TIMER0->EVENTS_COMPARE[2] = 0; + phy_fem_enable_pa(); +#endif - /* - * XXX: Hack warning! - * - * It may happen (during flash erase) that CPU is stopped for a moment and - * TIMER0 already counted past CC[0]. In such case we will be stuck waiting - * for TX to start since EVENTS_COMPARE[0] will not happen any time soon. - * For now let's set a flag denoting that we are late in RX-TX transition so - * ble_phy_tx() will fail - this allows everything to cleanup nicely without - * the need for extra handling in many places. + /* Need to check if TIMER0 did not already count past CC[0] and/or CC[2], so + * we're not stuck waiting for events in case radio and/or PA was not + * started. If event was triggered we're fine regardless of timer value. * * Note: CC[3] is used only for wfr which we do not need here. */ nrf_timer_task_trigger(NRF_TIMER0, NRF_TIMER_TASK_CAPTURE3); - if (NRF_TIMER0->CC[3] > NRF_TIMER0->CC[0]) { - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk); + is_late = (NRF_TIMER0->CC[3] > radio_time) && !NRF_TIMER0->EVENTS_COMPARE[0]; +#if PHY_USE_FEM_PA + is_late = is_late || + ((NRF_TIMER0->CC[3] > fem_time) && !NRF_TIMER0->EVENTS_COMPARE[2]); +#endif + if (is_late) { + phy_ppi_timer0_compare0_to_radio_txen_disable(); g_ble_phy_data.phy_transition_late = 1; } @@ -1221,7 +1345,7 @@ ble_phy_rx_start_isr(void) nrf_radio_int_disable(NRF_RADIO, RADIO_INTENCLR_ADDRESS_Msk); /* Clear wfr timer channels */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); + phy_ppi_wfr_disable(); /* Initialize the ble mbuf header */ ble_hdr = &g_ble_phy_data.rxhdr; @@ -1303,7 +1427,7 @@ ble_phy_rx_start_isr(void) /* Trigger AAR after last bit of AdvA is received */ NRF_RADIO->EVENTS_BCMATCH = 0; - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH23_Msk); + phy_ppi_radio_bcmatch_to_aar_start_enable(); nrf_radio_bcc_set(NRF_RADIO, (BLE_LL_PDU_HDR_LEN + adva_offset + BLE_DEV_ADDR_LEN) * 8 + g_ble_phy_data.phy_bcc_offset); } @@ -1375,9 +1499,9 @@ ble_phy_isr(void) switch (g_ble_phy_data.phy_state) { case BLE_PHY_STATE_RX: -#if MYNEWT_VAL(BLE_LL_LNA) - NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; - ble_ll_plna_lna_disable(); +#if MYNEWT_VAL(BLE_FEM_LNA) + phy_ppi_fem_disable(); + ble_fem_lna_disable(); #endif if (g_ble_phy_data.phy_rx_started) { ble_phy_rx_end_isr(); @@ -1386,9 +1510,9 @@ ble_phy_isr(void) } break; case BLE_PHY_STATE_TX: -#if MYNEWT_VAL(BLE_LL_PA) - NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; - ble_ll_plna_pa_disable(); +#if MYNEWT_VAL(BLE_FEM_PA) + phy_ppi_fem_disable(); + ble_fem_pa_disable(); #endif ble_phy_tx_end_isr(); break; @@ -1405,94 +1529,19 @@ ble_phy_isr(void) os_trace_isr_exit(); } -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 || \ - MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 || \ - MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 || \ - MYNEWT_VAL(BLE_LL_PA) || \ - MYNEWT_VAL(BLE_LL_LNA) -static int -ble_phy_gpiote_configure(int pin) -{ - NRF_GPIO_Type *port; - - g_ble_phy_gpiote_idx--; - -#if NRF52840_XXAA - port = pin > 31 ? NRF_P1 : NRF_P0; - pin &= 0x1f; -#else - port = NRF_P0; -#endif - - /* Configure GPIO directly to avoid dependency to hal_gpio (for porting) */ - port->DIRSET = (1 << pin); - port->OUTCLR = (1 << pin); - - NRF_GPIOTE->CONFIG[g_ble_phy_gpiote_idx] = - (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) | - ((pin & 0x1F) << GPIOTE_CONFIG_PSEL_Pos) | -#if NRF52840_XXAA - ((port == NRF_P1) << GPIOTE_CONFIG_PORT_Pos); -#else - 0; -#endif - - BLE_LL_ASSERT(g_ble_phy_gpiote_idx >= 0); - - return g_ble_phy_gpiote_idx; -} -#endif - +#if PHY_USE_HEADERMASK_WORKAROUND static void -ble_phy_dbg_time_setup(void) +ble_phy_ccm_isr(void) { - int idx __attribute__((unused)); - - /* - * We setup GPIOTE starting from last configuration index to minimize risk - * of conflict with GPIO setup via hal. It's not great solution, but since - * this is just debugging code we can live with this. - */ - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0 - idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); - - nrf_ppi_channel_endpoint_setup(NRF_PPI, 17, (uint32_t)&(NRF_RADIO->EVENTS_READY), - (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx])); - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH17_Msk); - - /* CH[20] and PPI CH[21] are on to trigger TASKS_TXEN or TASKS_RXEN */ - nrf_ppi_fork_endpoint_setup(NRF_PPI, 20, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx])); - nrf_ppi_fork_endpoint_setup(NRF_PPI, 21, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx])); -#endif - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0 - idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); + volatile uint8_t *tx_buf = (uint8_t *)g_ble_phy_tx_buf; - /* CH[26] and CH[27] are always on for EVENT_ADDRESS and EVENT_END */ - nrf_ppi_fork_endpoint_setup(NRF_PPI, 26, (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx])); - nrf_ppi_fork_endpoint_setup(NRF_PPI, 27, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx])); -#endif - -#if MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0 - idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); - -#if NRF52840_XXAA - nrf_ppi_channel_endpoint_setup(NRF_PPI, 18, (uint32_t)&(NRF_RADIO->EVENTS_RXREADY), - (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx])); -#else - nrf_ppi_channel_endpoint_setup(NRF_PPI, 18, (uint32_t)&(NRF_RADIO->EVENTS_READY), - (uint32_t)&(NRF_GPIOTE->TASKS_SET[idx])); -#endif - nrf_ppi_channel_endpoint_setup(NRF_PPI, 19, (uint32_t)&(NRF_RADIO->EVENTS_DISABLED), - (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx])); - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk); - - /* CH[4] and CH[5] are always on for wfr */ - nrf_ppi_fork_endpoint_setup(NRF_PPI, 4, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx])); - nrf_ppi_fork_endpoint_setup(NRF_PPI, 5, (uint32_t)&(NRF_GPIOTE->TASKS_CLR[idx])); -#endif + if (NRF_CCM->EVENTS_ENDKSGEN) { + while (tx_buf[0] == 0xff); + tx_buf[0] = g_ble_phy_data.phy_headerbyte; + NRF_CCM->INTENCLR = CCM_INTENCLR_ENDKSGEN_Msk; + } } +#endif /** * ble phy init @@ -1506,22 +1555,43 @@ ble_phy_init(void) { int rc; - g_ble_phy_gpiote_idx = 8; - /* Default phy to use is 1M */ g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M; g_ble_phy_data.phy_tx_phy_mode = BLE_PHY_MODE_1M; g_ble_phy_data.phy_rx_phy_mode = BLE_PHY_MODE_1M; - g_ble_phy_data.rx_pwr_compensation = 0; - /* Set phy channel to an invalid channel so first set channel works */ g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS; +#if MYNEWT_VAL(BLE_PHY_VARIABLE_TIFS) + g_ble_phy_data.tifs = BLE_LL_IFS; +#endif + /* Toggle peripheral power to reset (just in case) */ nrf_radio_power_set(NRF_RADIO, false); nrf_radio_power_set(NRF_RADIO, true); +#ifdef NRF53_SERIES + /* Errata 158: load trim values after toggling power */ + for (uint32_t index = 0; index < 32ul && + NRF_FICR_NS->TRIMCNF[index].ADDR != 0xFFFFFFFFul; index++) { + if (((uint32_t)NRF_FICR_NS->TRIMCNF[index].ADDR & 0xFFFFF000ul) == (volatile uint32_t)NRF_RADIO_NS) { + *((volatile uint32_t *)NRF_FICR_NS->TRIMCNF[index].ADDR) = NRF_FICR_NS->TRIMCNF[index].DATA; + } + } + + *(volatile uint32_t *)(NRF_RADIO_NS_BASE + 0x774) = + (*(volatile uint32_t* )(NRF_RADIO_NS_BASE + 0x774) & 0xfffffffe) | 0x01000000; +#if NRF53_ERRATA_16_ENABLE_WORKAROUND + if (nrf53_errata_16()) { + /* [16] RADIO: POWER register is not functional */ + NRF_RADIO_NS->SUBSCRIBE_TXEN = 0; + NRF_RADIO_NS->SUBSCRIBE_RXEN = 0; + NRF_RADIO_NS->SUBSCRIBE_DISABLE = 0; + } +#endif +#endif + /* Disable all interrupts */ nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL); @@ -1552,14 +1622,17 @@ ble_phy_init(void) /* Configure IFS */ NRF_RADIO->TIFS = BLE_LL_IFS; - /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk); - #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) nrf_ccm_int_disable(NRF_CCM, 0xffffffff); NRF_CCM->SHORTS = CCM_SHORTS_ENDKSGEN_CRYPT_Msk; NRF_CCM->EVENTS_ERROR = 0; memset(g_nrf_encrypt_scratchpad, 0, sizeof(g_nrf_encrypt_scratchpad)); + +#if PHY_USE_HEADERMASK_WORKAROUND + NVIC_SetVector(CCM_AAR_IRQn, (uint32_t)ble_phy_ccm_isr); + NVIC_EnableIRQ(CCM_AAR_IRQn); + NRF_CCM->INTENCLR = CCM_INTENCLR_ENDKSGEN_Msk;; +#endif #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) @@ -1579,45 +1652,23 @@ ble_phy_init(void) NRF_TIMER0->MODE = 0; /* Timer mode */ NRF_TIMER0->PRESCALER = 4; /* gives us 1 MHz */ - /* - * PPI setup. - * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used - * to cancel the wait for response timer. - * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait - * for response timer. - */ - nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL4, - (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS), - (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3])); - nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL5, - (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]), - (uint32_t)&(NRF_RADIO->TASKS_DISABLE)); - -#if MYNEWT_VAL(BLE_LL_PA) || MYNEWT_VAL(BLE_LL_LNA) -#if PLNA_SINGLE_GPIO - plna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_PA_GPIO)); - NRF_PPI->CH[6].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_SET[plna_idx]); - NRF_PPI->CH[7].TEP = (uint32_t) &(NRF_GPIOTE->TASKS_CLR[plna_idx]); -#else -#if MYNEWT_VAL(BLE_LL_PA) - plna_pa_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_PA_GPIO)); - NRF_GPIOTE->TASKS_CLR[plna_pa_idx] = 1; -#endif -#if MYNEWT_VAL(BLE_LL_LNA) - plna_lna_idx = ble_phy_gpiote_configure(MYNEWT_VAL(BLE_LL_LNA_GPIO)); - NRF_GPIOTE->TASKS_CLR[plna_lna_idx] = 1; -#endif -#endif + phy_ppi_init(); - NRF_PPI->CH[6].EEP = (uint32_t)&(NRF_RADIO->EVENTS_READY); - NRF_PPI->CH[7].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED); - NRF_PPI->CHENCLR = PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk; +#if PHY_USE_DEBUG + phy_debug_init(); +#endif +#if PHY_USE_FEM + phy_fem_init(); #endif /* Set isr in vector table and enable interrupt */ #ifndef RIOT_VERSION +#ifdef FREERTOS + NVIC_SetPriority(RADIO_IRQn, 5); +#else NVIC_SetPriority(RADIO_IRQn, 0); #endif +#endif #if MYNEWT NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr); #else @@ -1637,8 +1688,6 @@ ble_phy_init(void) g_ble_phy_data.phy_stats_initialized = 1; } - ble_phy_dbg_time_setup(); - return 0; } @@ -1647,7 +1696,7 @@ ble_phy_init(void) * * @return int 0: success; BLE Phy error code otherwise */ -int +static int ble_phy_rx(void) { /* @@ -1678,48 +1727,53 @@ ble_phy_rx(void) /* Setup for rx */ ble_phy_rx_xcvr_setup(); - /* PPI to start radio automatically shall be set here */ - assert(NRF_PPI->CHEN & PPI_CHEN_CH21_Msk); - return 0; } #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) -/** - * Called to enable encryption at the PHY. Note that this state will persist - * in the PHY; in other words, if you call this function you have to call - * disable so that future PHY transmits/receives will not be encrypted. - * - * @param pkt_counter - * @param iv - * @param key - * @param is_master - */ void -ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key, - uint8_t is_master) +ble_phy_encrypt_enable(const uint8_t *key) { memcpy(g_nrf_ccm_data.key, key, 16); - g_nrf_ccm_data.pkt_counter = pkt_counter; - memcpy(g_nrf_ccm_data.iv, iv, 8); - g_nrf_ccm_data.dir_bit = is_master; g_ble_phy_data.phy_encrypted = 1; - /* Enable the module (AAR cannot be on while CCM on) */ NRF_AAR->ENABLE = AAR_ENABLE_ENABLE_Disabled; NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Enabled; +#ifdef NRF5340_XXAA + NRF_CCM->HEADERMASK = BLE_LL_PDU_HEADERMASK_DATA; +#endif +#if PHY_USE_HEADERMASK_WORKAROUND + g_ble_phy_data.phy_headermask = BLE_LL_PDU_HEADERMASK_DATA; +#endif } void -ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir) +ble_phy_encrypt_header_mask_set(uint8_t mask) { - g_nrf_ccm_data.pkt_counter = pkt_counter; - g_nrf_ccm_data.dir_bit = dir; +#ifdef NRF5340_XXAA + NRF_CCM->HEADERMASK = mask; +#endif +#if PHY_USE_HEADERMASK_WORKAROUND + g_ble_phy_data.phy_headermask = mask; +#endif +} + +void +ble_phy_encrypt_iv_set(const uint8_t *iv) +{ + memcpy(g_nrf_ccm_data.iv, iv, 8); +} + +void +ble_phy_encrypt_counter_set(uint64_t counter, uint8_t dir_bit) +{ + g_nrf_ccm_data.pkt_counter = counter; + g_nrf_ccm_data.dir_bit = dir_bit; } void ble_phy_encrypt_disable(void) { - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH25_Msk); + phy_ppi_radio_address_to_ccm_crypt_disable(); nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_STOP); NRF_CCM->EVENTS_ERROR = 0; NRF_CCM->ENABLE = CCM_ENABLE_ENABLE_Disabled; @@ -1766,7 +1820,7 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) /* XXX: This should not be necessary, but paranoia is good! */ /* Clear timer0 compare to RXEN since we are transmitting */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH21_Msk); + phy_ppi_timer0_compare0_to_radio_rxen_disable(); if (ble_phy_set_start_time(cputime, rem_usecs, true) != 0) { STATS_INC(ble_phy_stats, tx_late); @@ -1774,10 +1828,8 @@ ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs) rc = BLE_PHY_ERR_TX_LATE; } else { /* Enable PPI to automatically start TXEN */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk); + phy_ppi_timer0_compare0_to_radio_txen_enable(); rc = 0; - - ble_phy_plna_enable_pa(); } return rc; @@ -1810,7 +1862,7 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) /* XXX: This should not be necessary, but paranoia is good! */ /* Clear timer0 compare to TXEN since we are transmitting */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk); + phy_ppi_timer0_compare0_to_radio_txen_disable(); if (ble_phy_set_start_time(cputime, rem_usecs, false) != 0) { STATS_INC(ble_phy_stats, rx_late); @@ -1822,9 +1874,7 @@ ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs) } /* Enable PPI to automatically start RXEN */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk); - - ble_phy_plna_enable_lna(); + phy_ppi_timer0_compare0_to_radio_rxen_enable(); /* Start rx */ rc = ble_phy_rx(); @@ -1870,8 +1920,9 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) * paranoid, and if you are going to clear one, might as well clear them * all. */ - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | - PPI_CHEN_CH23_Msk | PPI_CHEN_CH25_Msk); + phy_ppi_wfr_disable(); + phy_ppi_radio_bcmatch_to_aar_start_disable(); + phy_ppi_radio_address_to_ccm_crypt_disable(); #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) if (g_ble_phy_data.phy_encrypted) { @@ -1907,6 +1958,15 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) /* Start key-stream generation and encryption (via short) */ if (g_ble_phy_data.phy_encrypted) { +#if PHY_USE_HEADERMASK_WORKAROUND + if (g_ble_phy_data.phy_headermask != BLE_LL_PDU_HEADERMASK_DATA) { + g_ble_phy_data.phy_headerbyte = dptr[0]; + dptr[0] &= g_ble_phy_data.phy_headermask; + g_ble_phy_tx_buf[0] = 0xffffffff; + NRF_CCM->EVENTS_ENDKSGEN = 0; + NRF_CCM->INTENSET = CCM_INTENSET_ENDKSGEN_Msk; + } +#endif nrf_ccm_task_trigger(NRF_CCM, NRF_CCM_TASK_KSGEN); } #endif @@ -1960,12 +2020,12 @@ ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans) * @return int 0: success; anything else is an error */ int -ble_phy_txpwr_set(int dbm) +ble_phy_tx_power_set(int dbm) { - /* "Rail" power level if outside supported range */ - dbm = ble_phy_txpower_round(dbm); + /* Get actual TX power supported by radio */ + dbm = phy_txpower_round(dbm); - NRF_RADIO->TXPOWER = dbm; + phy_txpower_set(dbm); g_ble_phy_data.phy_txpwr_dbm = dbm; return 0; @@ -1980,62 +2040,10 @@ ble_phy_txpwr_set(int dbm) * * @return int Rounded power in dBm */ -int ble_phy_txpower_round(int dbm) +int +ble_phy_tx_power_round(int dbm) { - /* "Rail" power level if outside supported range */ -#ifdef RADIO_TXPOWER_TXPOWER_Pos8dBm - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm; - } -#endif - -#ifdef RADIO_TXPOWER_TXPOWER_Pos7dBm - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm; - } -#endif - -#ifdef RADIO_TXPOWER_TXPOWER_Pos6dBm - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm; - } -#endif - -#ifdef RADIO_TXPOWER_TXPOWER_Pos5dBm - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm; - } -#endif - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm; - } - - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm; - } - - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; + return phy_txpower_round(dbm); } /** @@ -2055,9 +2063,21 @@ ble_phy_set_access_addr(uint32_t access_addr) g_ble_phy_data.phy_access_address = access_addr; +#if NRF52_ERRATA_102_ENABLE_WORKAROUND || \ + NRF52_ERRATA_106_ENABLE_WORKAROUND || \ + NRF52_ERRATA_107_ENABLE_WORKAROUND #ifndef BABBLESIM - ble_phy_apply_errata_102_106_107(); + if (nrf52_errata_102() || nrf52_errata_106() || nrf52_errata_107()) { + /* [102] RADIO: PAYLOAD/END events delayed or not triggered after ADDRESS + * [106] RADIO: Higher CRC error rates for some access addresses + * [107] RADIO: Immediate address match for access addresses containing MSBs 0x00 + */ + *(volatile uint32_t *)0x40001774 = + ((*(volatile uint32_t *)0x40001774) & 0xfffffffe) | 0x01000000; + } #endif +#endif + return 0; } @@ -2069,17 +2089,11 @@ ble_phy_set_access_addr(uint32_t access_addr) * @return int The current PHY transmit power, in dBm */ int -ble_phy_txpwr_get(void) +ble_phy_tx_power_get(void) { return g_ble_phy_data.phy_txpwr_dbm; } -void -ble_phy_set_rx_pwr_compensation(int8_t compensation) -{ - g_ble_phy_data.rx_pwr_compensation = compensation; -} - /** * ble phy setchan * @@ -2118,6 +2132,12 @@ ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit) return 0; } +uint8_t +ble_phy_chan_get(void) +{ + return g_ble_phy_data.phy_chan; +} + /** * Stop the timer used to count microseconds when using RTC for cputime */ @@ -2143,10 +2163,7 @@ ble_phy_disable_irq_and_ppi(void) nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_IRQ_MASK_ALL); NRF_RADIO->SHORTS = 0; nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE); - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | - PPI_CHEN_CH20_Msk | PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk | - PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk); - nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk); + phy_ppi_disable(); NVIC_ClearPendingIRQ(RADIO_IRQn); g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE; } @@ -2159,7 +2176,7 @@ ble_phy_restart_rx(void) ble_phy_set_start_now(); /* Enable PPI to automatically start RXEN */ - nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk); + phy_ppi_timer0_compare0_to_radio_rxen_enable(); ble_phy_rx(); } @@ -2176,8 +2193,18 @@ ble_phy_disable(void) { ble_phy_trace_void(BLE_PHY_TRACE_ID_DISABLE); +#if PHY_USE_HEADERMASK_WORKAROUND + NRF_CCM->INTENCLR = CCM_INTENCLR_ENDKSGEN_Msk; +#endif + ble_phy_stop_usec_timer(); ble_phy_disable_irq_and_ppi(); + + g_ble_phy_data.phy_transition_late = 0; + +#if PHY_USE_FEM + phy_fem_disable(); +#endif } /* Gets the current access address */ @@ -2268,8 +2295,13 @@ void ble_phy_disable_dtm(void) void ble_phy_rfclk_enable(void) { -#if MYNEWT || ARDUINO +#if MYNEWT || defined(RIOT_VERSION) || defined(ARDUINO) +#ifdef NRF52_SERIES nrf52_clock_hfxo_request(); +#endif +#ifdef NRF53_SERIES + nrf5340_net_clock_hfxo_request(); +#endif #else nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTART); #endif @@ -2278,11 +2310,23 @@ ble_phy_rfclk_enable(void) void ble_phy_rfclk_disable(void) { -#if MYNEWT || ARDUINO +#if MYNEWT || defined(RIOT_VERSION) || defined(ARDUINO) +#ifdef NRF52_SERIES nrf52_clock_hfxo_release(); +#endif +#ifdef NRF53_SERIES + nrf5340_net_clock_hfxo_release(); +#endif #else nrf_clock_task_trigger(NRF_CLOCK, NRF_CLOCK_TASK_HFCLKSTOP); #endif } -#endif +void +ble_phy_tifs_txtx_set(uint16_t usecs, uint8_t anchor) +{ + g_ble_phy_data.txtx_time_us = usecs; + g_ble_phy_data.txtx_time_anchor = anchor; +} + +#endif /* defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) */ diff --git a/src/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c b/src/nimble/nimble/drivers/nrf5x/src/ble_phy_trace.c similarity index 89% rename from src/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c rename to src/nimble/nimble/drivers/nrf5x/src/ble_phy_trace.c index 84dbf4de..c31efda4 100644 --- a/src/nimble/nimble/drivers/nrf52/src/ble_phy_trace.c +++ b/src/nimble/nimble/drivers/nrf5x/src/ble_phy_trace.c @@ -17,7 +17,7 @@ * under the License. */ -#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) +#if defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" @@ -44,4 +44,5 @@ ble_phy_trace_init(void) ble_phy_trace_module_send_desc); } #endif -#endif \ No newline at end of file + +#endif /* defined(ARDUINO_ARCH_NRF5) && (defined(NRF52_SERIES) || defined(NRF53_SERIES)) */ diff --git a/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy.c b/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy.c new file mode 100644 index 00000000..a2b04db9 --- /dev/null +++ b/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy.c @@ -0,0 +1,249 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) + +#include +#include +#include +#include "nimble/nimble/drivers/nrf5x/src/phy_priv.h" + +#if PHY_USE_DEBUG +void +phy_debug_init(void) +{ +#if PHY_USE_DEBUG_1 + phy_gpiote_configure(PHY_GPIOTE_DEBUG_1, + MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); + + nrf_ppi_channel_endpoint_setup(NRF_PPI, 17, + (uint32_t)&(NRF_RADIO->EVENTS_READY), + (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_DEBUG_1])); + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH17_Msk); + + /* CH[20] and PPI CH[21] are on to trigger TASKS_TXEN or TASKS_RXEN */ + nrf_ppi_fork_endpoint_setup(NRF_PPI, 20, + (uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_DEBUG_1])); + nrf_ppi_fork_endpoint_setup(NRF_PPI, 21, + (uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_DEBUG_1])); +#endif + +#if PHY_USE_DEBUG_2 + phy_gpiote_configure(PHY_GPIOTE_DEBUG_2, + MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); + + /* CH[26] and CH[27] are always on for EVENT_ADDRESS and EVENT_END */ + nrf_ppi_fork_endpoint_setup(NRF_PPI, 26, + (uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_DEBUG_2])); + nrf_ppi_fork_endpoint_setup(NRF_PPI, 27, + (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_DEBUG_2])); +#endif + +#if PHY_USE_DEBUG_3 + phy_gpiote_configure(PHY_GPIOTE_DEBUG_3, MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); + +#if NRF52840_XXAA + nrf_ppi_channel_endpoint_setup(NRF_PPI, 18, + (uint32_t)&(NRF_RADIO->EVENTS_RXREADY), + (uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_DEBUG_3])); +#else + nrf_ppi_channel_endpoint_setup(NRF_PPI, 18, + (uint32_t)&(NRF_RADIO->EVENTS_READY), + (uint32_t)&(NRF_GPIOTE->TASKS_SET[GIDX_DEBUG_3])); +#endif + nrf_ppi_channel_endpoint_setup(NRF_PPI, 19, + (uint32_t)&(NRF_RADIO->EVENTS_DISABLED), + (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_DEBUG_3])); + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH18_Msk | PPI_CHEN_CH19_Msk); + + /* CH[4] and CH[5] are always on for wfr */ + nrf_ppi_fork_endpoint_setup(NRF_PPI, 4, + (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_DEBUG_3])); + nrf_ppi_fork_endpoint_setup(NRF_PPI, 5, + (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_DEBUG_3])); +#endif +} +#endif /* PHY_USE_DEBUG */ + +#if PHY_USE_FEM +void +phy_fem_init(void) +{ +#if PHY_USE_FEM_SINGLE_GPIO +#if PHY_USE_FEM_PA + phy_gpiote_configure(PHY_GPIOTE_FEM, MYNEWT_VAL(BLE_FEM_PA_GPIO)); +#else + phy_gpiote_configure(PHY_GPIOTE_FEM, MYNEWT_VAL(BLE_FEM_LNA_GPIO)); +#endif + NRF_PPI->CH[6].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_FEM]); + NRF_PPI->CH[7].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM]); +#else +#if PHY_USE_FEM_PA + phy_gpiote_configure(PHY_GPIOTE_FEM_PA, MYNEWT_VAL(BLE_FEM_PA_GPIO)); + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_PA] = 1; +#endif +#if PHY_USE_FEM_LNA + phy_gpiote_configure(PHY_GPIOTE_FEM_LNA, MYNEWT_VAL(BLE_FEM_LNA_GPIO)); + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_LNA] = 1; +#endif +#endif /* PHY_USE_FEM_SINGLE_GPIO */ + + NRF_PPI->CH[6].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[2]); + NRF_PPI->CH[7].EEP = (uint32_t)&(NRF_RADIO->EVENTS_DISABLED); + + nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk); +} + +#if PHY_USE_FEM_PA +void +phy_fem_enable_pa(void) +{ + ble_fem_pa_enable(); + +#if !PHY_USE_FEM_SINGLE_GPIO + /* Switch FEM channels to control PA */ + NRF_PPI->CH[6].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_FEM_PA]); + NRF_PPI->CH[7].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_PA]); +#endif + + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk); +} +#endif + +#if PHY_USE_FEM_LNA +void +phy_fem_enable_lna(void) +{ + ble_fem_lna_enable(); + +#if !PHY_USE_FEM_SINGLE_GPIO + /* Switch FEM channels to control LNA */ + NRF_PPI->CH[6].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_SET[PHY_GPIOTE_FEM_LNA]); + NRF_PPI->CH[7].TEP = (uint32_t)&(NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_LNA]); +#endif + + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk); +} +#endif + +void +phy_fem_disable(void) +{ +#if PHY_USE_FEM_SINGLE_GPIO + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM] = 1; +#else +#if PHY_USE_FEM_PA + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_PA] = 1; +#endif +#if PHY_USE_FEM_LNA + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_LNA] = 1; +#endif +#endif +} +#endif /* PHY_USE_FEM */ + +void +phy_ppi_init(void) +{ + /* radio_address_to_timer0_capture1 */ + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH26_Msk); + /* radio_end_to_timer0_capture2 */ + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH27_Msk); + + /* + * PPI setup. + * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used + * to cancel the wait for response timer. + * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait + * for response timer. + */ + nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL4, + (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS), + (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3])); + nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_PPI_CHANNEL5, + (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]), + (uint32_t)&(NRF_RADIO->TASKS_DISABLE)); +} + +void +phy_txpower_set(int8_t dbm) +{ + NRF_RADIO->TXPOWER = dbm; +} + +int8_t +phy_txpower_round(int8_t dbm) +{ +/* "Rail" power level if outside supported range */ +#ifdef RADIO_TXPOWER_TXPOWER_Pos8dBm + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm; + } +#endif + +#ifdef RADIO_TXPOWER_TXPOWER_Pos7dBm + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm; + } +#endif + +#ifdef RADIO_TXPOWER_TXPOWER_Pos6dBm + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm; + } +#endif + +#ifdef RADIO_TXPOWER_TXPOWER_Pos5dBm + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm; + } +#endif + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + +#endif /* defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) */ diff --git a/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy_ppi.h b/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy_ppi.h new file mode 100644 index 00000000..3f9e931c --- /dev/null +++ b/src/nimble/nimble/drivers/nrf5x/src/nrf52/phy_ppi.h @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_PHY_PPI_ +#define H_PHY_PPI_ + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES) + +#include + +static inline void +phy_ppi_rtc0_compare0_to_timer0_start_enable(void) +{ + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH31_Msk); +} + +static inline void +phy_ppi_rtc0_compare0_to_timer0_start_disable(void) +{ + nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH31_Msk); +} + +static inline void +phy_ppi_timer0_compare0_to_radio_txen_enable(void) +{ + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH20_Msk); +} + +static inline void +phy_ppi_timer0_compare0_to_radio_txen_disable(void) +{ + nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH20_Msk); +} + +static inline void +phy_ppi_timer0_compare0_to_radio_rxen_enable(void) +{ + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH21_Msk); +} + +static inline void +phy_ppi_timer0_compare0_to_radio_rxen_disable(void) +{ + nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH21_Msk); +} + +static inline void +phy_ppi_radio_bcmatch_to_aar_start_enable(void) +{ + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH23_Msk); +} + +static inline void +phy_ppi_radio_bcmatch_to_aar_start_disable(void) +{ + nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH23_Msk); +} + +static inline void +phy_ppi_radio_address_to_ccm_crypt_enable(void) +{ + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH25_Msk); +} + +static inline void +phy_ppi_radio_address_to_ccm_crypt_disable(void) +{ + nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH25_Msk); +} + +static inline void +phy_ppi_wfr_enable(void) +{ + nrf_ppi_channels_enable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); +} + +static inline void +phy_ppi_wfr_disable(void) +{ + nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk); +} + +static inline void +phy_ppi_fem_disable(void) +{ + nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk); +} + +static inline void +phy_ppi_disable(void) +{ + nrf_ppi_channels_disable(NRF_PPI, PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | + PPI_CHEN_CH6_Msk | PPI_CHEN_CH7_Msk | + PPI_CHEN_CH20_Msk | PPI_CHEN_CH21_Msk | + PPI_CHEN_CH23_Msk | PPI_CHEN_CH25_Msk | + PPI_CHEN_CH31_Msk); +} + +#endif /* H_PHY_PPI_ */ +#endif /* ARDUINO_ARCH_NRF5 && NRF52_SERIES */ \ No newline at end of file diff --git a/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy.c b/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy.c new file mode 100644 index 00000000..016ebf29 --- /dev/null +++ b/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy.c @@ -0,0 +1,317 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF53) + +#include +#include +#include +#include "nimble/nimble/drivers/nrf5x/src/phy_priv.h" + +/* + * When the radio is operated on high voltage (see VREQCTRL - Voltage request + * control on page 62 for how to control voltage), the output power is increased + * by 3 dB. I.e. if the TXPOWER value is set to 0 dBm and high voltage is + * requested using VREQCTRL, the output power will be +3 + * */ +#define NRF_TXPOWER_VREQH 3 + +#if PHY_USE_DEBUG +void +phy_debug_init(void) +{ +#if PHY_USE_DEBUG_1 + phy_gpiote_configure(PHY_GPIOTE_DEBUG_1, + MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN)); + + NRF_RADIO->PUBLISH_READY = DPPI_CH_PUB(RADIO_EVENTS_READY); + NRF_DPPIC->CHENSET = DPPI_CH_MASK(RADIO_EVENTS_READY); + + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_DEBUG_1] = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); + NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_DEBUG_1] = DPPI_CH_SUB(RADIO_EVENTS_READY); +#endif + +#if PHY_USE_DEBUG_2 + phy_gpiote_configure(PHY_GPIOTE_DEBUG_2, + MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN)); + + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_DEBUG_2] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); + NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_DEBUG_2] = DPPI_CH_SUB(RADIO_EVENTS_END); +#endif + +#if PHY_USE_DEBUG_3 + phy_gpiote_configure(PHY_GPIOTE_DEBUG_3, MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN)); + + NRF_RADIO->PUBLISH_RXREADY = DPPI_CH_PUB(RADIO_EVENTS_READY); + NRF_RADIO->PUBLISH_DISABLED = DPPI_CH_PUB(RADIO_EVENTS_DISABLED); + NRF_DPPIC->CHENSET = DPPI_CH_MASK(RADIO_EVENTS_RXREADY) | + DPPI_CH_MASK(RADIO_EVENTS_DISABLED); + + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_DEBUG_3] = DPPI_CH_SUB(RADIO_EVENTS_RXREADY); + + /* TODO figure out how (if?) to subscribe task to multiple DPPI channels + * Currently only last one is working. Also using multiple GPIOTE for same + * PIN doesn't work... + */ + NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_DEBUG_3] = DPPI_CH_SUB(RADIO_EVENTS_DISABLED); + NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_DEBUG_3] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); + NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_DEBUG_3] = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_3); + +#endif +} +#endif /* PHY_USE_DEBUG */ + +#if PHY_USE_FEM +void +phy_fem_init() +{ + /* We can keep clear tasks subscribed and published channels always enabled, + * it's enough to just (un)subscribe set tasks when needed. + * TODO: check if this affects power consumption + */ + + NRF_TIMER0->PUBLISH_COMPARE[2] = DPPI_CH_PUB(TIMER0_EVENTS_COMPARE_2); + NRF_RADIO->PUBLISH_DISABLED = DPPI_CH_PUB(RADIO_EVENTS_DISABLED); + +#if PHY_USE_FEM_SINGLE_GPIO +#if PHY_USE_FEM_PA + phy_gpiote_configure(PHY_GPIOTE_FEM, MYNEWT_VAL(BLE_FEM_PA_GPIO)); +#else + phy_gpiote_configure(PHY_GPIOTE_FEM, MYNEWT_VAL(BLE_FEM_LNA_GPIO)); +#endif + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM] = + DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_2); + NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_FEM] = + DPPI_CH_SUB(RADIO_EVENTS_DISABLED); + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM] = 1; +#else +#if PHY_USE_FEM_PA + phy_gpiote_configure(PHY_GPIOTE_FEM_PA, MYNEWT_VAL(BLE_FEM_PA_GPIO)); + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_PA] = + DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_2); + NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_FEM_PA] = + DPPI_CH_SUB(RADIO_EVENTS_DISABLED); + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_PA] = 1; +#endif +#if PHY_USE_FEM_LNA + phy_gpiote_configure(PHY_GPIOTE_FEM_LNA, MYNEWT_VAL(BLE_FEM_LNA_GPIO)); + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_LNA] = + DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_2); + NRF_GPIOTE->SUBSCRIBE_CLR[PHY_GPIOTE_FEM_LNA] = + DPPI_CH_SUB(RADIO_EVENTS_DISABLED); + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_LNA] = 1; +#endif +#endif /* PHY_USE_FEM_SINGLE_GPIO */ + + NRF_DPPIC->CHENSET = DPPI_CH_MASK_FEM; +} + +#if PHY_USE_FEM_PA +void +phy_fem_enable_pa(void) +{ + ble_fem_pa_enable(); + +#if PHY_USE_FEM_SINGLE_GPIO + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM] = + DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_2); +#else + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_PA] = + DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_2); +#endif +} +#endif + +#if PHY_USE_FEM_LNA +void +phy_fem_enable_lna(void) +{ + ble_fem_lna_enable(); + +#if PHY_USE_FEM_SINGLE_GPIO + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM] = + DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_2); +#else + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_LNA] = + DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_2); +#endif +} +#endif + +void +phy_fem_disable(void) +{ +#if PHY_USE_FEM_SINGLE_GPIO + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM] = 1; +#else +#if PHY_USE_FEM_PA + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_PA] = 1; +#endif +#if PHY_USE_FEM_LNA + NRF_GPIOTE->TASKS_CLR[PHY_GPIOTE_FEM_LNA] = 1; +#endif +#endif +} +#endif /* PHY_USE_FEM */ + +void +phy_ppi_init(void) +{ + /* Publish events */ + NRF_TIMER0->PUBLISH_COMPARE[0] = DPPI_CH_PUB(TIMER0_EVENTS_COMPARE_0); + NRF_TIMER0->PUBLISH_COMPARE[3] = DPPI_CH_PUB(TIMER0_EVENTS_COMPARE_3); + NRF_RADIO->PUBLISH_END = DPPI_CH_PUB(RADIO_EVENTS_END); + NRF_RADIO->PUBLISH_BCMATCH = DPPI_CH_PUB(RADIO_EVENTS_BCMATCH); + NRF_RADIO->PUBLISH_ADDRESS = DPPI_CH_PUB(RADIO_EVENTS_ADDRESS); + NRF_RTC0->PUBLISH_COMPARE[0] = DPPI_CH_PUB(RTC0_EVENTS_COMPARE_0); + + /* Enable channels we publish on */ + NRF_DPPIC->CHENSET = DPPI_CH_ENABLE_ALL; + + /* radio_address_to_timer0_capture1 */ + NRF_TIMER0->SUBSCRIBE_CAPTURE[1] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); + /* radio_end_to_timer0_capture2 */ + NRF_TIMER0->SUBSCRIBE_CAPTURE[2] = DPPI_CH_SUB(RADIO_EVENTS_END); +} + +void +phy_txpower_set(int8_t dbm) +{ +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + switch (dbm) { + case ((int8_t)RADIO_TXPOWER_TXPOWER_0dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) + NRF_TXPOWER_VREQH: + NRF_VREQCTRL->VREGRADIO.VREQH = 1; + dbm -= NRF_TXPOWER_VREQH; + break; + default: + NRF_VREQCTRL->VREGRADIO.VREQH = 0; + break; + } +#endif + + NRF_RADIO->TXPOWER = dbm; +} + +int8_t +phy_txpower_round(int8_t dbm) +{ +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + /* +3 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_0dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_0dBm) + NRF_TXPOWER_VREQH; + } + + /* +2 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) + NRF_TXPOWER_VREQH; + } + + /* +1 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) + NRF_TXPOWER_VREQH; + } +#endif + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg3dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg3dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm; + } + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + /* -9 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) + NRF_TXPOWER_VREQH; + } +#endif + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + /* -13 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) + NRF_TXPOWER_VREQH; + } +#endif + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + /* -17 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) + NRF_TXPOWER_VREQH; + } +#endif + + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + /* -37 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) + NRF_TXPOWER_VREQH; + } +#endif + + return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + +#endif /* ARDUINO_ARCH_NRF5 && NRF53 */ + diff --git a/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy_ppi.h b/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy_ppi.h new file mode 100644 index 00000000..6412f327 --- /dev/null +++ b/src/nimble/nimble/drivers/nrf5x/src/nrf53/phy_ppi.h @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_PHY_PPI_ +#define H_PHY_PPI_ + +#define DPPI_CH_PUB(_ch) (((DPPI_CH_ ## _ch) & 0xff) | (1 << 31)) +#define DPPI_CH_SUB(_ch) (((DPPI_CH_ ## _ch) & 0xff) | (1 << 31)) +#define DPPI_CH_UNSUB(_ch) (((DPPI_CH_ ## _ch) & 0xff) | (0 << 31)) +#define DPPI_CH_MASK(_ch) (1 << (DPPI_CH_ ## _ch)) + +/* Channels 0..5 are always used. + * Channels 6 and 7 are used for PA/LNA (optionally). + * Channels 7..9 are used for GPIO debugging (optionally). + */ + +#define DPPI_CH_TIMER0_EVENTS_COMPARE_0 0 +#define DPPI_CH_TIMER0_EVENTS_COMPARE_3 1 +#define DPPI_CH_RADIO_EVENTS_END 2 +#define DPPI_CH_RADIO_EVENTS_BCMATCH 3 +#define DPPI_CH_RADIO_EVENTS_ADDRESS 4 +#define DPPI_CH_RTC0_EVENTS_COMPARE_0 5 +#define DPPI_CH_TIMER0_EVENTS_COMPARE_2 6 +#define DPPI_CH_RADIO_EVENTS_DISABLED 7 +#define DPPI_CH_RADIO_EVENTS_READY 8 +#define DPPI_CH_RADIO_EVENTS_RXREADY 9 + +#define DPPI_CH_ENABLE_ALL (DPPIC_CHEN_CH0_Msk | DPPIC_CHEN_CH1_Msk | \ + DPPIC_CHEN_CH2_Msk | DPPIC_CHEN_CH3_Msk | \ + DPPIC_CHEN_CH4_Msk | DPPIC_CHEN_CH5_Msk) + +#define DPPI_CH_MASK_FEM (DPPI_CH_MASK(TIMER0_EVENTS_COMPARE_2) | \ + DPPI_CH_MASK(RADIO_EVENTS_DISABLED)) + +static inline void +phy_ppi_rtc0_compare0_to_timer0_start_enable(void) +{ + NRF_TIMER0->SUBSCRIBE_START = DPPI_CH_SUB(RTC0_EVENTS_COMPARE_0); +} + +static inline void +phy_ppi_rtc0_compare0_to_timer0_start_disable(void) +{ + NRF_TIMER0->SUBSCRIBE_START = DPPI_CH_UNSUB(RTC0_EVENTS_COMPARE_0); + NRF_TIMER0->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); + NRF_RADIO->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); +} + +static inline void +phy_ppi_timer0_compare0_to_radio_txen_enable(void) +{ + NRF_RADIO->SUBSCRIBE_TXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); +} + +static inline void +phy_ppi_timer0_compare0_to_radio_txen_disable(void) +{ + NRF_RADIO->SUBSCRIBE_TXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); +} + +static inline void +phy_ppi_timer0_compare0_to_radio_rxen_enable(void) +{ + NRF_RADIO->SUBSCRIBE_RXEN = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_0); +} + +static inline void +phy_ppi_timer0_compare0_to_radio_rxen_disable(void) +{ + NRF_RADIO->SUBSCRIBE_RXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); +} + +static inline void +phy_ppi_radio_address_to_ccm_crypt_enable(void) +{ + NRF_CCM->SUBSCRIBE_CRYPT = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); +} + +static inline void +phy_ppi_radio_address_to_ccm_crypt_disable(void) +{ + NRF_CCM->SUBSCRIBE_CRYPT = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); +} + +static inline void +phy_ppi_radio_bcmatch_to_aar_start_enable(void) +{ + NRF_AAR->SUBSCRIBE_START = DPPI_CH_SUB(RADIO_EVENTS_BCMATCH); +} + +static inline void +phy_ppi_radio_bcmatch_to_aar_start_disable(void) +{ + NRF_AAR->SUBSCRIBE_START = DPPI_CH_UNSUB(RADIO_EVENTS_BCMATCH); +} + +static inline void +phy_ppi_wfr_enable(void) +{ + NRF_TIMER0->SUBSCRIBE_CAPTURE[3] = DPPI_CH_SUB(RADIO_EVENTS_ADDRESS); + NRF_RADIO->SUBSCRIBE_DISABLE = DPPI_CH_SUB(TIMER0_EVENTS_COMPARE_3); +} + +static inline void +phy_ppi_wfr_disable(void) +{ + NRF_TIMER0->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); + NRF_RADIO->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); +} + +static inline void +phy_ppi_fem_disable(void) +{ +#if PHY_USE_FEM_SINGLE_GPIO + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM] = + DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); +#else +#if PHY_USE_FEM_PA + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_PA] = + DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_2); +#endif +#if PHY_USE_FEM_LNA + NRF_GPIOTE->SUBSCRIBE_SET[PHY_GPIOTE_FEM_LNA] = + DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_2); +#endif +#endif +} + +static inline void +phy_ppi_disable(void) +{ + NRF_TIMER0->SUBSCRIBE_START = DPPI_CH_UNSUB(RTC0_EVENTS_COMPARE_0); + NRF_TIMER0->SUBSCRIBE_CAPTURE[3] = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); + NRF_RADIO->SUBSCRIBE_DISABLE = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_3); + NRF_RADIO->SUBSCRIBE_TXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); + NRF_RADIO->SUBSCRIBE_RXEN = DPPI_CH_UNSUB(TIMER0_EVENTS_COMPARE_0); + NRF_AAR->SUBSCRIBE_START = DPPI_CH_UNSUB(RADIO_EVENTS_BCMATCH); + NRF_CCM->SUBSCRIBE_CRYPT = DPPI_CH_UNSUB(RADIO_EVENTS_ADDRESS); + + phy_ppi_fem_disable(); +} + +#endif /* H_PHY_PPI_ */ \ No newline at end of file diff --git a/src/nimble/nimble/drivers/nrf5x/src/phy_priv.h b/src/nimble/nimble/drivers/nrf5x/src/phy_priv.h new file mode 100644 index 00000000..aac5e52f --- /dev/null +++ b/src/nimble/nimble/drivers/nrf5x/src/phy_priv.h @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_PHY_PRIV_ +#define H_PHY_PRIV_ + +#include +#include +#include + + +#if defined(NRF52840_XXAA) && MYNEWT_VAL(BLE_PHY_NRF52_HEADERMASK_WORKAROUND) +#define PHY_USE_HEADERMASK_WORKAROUND 1 +#endif + +#define PHY_USE_DEBUG_1 (MYNEWT_VAL(BLE_PHY_DBG_TIME_TXRXEN_READY_PIN) >= 0) +#define PHY_USE_DEBUG_2 (MYNEWT_VAL(BLE_PHY_DBG_TIME_ADDRESS_END_PIN) >= 0) +#define PHY_USE_DEBUG_3 (MYNEWT_VAL(BLE_PHY_DBG_TIME_WFR_PIN) >= 0) +#define PHY_USE_DEBUG (PHY_USE_DEBUG_1 || PHY_USE_DEBUG_2 || PHY_USE_DEBUG_3) + +#define PHY_USE_FEM_PA (MYNEWT_VAL(BLE_FEM_PA) != 0) +#define PHY_USE_FEM_LNA (MYNEWT_VAL(BLE_FEM_LNA) != 0) +#define PHY_USE_FEM (PHY_USE_FEM_PA || PHY_USE_FEM_LNA) +#define PHY_USE_FEM_SINGLE_GPIO \ + (PHY_USE_FEM && (!PHY_USE_FEM_PA || !PHY_USE_FEM_LNA || \ + (MYNEWT_VAL(BLE_FEM_PA_GPIO) == \ + MYNEWT_VAL(BLE_FEM_LNA_GPIO)))) + +/* GPIOTE indexes, start assigning from last one */ +#define PHY_GPIOTE_DEBUG_1 (8 - PHY_USE_DEBUG_1) +#define PHY_GPIOTE_DEBUG_2 (PHY_GPIOTE_DEBUG_1 - PHY_USE_DEBUG_2) +#define PHY_GPIOTE_DEBUG_3 (PHY_GPIOTE_DEBUG_2 - PHY_USE_DEBUG_3) +#if PHY_USE_FEM_SINGLE_GPIO +#define PHY_GPIOTE_FEM (PHY_GPIOTE_DEBUG_3 - PHY_USE_FEM) +#else +#define PHY_GPIOTE_FEM_PA (PHY_GPIOTE_DEBUG_3 - PHY_USE_FEM_PA) +#define PHY_GPIOTE_FEM_LNA (PHY_GPIOTE_FEM_PA - PHY_USE_FEM_LNA) +#endif + +static inline void +phy_gpiote_configure(int idx, int pin) +{ + nrf_gpio_cfg_output(pin); + nrf_gpiote_task_configure(NRF_GPIOTE, idx, pin, GPIOTE_CONFIG_POLARITY_None/*NRF_GPIOTE_POLARITY_NONE*/, + NRF_GPIOTE_INITIAL_VALUE_LOW); + nrf_gpiote_task_enable(NRF_GPIOTE, idx); +} + +#if PHY_USE_DEBUG +void phy_debug_init(void); +#endif + +#if PHY_USE_FEM +void phy_fem_init(void); +#if PHY_USE_FEM_PA +void phy_fem_enable_pa(void); +#endif +#if PHY_USE_FEM_LNA +void phy_fem_enable_lna(void); +#endif +void phy_fem_disable(void); +#endif + +void phy_ppi_init(void); + +#ifdef NRF52_SERIES +#include "nimble/nimble/drivers/nrf5x/src/nrf52/phy_ppi.h" +#endif + +void phy_txpower_set(int8_t dbm); +int8_t phy_txpower_round(int8_t dbm); + +#ifdef NRF52_SERIES +#include "nimble/nimble/drivers/nrf5x/src/nrf52/phy_ppi.h" +#endif +#ifdef NRF53_SERIES +#include "nimble/nimble/drivers/nrf5x/src/nrf52/phy_ppi.h" +#endif + +#endif /* H_PHY_PRIV_ */ diff --git a/src/nimble/nimble/host/include/host/ble_aes_ccm.h b/src/nimble/nimble/host/include/host/ble_aes_ccm.h index c2a3a738..a2d1eca2 100644 --- a/src/nimble/nimble/host/include/host/ble_aes_ccm.h +++ b/src/nimble/nimble/host/include/host/ble_aes_ccm.h @@ -9,10 +9,10 @@ #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/queue.h" -#include "ble_hs.h" +#include "nimble/nimble/host/include/host/ble_hs.h" #if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) -#include "mbedtls/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" #else #include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" #endif diff --git a/src/nimble/nimble/host/include/host/ble_att.h b/src/nimble/nimble/host/include/host/ble_att.h index 18817889..fb8f72a9 100644 --- a/src/nimble/nimble/host/include/host/ble_att.h +++ b/src/nimble/nimble/host/include/host/ble_att.h @@ -32,29 +32,82 @@ extern "C" { #endif +/** Chained memory buffer. */ struct os_mbuf; +/** + * @defgroup ble_att_uuids Attribute Protocol (ATT) UUIDs + * @{ + */ +/** UUID for a primary service. */ #define BLE_ATT_UUID_PRIMARY_SERVICE 0x2800 + +/** UUID for a secondary service. */ #define BLE_ATT_UUID_SECONDARY_SERVICE 0x2801 + +/** UUID for an include definition. */ #define BLE_ATT_UUID_INCLUDE 0x2802 + +/** UUID for a characteristic. */ #define BLE_ATT_UUID_CHARACTERISTIC 0x2803 +/** @} */ + +/** + * @defgroup ble_att_err_codes Attribute Protocol (ATT) Error Codes + * @{ + */ + +/** The attribute handle given was not valid on this server */ #define BLE_ATT_ERR_INVALID_HANDLE 0x01 + +/** The attribute cannot be read. */ #define BLE_ATT_ERR_READ_NOT_PERMITTED 0x02 + +/** The attribute cannot be written. */ #define BLE_ATT_ERR_WRITE_NOT_PERMITTED 0x03 + +/** The attribute PDU was invalid. */ #define BLE_ATT_ERR_INVALID_PDU 0x04 + +/** The attribute requires authentication before it can be read or written. */ #define BLE_ATT_ERR_INSUFFICIENT_AUTHEN 0x05 + +/** ATT Server does not support the request received from the client. */ #define BLE_ATT_ERR_REQ_NOT_SUPPORTED 0x06 + +/** Offset specified was past the end of the attribute. */ #define BLE_ATT_ERR_INVALID_OFFSET 0x07 + +/** The attribute requires authorization before it can be read or written. */ #define BLE_ATT_ERR_INSUFFICIENT_AUTHOR 0x08 + +/** Too many prepare writes have been queued. */ #define BLE_ATT_ERR_PREPARE_QUEUE_FULL 0x09 + +/** No attribute found within the given attribute handle range. */ #define BLE_ATT_ERR_ATTR_NOT_FOUND 0x0a + +/** The attribute cannot be read using the ATT_READ_BLOB_REQ PDU. */ #define BLE_ATT_ERR_ATTR_NOT_LONG 0x0b + +/** The Encryption Key Size used for encrypting this link is too short. */ #define BLE_ATT_ERR_INSUFFICIENT_KEY_SZ 0x0c + +/** The attribute value length is invalid for the operation. */ #define BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN 0x0d + +/** The attribute request that was requested has encountered an error that was unlikely, + * and therefore could not be completed as requested. */ #define BLE_ATT_ERR_UNLIKELY 0x0e + +/** The attribute requires encryption before it can be read or written */ #define BLE_ATT_ERR_INSUFFICIENT_ENC 0x0f + +/** The attribute type is not a supported grouping attribute as defined by a higher layer specification. */ #define BLE_ATT_ERR_UNSUPPORTED_GROUP 0x10 + +/**Insufficient Resources to complete the request. */ #define BLE_ATT_ERR_INSUFFICIENT_RES 0x11 #define BLE_ATT_ERR_DB_OUT_OF_SYNC 0x12 #define BLE_ATT_ERR_VALUE_NOT_ALLOWED 0x13 @@ -69,27 +122,71 @@ struct os_mbuf; /** Error Response. */ #define BLE_ATT_OP_ERROR_RSP 0x01 + +/** MTU Request. */ #define BLE_ATT_OP_MTU_REQ 0x02 + +/** MTU Response. */ #define BLE_ATT_OP_MTU_RSP 0x03 + +/** Find Information Request. */ #define BLE_ATT_OP_FIND_INFO_REQ 0x04 + +/** Find Information Response. */ #define BLE_ATT_OP_FIND_INFO_RSP 0x05 + +/** Find By Type Value Request. */ #define BLE_ATT_OP_FIND_TYPE_VALUE_REQ 0x06 + +/** Find By Type Value Response. */ #define BLE_ATT_OP_FIND_TYPE_VALUE_RSP 0x07 + +/** Read By Type Request. */ #define BLE_ATT_OP_READ_TYPE_REQ 0x08 + +/** Read By Type Response. */ #define BLE_ATT_OP_READ_TYPE_RSP 0x09 + +/** Read Request. */ #define BLE_ATT_OP_READ_REQ 0x0a + +/** Read Response. */ #define BLE_ATT_OP_READ_RSP 0x0b + +/** Read Blob Request. */ #define BLE_ATT_OP_READ_BLOB_REQ 0x0c + +/** Read Blob Response. */ #define BLE_ATT_OP_READ_BLOB_RSP 0x0d + +/** Read Multiple Request. */ #define BLE_ATT_OP_READ_MULT_REQ 0x0e + +/** Read Multiple Response. */ #define BLE_ATT_OP_READ_MULT_RSP 0x0f + +/** Read By Group Type Request. */ #define BLE_ATT_OP_READ_GROUP_TYPE_REQ 0x10 + +/** Read By Group Type Response. */ #define BLE_ATT_OP_READ_GROUP_TYPE_RSP 0x11 + +/** Write Request. */ #define BLE_ATT_OP_WRITE_REQ 0x12 + +/** Write Response. */ #define BLE_ATT_OP_WRITE_RSP 0x13 + +/** Prepare Write Request. */ #define BLE_ATT_OP_PREP_WRITE_REQ 0x16 + +/** Prepare Write Response. */ #define BLE_ATT_OP_PREP_WRITE_RSP 0x17 + +/** Execute Write Request. */ #define BLE_ATT_OP_EXEC_WRITE_REQ 0x18 + +/** Execute Write Response. */ #define BLE_ATT_OP_EXEC_WRITE_RSP 0x19 /** Read Multiple Variable Lenght Request */ @@ -98,28 +195,76 @@ struct os_mbuf; /** Read Multiple Variable Lenght Response */ #define BLE_ATT_OP_READ_MULT_VAR_RSP 0x21 +/** Notify Request. */ #define BLE_ATT_OP_NOTIFY_REQ 0x1b + +/** Indicate Request. */ #define BLE_ATT_OP_INDICATE_REQ 0x1d + +/** Indicate Response. */ #define BLE_ATT_OP_INDICATE_RSP 0x1e + +/** Multiple Handle Value Length Notification Request */ +#define BLE_ATT_OP_NOTIFY_MULTI_REQ 0x23 + +/** Write Command. */ #define BLE_ATT_OP_WRITE_CMD 0x52 + +/** Signed Write Command */ #define BLE_ATT_OP_SIGNED_WRITE_CMD 0xD2 +/** @} */ + +/** Maximum length of an Attribute Protocol (ATT) attribute. */ #define BLE_ATT_ATTR_MAX_LEN 512 +/** + * @defgroup ble_att_flags Attribute Protocol (ATT) Flags + * @{ + */ + +/** Read permission flag. */ #define BLE_ATT_F_READ 0x01 + +/** Write permission flag. */ #define BLE_ATT_F_WRITE 0x02 + +/** Read encrypted permission flag. */ #define BLE_ATT_F_READ_ENC 0x04 + +/** Read authenticated permission flag. */ #define BLE_ATT_F_READ_AUTHEN 0x08 + +/** Read authorized permission flag. */ #define BLE_ATT_F_READ_AUTHOR 0x10 + +/** Write encrypted permission flag. */ #define BLE_ATT_F_WRITE_ENC 0x20 + +/** Write authenticated permission flag. */ #define BLE_ATT_F_WRITE_AUTHEN 0x40 + +/** Write authorized permission flag. */ #define BLE_ATT_F_WRITE_AUTHOR 0x80 +/** Read and write permission flag. */ #define HA_FLAG_PERM_RW (BLE_ATT_F_READ | BLE_ATT_F_WRITE) +/** @} */ + +/** + * @defgroup ble_att_access_op_codes Attribute Protocol (ATT) Access Operation Codes + * @{ + */ + +/** Access operation: Read. */ #define BLE_ATT_ACCESS_OP_READ 1 + +/** Access operation: Write. */ #define BLE_ATT_ACCESS_OP_WRITE 2 +/** @} */ + /** Default ATT MTU. Also the minimum. */ #define BLE_ATT_MTU_DFLT 23 @@ -202,6 +347,9 @@ uint16_t ble_att_preferred_mtu(void); */ int ble_att_set_preferred_mtu(uint16_t mtu); +int ble_att_set_default_bearer_using_cid(uint16_t conn_handle, uint16_t cid); +uint16_t ble_att_get_default_bearer_cid(uint16_t conn_handle); + #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/host/include/host/ble_dtm.h b/src/nimble/nimble/host/include/host/ble_dtm.h new file mode 100644 index 00000000..cd01a23b --- /dev/null +++ b/src/nimble/nimble/host/include/host/ble_dtm.h @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef H_BLE_DTM_ +#define H_BLE_DTM_ + +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file ble_dtm.h + * + * @brief DTM (Direct Test Mode) + * + * This header file provides the interface and data structures for working with + * the Direct Test Mode (DTM) functionality in a BLE (Bluetooth Low Energy) host. + * DTM allows for testing and validation of the BLE radio performance by enabling + * custom transmission and reception of data packets. + * + * @defgroup bt_host_dtm Bluetooth Host Direct Test Mode + * @ingroup bt_host + * @{ + */ + +/** + * @struct ble_dtm_rx_params + * @brief Parameters for DTM RX test. + * + * This structure represents the parameters for a Direct Test Mode (DTM) receiver test. + */ +struct ble_dtm_rx_params { + /** The channel to use for the RX test. */ + uint8_t channel; + + /** The PHY to use for the RX test. */ + uint8_t phy; + + /** The modulation index to use for the RX test. */ + uint8_t modulation_index; +}; + +/** + * @brief Start a Direct Test Mode (DTM) receiver test. + * + * This function starts a DTM RX test with the provided parameters. + * + * @param params The parameters for the DTM RX test. + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_dtm_rx_start(const struct ble_dtm_rx_params *params); + +/** + * @struct ble_dtm_tx_params + * @brief Parameters for DTM TX test. + * + * This structure represents the parameters for a Direct Test Mode (DTM) transmitter test. + */ +struct ble_dtm_tx_params { + /** The channel to use for the TX test. */ + uint8_t channel; + + /** The length of the data for the TX test. */ + uint8_t test_data_len; + + /** The payload to use for the TX test. */ + uint8_t payload; + + /** The PHY to use for the TX test. */ + uint8_t phy; +}; + +/** + * @brief Start a Direct Test Mode (DTM) transmitter test. + * + * This function starts a DTM TX test with the provided parameters. + * + * @param params The parameters for the DTM TX test. + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_dtm_tx_start(const struct ble_dtm_tx_params *params); + +/** + * @brief Stops a Direct Test Mode (DTM) test and retrieves the number of transmitted packets. + * + * This function sends a command to the Bluetooth controller to stop the currently running DTM test. + * It retrieves the number of packets transmitted during the test and stores it in the provided `num_packets` variable. + * + * @param num_packets Pointer to a `uint16_t` variable to store the number of transmitted packets. + * If an error occurs, the value will be set to 0. + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_dtm_stop(uint16_t *num_packets); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif diff --git a/src/nimble/nimble/host/include/host/ble_ead.h b/src/nimble/nimble/host/include/host/ble_ead.h index 135224b6..74539f7f 100644 --- a/src/nimble/nimble/host/include/host/ble_ead.h +++ b/src/nimble/nimble/host/include/host/ble_ead.h @@ -11,6 +11,7 @@ #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/nimble/host/include/host/ble_gap.h" + #ifdef __cplusplus extern "C" { #endif @@ -120,8 +121,6 @@ int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], const uint8_t iv[BLE_EAD_IV_SIZE], const uint8_t *encrypted_payload, size_t encrypted_payload_size, uint8_t *payload); -int ble_ead_serialize_data(const struct enc_adv_data *input, uint8_t *output); - #endif /* ENC_ADV_DATA */ #ifdef __cplusplus diff --git a/src/nimble/nimble/host/include/host/ble_esp_gap.h b/src/nimble/nimble/host/include/host/ble_esp_gap.h index 10fd59b3..c94d81eb 100644 --- a/src/nimble/nimble/host/include/host/ble_esp_gap.h +++ b/src/nimble/nimble/host/include/host/ble_esp_gap.h @@ -30,6 +30,21 @@ typedef enum gap_status gap_status_t; #define BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROV_SRV_ADV 3 #define BLE_DUPLICATE_SCAN_EXCEPTIONAL_INFO_MESH_PROXY_SRV_ADV 4 +#define ESP_BLE_VENDOR_LEGACY_SCAN_REQ_EVT_MASK BIT(0) +#define ESP_BLE_VENDOR_CHAN_MAP_UPDATE_CMPL_EVT_MASK BIT(1) +#define ESP_BLE_VENDOR_TL_RUNNING_STATUS_EVT_MASK BIT(2) +#define ESP_BLE_VENDOR_SLEEP_WAKEUP_EVT_MASK BIT(3) +#define ESP_BLE_VENDOR_CONNECT_IND_REQ_EVT_MASK BIT(4) +#define ESP_BLE_VENDOR_AUX_CONNECT_RSP_EVT_MASK BIT(5) + +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) +#ifdef CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT +#define MAX_REATTEMPT_ALLOWED CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT +#else +#define MAX_REATTEMPT_ALLOWED 0 +#endif +#endif + /** * Configure LE Data Length in controller (OGF = 0x08, OCF = 0x0022). * @@ -88,6 +103,15 @@ int ble_hs_hci_util_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, uint16_ */ int ble_gap_wl_tx_rmv(const ble_addr_t *addrs); +/** + * Adds the address in controller's white list. + * + * @param addrs The entry to be added in the white list. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_wl_tx_add(const ble_addr_t *addrs); + /** * Clears all addresses from controller's white list. * @@ -125,12 +149,12 @@ int ble_gap_get_local_used_addr(ble_addr_t *addr); * This API is called to get ADV data for a specific type. * - * @param adv_data Pointer of ADV data (unsigned 8 bit integer) which to be resolved. + * @param adv_data Pointer of ADV data which to be resolved. * @param adv_type Finding ADV data type. * @param adv_data_len Total length of Advertising data. * @param length Return the length of ADV data not including type. * - * @return Pointer (unsigned 8 bit integer) of type specific ADV data. + * @return Pointer of type specific ADV data. */ uint8_t* ble_resolve_adv_data(const uint8_t *adv_data, uint8_t adv_type, uint8_t adv_data_len , uint8_t * length); @@ -257,6 +281,20 @@ int ble_gap_set_chan_select(uint8_t select); int ble_gap_dev_authorization(uint16_t conn_handle, bool authorized); +/** + * Sets the vendor-specific event mask for BLE host. + * + * This function configures the vendor-specific event mask, enabling or disabling + * specific vendor-defined events from being reported by the controller. + * + * @param event_mask Bitmask representing the events to enable. + * + * @return 0 on success; + * A nonzero value indicating an error if the command fails. + */ +int +ble_hs_send_vs_event_mask(uint32_t event_mask); + void ble_gap_rx_test_evt(const void *buf, uint8_t len); void ble_gap_tx_test_evt(const void *buf, uint8_t len); void ble_gap_end_test_evt(const void *buf, uint8_t len); diff --git a/src/nimble/nimble/host/include/host/ble_gap.h b/src/nimble/nimble/host/include/host/ble_gap.h index 8af8c949..31e43228 100644 --- a/src/nimble/nimble/host/include/host/ble_gap.h +++ b/src/nimble/nimble/host/include/host/ble_gap.h @@ -28,13 +28,13 @@ */ #include -#include "ble_hs.h" -#include "ble_hs_adv.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "nimble/nimble/host/include/host/ble_hs_adv.h" #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "ble_esp_gap.h" +#include "nimble/nimble/host/include/host/ble_esp_gap.h" #if MYNEWT_VAL(ENC_ADV_DATA) -#include "../../src/ble_hs_hci_priv.h" +#include "nimble/nimble/host/src/ble_hs_hci_priv.h" #endif #ifdef __cplusplus @@ -153,12 +153,24 @@ struct hci_conn_update; #define BLE_GAP_EVENT_PERIODIC_TRANSFER 24 #define BLE_GAP_EVENT_PATHLOSS_THRESHOLD 25 #define BLE_GAP_EVENT_TRANSMIT_POWER 26 -#define BLE_GAP_EVENT_SUBRATE_CHANGE 27 -#define BLE_GAP_EVENT_VS_HCI 28 -#define BLE_GAP_EVENT_REATTEMPT_COUNT 29 -#define BLE_GAP_EVENT_AUTHORIZE 30 -#define BLE_GAP_EVENT_TEST_UPDATE 31 -#define BLE_GAP_EVENT_DATA_LEN_CHG 32 +#define BLE_GAP_EVENT_PARING_COMPLETE 27 +#define BLE_GAP_EVENT_SUBRATE_CHANGE 28 +#define BLE_GAP_EVENT_VS_HCI 29 +#define BLE_GAP_EVENT_BIGINFO_REPORT 30 +#define BLE_GAP_EVENT_REATTEMPT_COUNT 31 +#define BLE_GAP_EVENT_AUTHORIZE 32 +#define BLE_GAP_EVENT_TEST_UPDATE 33 +#define BLE_GAP_EVENT_DATA_LEN_CHG 34 +#define BLE_GAP_EVENT_CONNLESS_IQ_REPORT 35 +#define BLE_GAP_EVENT_CONN_IQ_REPORT 36 +#define BLE_GAP_EVENT_CTE_REQ_FAILED 37 + +//TODO : Deprecate the EVENT_LINK_ESTAB going ahead +#define BLE_GAP_EVENT_LINK_ESTAB 38 +#define BLE_GAP_EVENT_EATT 39 +#define BLE_GAP_EVENT_PER_SUBEV_DATA_REQ 40 +#define BLE_GAP_EVENT_PER_SUBEV_RESP 41 +#define BLE_GAP_EVENT_PERIODIC_TRANSFER_V2 42 /* DTM events */ #define BLE_GAP_DTM_TX_START_EVT 0 @@ -216,6 +228,18 @@ struct ble_gap_sec_state { unsigned authorize:1; }; +/** Read Remote Version parameters **/ +struct ble_gap_read_rem_ver_params { + /** Version of the Current LMP **/ + uint8_t version; + + /** Company Identifier **/ + uint16_t manufacturer; + + /** Revision of the LMP **/ + uint16_t subversion; +}; + /** Advertising parameters */ struct ble_gap_adv_params { /** Advertising mode. Can be one of following constants: @@ -502,6 +526,66 @@ struct ble_gap_repeat_pairing { uint8_t new_bonding:1; }; + +#define BLE_GAP_PER_ADV_DATA_STATUS_COMPLETE 0x00 +#define BLE_GAP_PER_ADV_DATA_STATUS_INCOMPLETE 0x01 +#define BLE_GAP_PER_ADV_DATA_STATUS_TRUNCATED 0x02 +#define BLE_GAP_PER_ADV_DATA_STATUS_RX_FAILED 0xFF + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +struct ble_gap_periodic_adv_response { + /** The subevent in which the response is received */ + uint8_t subevent; + + /** Status of the subevent indication. + * + * 0 if subevent indication was transmitted. + * 1 if subevent indication was not transmitted. + * All other values RFU. + */ + + /** The adv handle of the adv */ + uint8_t adv_handle; + + uint8_t tx_status; + + /** The TX power of the response in dBm */ + int8_t tx_power; + + /** The RSSI of the response in dBm */ + int8_t rssi; + + /** The Constant Tone Extension (CTE) of the advertisement */ + uint8_t cte_type; + + /** The response slot */ + uint8_t response_slot; + + /** Data status */ + uint8_t data_status; + + /** Data length */ + uint8_t data_length; + + /** response data */ + const uint8_t *data; +}; + +struct ble_gap_periodic_adv_response_params { + /** The periodic advertsing event for which response shall be sent in */ + uint16_t request_event; + + /** The request subevent for which response shall be sent in */ + uint8_t request_subevent; + + /** The subevent the response shall be sent in */ + uint8_t response_subevent; + + /** The response slot the response shall be sent in */ + uint8_t response_slot; +}; +#endif + /** * Represents a GAP-related event. When such an event occurs, the host * notifies the application by passing an instance of this structure to an @@ -535,8 +619,63 @@ struct ble_gap_event { /** The handle of the relevant connection. */ uint16_t conn_handle; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /* + * Adv_Handle is used to identify an advertising set. + * If the connection is established from periodic advertising with responses + * and Role is 0x00 then the Advertising_Handle parameter shall be set + * according to the periodic advertising train the connection was established from + */ + uint8_t adv_handle; + + /* + * Sync_Handle identifying the periodic advertising train + * If the connection is established from periodic advertising with responses + * and Role is 0x01, then the Sync_Handle parameter shall be set according + * to the periodic advertising train the connection was established from + */ + uint16_t sync_handle; +#endif } connect; + /** + * Represents a successful Link establishment attempt. Sometimes, in noisy environment, + * even if BLE_GAP_EVENT_CONNECT is posted, the link syncronization procedure may fail + * and link gets disconnected with reason 0x3E. Application can wait for below event to ensure + * the link syncronization is completed. Valid for the following event + * types: + * o BLE_GAP_EVENT_LINK_ESTAB + */ + + struct { + /** + * The final status of the link establishment; + * o 0: the connection was successfully established. + * o BLE host error code: the connection attempt failed for + * the specified reason. + */ + int status; + + /** The handle of the relevant connection. */ + uint16_t conn_handle; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /* + * Adv_Handle is used to identify an advertising set. + * If the connection is established from periodic advertising with responses + * and Role is 0x00 then the Advertising_Handle parameter shall be set + * according to the periodic advertising train the connection was established from + */ + uint8_t adv_handle; + /* + * Sync_Handle identifying the periodic advertising train + * If the connection is established from periodic advertising with responses + * and Role is 0x01, then the Sync_Handle parameter shall be set according + * to the periodic advertising train the connection was established from + */ + uint16_t sync_handle; +#endif + } link_estab; + /** * Represents a terminated connection. Valid for the following event * types: @@ -850,6 +989,8 @@ struct ble_gap_event { struct { /** The handle of the relevant connection. */ uint16_t conn_handle; + /** Peer identity address */ + ble_addr_t peer_id_addr; } identity_resolved; /** @@ -917,6 +1058,18 @@ struct ble_gap_event { /** Advertiser clock accuracy */ uint8_t adv_clk_accuracy; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /** Number of subevents. If zero, the periodic advertiser will be a broadcaster, + * without responses. + */ + uint8_t num_subevents; + /** Interval between subevents (N * 1.25 ms) */ + uint8_t subevent_interval; + /** Time between the advertising packet and the first response slot (N * 1.25 ms). */ + uint8_t response_slot_delay; + /** Time between response slots (N * 0.125 ms) */ + uint8_t response_slot_spacing; +#endif } periodic_sync; /** @@ -934,10 +1087,24 @@ struct ble_gap_event { /** Received signal strength indication in dBm (127 if unavailable) */ int8_t rssi; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /** + * It indicates the periodic advertising event counter (paEventCounter) of + * the event that the periodic advertising packet was received in. + */ + uint16_t event_counter; + /** + * It indicates Periodic Advertising with Responses subevent in which + * the periodic advertising packet was received in. + */ + uint8_t subevent; +#endif + /** Advertising data status, can be one of following constants: * - BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE * - BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE * - BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED + * - BLE_HCI_PERIODIC_DATA_STATUS_RX_FAILED */ uint8_t data_status; @@ -1019,9 +1186,69 @@ struct ble_gap_event { /** Advertiser clock accuracy */ uint8_t adv_clk_accuracy; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /** Number of subevents. If zero, the periodic advertiser will be a broadcaster,- + * without responses. + */ + uint8_t num_subevents; + /** Interval between subevents (N * 1.25 ms) */ + uint8_t subevent_interval; + /** Time between the advertising packet and the first response slot (N * 1.25 ms). */ + uint8_t response_slot_delay; + /** Time between response slots (N * 0.125 ms) */ + uint8_t response_slot_spacing; +#endif } periodic_transfer; #endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) + /** + * Represents a periodic advertising sync transfer received. Valid for + * the following event types: + * o BLE_GAP_EVENT_BIGINFO_REPORT + */ + struct { + /** Synchronization handle */ + uint16_t sync_handle; + + /** Number of present BISes */ + uint8_t bis_cnt; + + /** Number of SubEvents */ + uint8_t nse; + + /** ISO Interval */ + uint16_t iso_interval; + + /** Burst Number */ + uint8_t bn; + + /** Pre-Transmission Offset */ + uint8_t pto; + + /** Immediate Repetition Count */ + uint8_t irc; + + /** Maximum PDU size */ + uint16_t max_pdu; + + /** Maximum SDU size */ + uint16_t max_sdu; + + /** Service Data Unit Interval */ + uint32_t sdu_interval; + + /** BIG PHY */ + uint8_t phy; + + /** Framing of BIS Data PDUs */ + uint8_t framing : 1; + + /** Encryption */ + uint8_t encryption : 1; + } biginfo_report; +#endif + #if MYNEWT_VAL(BLE_POWER_CONTROL) /** * Represents a change in either local transmit power or remote transmit @@ -1069,6 +1296,24 @@ struct ble_gap_event { int8_t delta; } transmit_power; #endif + /** + * Represents a received Pairing Complete message + * + * Valid for the following event types: + * o BLE_GAP_EVENT_PARING_COMPLETE + */ + struct { + /** + * Indicates the result of the encryption state change attempt; + * o 0: the encrypted state was successfully updated; + * o BLE host error code: the encryption state change attempt + * failed for the specified reason. + */ + int status; + + /** The handle of the relevant connection. */ + uint16_t conn_handle; + } pairing_complete; #if MYNEWT_VAL(BLE_CONN_SUBRATING) /** @@ -1097,6 +1342,30 @@ struct ble_gap_event { uint16_t supervision_tmo; } subrate_change; #endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /** + * Represents a periodic advertising subevent data request + * with parameters valid for the following event types: + * o BLE_GAP_EVENT_PER_SUBEV_DATA_REQ + */ + struct { + /** Advertising handle */ + uint8_t adv_handle; + + /** Subevent start */ + uint8_t subevent_start; + + /** Number of subevents */ + uint8_t subevent_data_count; + } periodic_adv_subev_data_req; + + /** + * Represents a periodic advertising response + * with parameters valid for the following event types: + * o BLE_GAP_EVENT_PER_SUBEV_RESP + */ + struct ble_gap_periodic_adv_response periodic_adv_response; +#endif #if MYNEWT_VAL(BLE_HCI_VS) /** @@ -1136,6 +1405,31 @@ struct ble_gap_event { int out_response; } authorize; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + /** + * EATT Event + * + * Valid for the following event types: + * o BLE_GAP_EVENT_EATT + * + */ + struct { + /* Connection Handle */ + uint16_t conn_handle; + + /** Connected Status + * + * EATT Connected: 0 + * EATT Disconnected: 1 + */ + uint8_t status; + + /* CID of the bearer */ + uint16_t cid; + + } eatt; +#endif + #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) /** * Represents a event mentioning connection reattempt @@ -1176,7 +1470,6 @@ struct ble_gap_event { */ uint16_t num_pkt; } dtm_state; - /** * Represent an event for LE Data length change * @@ -1199,6 +1492,161 @@ struct ble_gap_event { /* Max Rx Time */ uint16_t max_rx_time; } data_len_chg; +#if MYNEWT_VAL(BLE_AOA_AOD) + /** + * Represents a AOA/AOD connectionless iq report event + * Valid for the following event types: + * o BLE_GAP_EVENT_CONNLESS_IQ_RPT + */ + struct { + /** Sync_Handle identifying the periodic advertising train. + * Range: 0x0000 to 0x0EFF + * 0x0FFF indicates Receiver Test mode. + */ + uint16_t sync_handle; + + /** The index of the channel on which the packet was received. + * Range: 0x00 to 0x27 + * Note: 0x25 to 0x27 can be used only for packets generated during test modes. + */ + uint8_t channel_index; + + /** RSSI of the packet. + * Range: -1270 to +200 (Units: 0.1 dBm). + */ + int16_t rssi; + + /** Antenna ID used for receiving the packet. */ + uint8_t rssi_antenna_id; + + /** Type of Constant Tone Extension (CTE). + * 0x00: AoA Constant Tone Extension + * 0x01: AoD Constant Tone Extension with 1 μs slots + * 0x02: AoD Constant Tone Extension with 2 μs slots + */ + uint8_t cte_type; + + /** Switching and sampling slot durations. + * 0x01: Switching and sampling slots are 1 μs each + * 0x02: Switching and sampling slots are 2 μs each + */ + uint8_t slot_durations; + + /** Status of the packet. + * 0x00: CRC was correct + * 0x01: CRC was incorrect, but Length and CTETime fields were used to determine sampling points + * 0x02: CRC was incorrect, but the Controller determined the position and length of the CTE in another way + * 0xFF: Insufficient resources to sample (Channel_Index, CTE_Type, and Slot_Durations invalid) + */ + uint8_t packet_status; + + /** Value of paEventCounter for the reported AUX_SYNC_IND PDU. */ + uint16_t periodic_event_counter; + + /** Total number of sample pairs (I and Q samples). + * 0x00: No samples provided (only permitted if Packet_Status is 0xFF) + * 0x09 to 0x52: Total number of sample pairs + */ + uint8_t sample_count; + + /** Array of I samples for the reported packet (signed integers). + * Each value represents an I sample at a specific sampling point. + * 0x80 indicates no valid sample available. + */ + int8_t *i_samples; + + /** Array of Q samples for the reported packet (signed integers). + * Each value represents a Q sample at a specific sampling point. + * 0x80 indicates no valid sample available. + */ + int8_t *q_samples; + } connless_iq_report; + + /** + * Represents a connection iq report. + * Valid for the following event types: + * o BLE_GAP_EVENT_CONN_IQ_RPT + */ + struct { + /** Connection handle identifying the connection. */ + uint16_t conn_handle; + + /** PHY used for receiving the packet. + * 0x01: LE 1M PHY + * 0x02: LE 2M PHY + */ + uint8_t rx_phy; + + /** The index of the data channel on which the packet was received. */ + uint8_t data_channel_index; + + /** RSSI of the packet. + * Range: -1270 to +200 (Units: 0.1 dBm). + */ + int16_t rssi; + + /** Antenna ID used for receiving the packet. */ + uint8_t rssi_antenna_id; + + /** Type of Constant Tone Extension (CTE). + * 0x00: AoA Constant Tone Extension + * 0x01: AoD Constant Tone Extension with 1 μs slots + * 0x02: AoD Constant Tone Extension with 2 μs slots + */ + uint8_t cte_type; + + /** Switching and sampling slot durations. + * 0x01: Switching and sampling slots are 1 μs each + * 0x02: Switching and sampling slots are 2 μs each + */ + uint8_t slot_durations; + + /** Status of the packet. + * 0x00: CRC was correct + * 0x01: CRC was incorrect, but Length and CTETime fields were used to determine sampling points + * 0x02: CRC was incorrect, but the Controller determined the position and length of the CTE in another way + * 0xFF: Insufficient resources to sample (Channel_Index, CTE_Type, and Slot_Durations invalid) + */ + uint8_t packet_status; + + /** Value of the connection event counter for the reported packet. */ + uint16_t conn_event_counter; + + /** Total number of sample pairs (I and Q samples). + * 0x00: No samples provided (only permitted if Packet_Status is 0xFF) + * 0x09 to 0x52: Total number of sample pairs + */ + uint8_t sample_count; + + /** Array of I samples for the reported packet (signed integers). + * Each value represents an I sample at a specific sampling point. + * 0x80 indicates no valid sample available. + */ + int8_t *i_samples; + + /** Array of Q samples for the reported packet (signed integers). + * Each value represents a Q sample at a specific sampling point. + * 0x80 indicates no valid sample available. + */ + int8_t *q_samples; + } conn_iq_report; + + /** + * Represents a cte req failed event + * Valid for the following event types: + * o BLE_GAP_EVENT_CTE_REQ_FAILED + */ + struct { + /** Status indicating the reason for failure. + * Refer to HCI error codes for detailed status values. + */ + uint8_t status; + + /** Connection handle identifying the connection. */ + uint16_t conn_handle; + } cte_req_fail; + +#endif }; }; @@ -1219,29 +1667,29 @@ struct ble_gap_multi_conn_params { /** The duration of the discovery procedure. */ int32_t duration_ms; - /** - * Additional arguments specifying the particulars of the connect procedure. When extended - * adv is disabled or BLE_GAP_LE_PHY_1M_MASK is set in phy_mask this parameter can't be + /** + * Additional arguments specifying the particulars of the connect procedure. When extended + * adv is disabled or BLE_GAP_LE_PHY_1M_MASK is set in phy_mask this parameter can't be * specified to null. */ const struct ble_gap_conn_params *phy_1m_conn_params; #if MYNEWT_VAL(BLE_EXT_ADV) - /** + /** * Additional arguments specifying the particulars of the connect procedure. When * BLE_GAP_LE_PHY_2M_MASK is set in phy_mask this parameter can't be specified to null. */ const struct ble_gap_conn_params *phy_2m_conn_params; - - /** + + /** * Additional arguments specifying the particulars of the connect procedure. When * BLE_GAP_LE_PHY_CODED_MASK is set in phy_mask this parameter can't be specified to null. */ const struct ble_gap_conn_params *phy_coded_conn_params; #endif // MYNEWT_VAL(BLE_EXT_ADV) - /** - * The minimum length occupied by this connection in scheduler. 0 means disable the + /** + * The minimum length occupied by this connection in scheduler. 0 means disable the * optimization for this connection. */ uint32_t scheduling_len_us; @@ -1249,6 +1697,7 @@ struct ble_gap_multi_conn_params { #endif // MYNEWT_VAL(OPTIMIZE_MULTI_CONN) typedef int ble_gap_event_fn(struct ble_gap_event *event, void *arg); +typedef int ble_gap_conn_foreach_handle_fn(uint16_t conn_handle, void *arg); #define BLE_GAP_CONN_MODE_NON 0 #define BLE_GAP_CONN_MODE_DIR 1 @@ -1534,6 +1983,12 @@ struct ble_gap_ext_adv_params { /** Advertising Set ID */ uint8_t sid; + + /** Primary PHY options */ + uint8_t primary_phy_opt; + + /** Secondary PHY options */ + uint8_t secondary_phy_opt; }; /** @@ -1656,7 +2111,7 @@ int ble_gap_ext_adv_active(uint8_t instance); /** @brief Periodic advertising parameters */ struct ble_gap_periodic_adv_params { /** If include TX power in advertising PDU */ - unsigned int include_tx_power:1; + unsigned int include_tx_power : 1; /** Minimum advertising interval in 1.25ms units, if 0 stack use sane * defaults @@ -1667,6 +2122,34 @@ struct ble_gap_periodic_adv_params { * defaults */ uint16_t itvl_max; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + /** Number of subevents + * If zero, the periodic advertiser will be a broadcaster, without responses. + */ + uint8_t num_subevents; + + /** Interval between subevents (N * 1.25 ms) + * Shall be between 7.5ms and 318.75 ms. + */ + uint8_t subevent_interval; + + /** Time between the advertising packet in a subevent and the + * first response slot (N * 1.25 ms) + * + */ + uint8_t response_slot_delay; + + /** Time between response slots (N * 0.125 ms) + * Shall be between 0.25 and 31.875 ms. + */ + uint8_t response_slot_spacing; + + /** Number of subevent response slots + * If zero, response_slot_delay and response_slot_spacing are ignored. + */ + uint8_t num_response_slots; +#endif /* PERIODIC_ADV_WITH_RESPONSES */ }; #if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) @@ -1708,7 +2191,107 @@ struct ble_gap_periodic_sync_params { created */ unsigned int filter_duplicates:1; #endif +#if MYNEWT_VAL(BLE_AOA_AOD) + /** + * Specifies the type of Constant Tone Extension (CTE) to which the receiver should not synchronize. + * This parameter determines which types of packets with specific CTE configurations are ignored during synchronization. + * + * Possible values: + * 0: Do not sync to packets with an AoA Constant Tone Extension. + * 1: Do not sync to packets with an AoD Constant Tone Extension with 1 μs slots. + * 2: Do not sync to packets with an AoD Constant Tone Extension with 2 μs slots. + * 3: Do not sync to packets with a type 3 Constant Tone Extension (currently reserved for future use). + * 4: Do not sync to packets without a Constant Tone Extension. + */ + uint8_t sync_cte_type; +#endif +}; + + +#if MYNEWT_VAL(BLE_AOA_AOD) +#define BLE_GAP_CTE_TYPE_AOA 0x0 +#define BLE_GAP_CTE_TYPE_AOD_1US 0x1 +#define BLE_GAP_CTE_TYPE_AOD_2US 0x2 + +#define BLE_GAP_CTE_RSP_ALLOW_AOA_MASK BLE_HCI_CTE_RSP_ALLOW_AOA_MASK +#define BLE_GAP_CTE_RSP_ALLOW_AOD_1US_MASK BLE_HCI_CTE_RSP_ALLOW_AOD_1US_MASK +#define BLE_GAP_CTE_RSP_ALLOW_AOD_2US_MASK BLE_HCI_CTE_RSP_ALLOW_AOD_2US_MASK + + +/** @brief Periodic advertising parameters */ +struct ble_gap_periodic_adv_cte_params { + /** + * Constant Tone Extension length in 8 µs units (Range: 0x02 to 0x14) + */ + uint8_t cte_length; + + /** + * Constant Tone Extension type + * 0x00 : AoA Constant Tone Extension + * 0x01 : AoD Constant Tone Extension with 1 µs slots + * 0x02 : AoD Constant Tone Extension with 2 µs slots + */ + uint8_t cte_type; + + /** + * The number of Constant Tone Extensions to transmit in each periodic + * advertising interval (Range: 0x01 to 0x10) + */ + uint8_t cte_count; + + /** + * The number of Antenna IDs in the pattern + * (Range: 0x02 to 0x4B) + */ + uint8_t switching_pattern_length; + + /** + * Antenna ID in the pattern. + * there is a pattern pointer + */ + uint8_t* antenna_ids; + +}; + +struct ble_gap_cte_sampling_params { + /** + * The sampling rate used by the Controller + * 0x01 : Switching and sampling slots are 1 μs each + * 0x02 : Switching and sampling slots are 2 μs each + */ + uint8_t slot_durations; + + /** + * The number of Antenna IDs in the pattern + * (Range: 0x02 to 0x4B) + */ + uint8_t switching_pattern_length; + + /** + * Antenna ID in the pattern. + * there is a pattern pointer + */ + uint8_t* antenna_ids; + +}; + +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +struct ble_gap_set_periodic_adv_subev_data_params { + /** The subevent to set data for */ + uint8_t subevent; + + /** The first response slot to listen to */ + uint8_t response_slot_start; + + /** The number of response slots to listen to */ + uint8_t response_slot_count; + + /** The data to send */ + struct os_mbuf *data; }; +#endif /** * Configure periodic advertising for specified advertising instance @@ -1952,6 +2535,122 @@ int ble_gap_clear_periodic_adv_list(void); * @return 0 on success; nonzero on failure. */ int ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size); + + + +#if MYNEWT_VAL(BLE_AOA_AOD) + +/** + * Set connectionless Constant Tone Extension (CTE) transmission parameters. + * + * @param instance Periodic advertising instance ID. + * @param params Pointer to the CTE transmission parameters. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_set_connless_cte_transmit_params(uint8_t instance, + const struct ble_gap_periodic_adv_cte_params *params); + +/** + * Enable or disable connectionless CTE transmission. + * + * @param instance Periodic advertising instance ID. + * @param cte_enable 0x00 to disable, 0x01 to enable CTE transmission. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_set_connless_cte_transmit_enable(uint8_t instance, uint8_t cte_enable); + +/** + * Enable or disable connectionless IQ sampling for periodic advertising. + * + * @param sync_handle Sync handle identifying the periodic advertiser. + * @param sampling_enable 0x00 to disable, 0x01 to enable IQ sampling. + * @param max_sampled_ctes Maximum number of sampled CTEs. + * @param cte_sampling_params Pointer to the CTE sampling parameters. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_set_connless_iq_sampling_enable(uint16_t sync_handle, uint8_t sampling_enable, + uint8_t max_sampled_ctes, + const struct ble_gap_cte_sampling_params *cte_sampling_params); + +/** + * Set connection CTE receive parameters. + * + * @param conn_handle Connection handle. + * @param sampling_enable 0x00 to disable, 0x01 to enable CTE sampling. + * @param cte_sampling_params Pointer to the CTE sampling parameters. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_set_conn_cte_recv_param(uint16_t conn_handle, uint8_t sampling_enable, + const struct ble_gap_cte_sampling_params *cte_sampling_params); + +/** + * Set connection CTE transmission parameters. + * + * @param conn_handle Connection handle. + * @param cte_types Bitfield specifying supported CTE types. + * @param switching_pattern_len Length of the antenna switching pattern. + * @param antenna_ids Pointer to the array of antenna IDs. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_set_conn_cte_transmit_param(uint16_t conn_handle, uint8_t cte_types, + uint8_t switching_pattern_len, const uint8_t *antenna_ids); + +/** + * Enable or disable connection CTE request. + * + * @param conn_handle Connection handle. + * @param enable 0x00 to disable, 0x01 to enable CTE request. + * @param cte_request_interval Interval between CTE requests in connection interval. + * @param requested_cte_length Requested CTE length in 8 µs units. + * @param requested_cte_type Requested CTE type. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_conn_cte_req_enable(uint16_t conn_handle, uint8_t enable, uint16_t cte_request_interval, + uint8_t requested_cte_length, uint8_t requested_cte_type); + +/** + * Enable or disable connection CTE response. + * + * @param conn_handle Connection handle. + * @param enable 0x00 to disable, 0x01 to enable CTE response. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_conn_cte_rsp_enable(uint16_t conn_handle, uint8_t enable); + +/** + * Read antenna information. + * + * @param switch_sampling_rates On success, stores the supported switching and sampling rates. + * @param num_antennae On success, stores the number of antennae. + * @param max_switch_pattern_len On success, stores the maximum switching pattern length. + * @param max_cte_len On success, stores the maximum CTE length. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gap_read_antenna_information(uint8_t *switch_sampling_rates, uint8_t *num_antennae, + uint8_t *max_switch_pattern_len, uint8_t *max_cte_len); + +#endif // MYNEWT_VAL(BLE_AOA_AOD) + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +int +ble_gap_set_periodic_adv_subev_data(uint8_t instance, uint8_t num_subevents, + const struct ble_gap_set_periodic_adv_subev_data_params *params); + +int ble_gap_periodic_adv_set_response_data(uint16_t sync_handle, + struct ble_gap_periodic_adv_response_params *param, + struct os_mbuf *data); + +int ble_gap_periodic_adv_sync_subev(uint16_t sync_handle, uint8_t include_tx_power, + uint8_t num_subevents, uint8_t *subevents); +#endif #endif @@ -2107,6 +2806,71 @@ int ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, const struct ble_gap_conn_params *params, ble_gap_event_fn *cb, void *cb_arg); +/** + * Initiates an Sync connect procedure for PAwR. + * + * @param own_addr_type The type of address the stack should use for + * itself during connection establishment. + * - BLE_OWN_ADDR_PUBLIC + * - BLE_OWN_ADDR_RANDOM + * - BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT + * - BLE_OWN_ADDR_RPA_RANDOM_DEFAULT + * @param advertising_handle The advertising_Handle identifying the periodic advertising train + * Range: 0x00 to 0xEF or 0xFF + * @param subevent The Subevent parameter is used to identify the subevent where a connection + request shall be initiated from a periodic advertising train. + The Advertising_Handle and Subevent parameters + shall be set to 0xFF if these + parameters are not used. + * @param peer_addr The address of the peer to connect to. + * If this parameter is NULL, the white list + * is used. + * @param duration_ms The duration of the discovery procedure. + * On expiration, the procedure ends and a + * BLE_GAP_EVENT_DISC_COMPLETE event is + * reported. Units are milliseconds. + * @param phy_mask Define on which PHYs connection attempt should + * be done + * @param phy_1m_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_1M_MASK is set in phy_mask + * this parameter can be specify to null for + * default values. + * @param phy_2m_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_2M_MASK is set in phy_mask + * this parameter can be specify to null for + * default values. + * @param phy_coded_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_CODED_MASK is set in + * phy_mask this parameter can be specify to + * null for default values. + * @param cb The callback to associate with this connect + * procedure. When the connect procedure + * completes, the result is reported through + * this callback. If the connect procedure + * succeeds, the connection inherits this + * callback as its event-reporting mechanism. + * @param cb_arg The optional argument to pass to the callback + * function. + * + * @return 0 on success; + * BLE_HS_EALREADY if a connection attempt is + * already in progress; + * BLE_HS_EBUSY if initiating a connection is not + * possible because scanning is in progress; + * BLE_HS_EDONE if the specified peer is already + * connected; + * Other nonzero on error. + */ +int ble_gap_connect_with_synced(uint8_t own_addr_type, uint8_t advertising_handle, + uint8_t subevent, const ble_addr_t *peer_addr, + int32_t duration_ms, uint8_t phy_mask, + const struct ble_gap_conn_params *phy_1m_conn_params, + const struct ble_gap_conn_params *phy_2m_conn_params, + const struct ble_gap_conn_params *phy_coded_conn_params, + ble_gap_event_fn *cb, void *cb_arg); /** * Initiates an extended connect procedure. * @@ -2168,11 +2932,11 @@ int ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, #if MYNEWT_VAL(OPTIMIZE_MULTI_CONN) /** * @brief Enable the optimization of multiple connections. - * + * * @param enable Enable or disable the optimization. * @param common_factor The greatest common factor of all intervals in 0.625ms units. - * @return 0 on success; - * + * @return 0 on success; + * */ int ble_gap_common_factor_set(bool enable, uint32_t common_factor); @@ -2189,7 +2953,7 @@ int ble_gap_common_factor_set(bool enable, uint32_t common_factor); * callback as its event-reporting mechanism. * @param cb_arg The optional argument to pass to the callback * function. - * + * * @return 0 on success; * BLE_HS_EALREADY if a connection attempt is * already in progress; @@ -2199,7 +2963,7 @@ int ble_gap_common_factor_set(bool enable, uint32_t common_factor); * connected; * Other nonzero on error. */ -int ble_gap_multi_connect(struct ble_gap_multi_conn_params *multi_conn_params, +int ble_gap_multi_connect(struct ble_gap_multi_conn_params *multi_conn_params, ble_gap_event_fn *cb, void *cb_arg); #endif @@ -2271,17 +3035,57 @@ int ble_gap_update_params(uint16_t conn_handle, * Configure LE Data Length in controller (OGF = 0x08, OCF = 0x0022). * * @param conn_handle Connection handle. - * @param tx_octets The preferred value of payload octets that the Controller - * should use for a new connection (Range - * 0x001B-0x00FB). - * @param tx_time The preferred maximum number of microseconds that the local Controller - * should use to transmit a single link layer packet - * (Range 0x0148-0x4290). + * @param tx_octets The preferred value of payload octets that the + * Controller should use for a new connection + * (Range 0x001B-0x00FB). + * @param tx_time The preferred maximum number of microseconds that + * the local Controller should use to transmit a single + * link layer packet (Range 0x0148-0x4290). * * @return 0 on success, * other error code on failure. */ -int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time); +int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, + uint16_t tx_time); + +/** + * Read LE Suggested Default Data Length in controller + * (OGF = 0x08, OCF = 0x0024). + * + * @param out_sugg_max_tx_octets The Host's suggested value for the + * Controller's maximum transmitted number of + * payload octets in LL Data PDUs to be used + * for new connections. (Range 0x001B-0x00FB). + * @param out_sugg_max_tx_time The Host's suggested value for the + * Controller's maximum packet transmission + * time for packets containing LL Data PDUs to + * be used for new connections. + * (Range 0x0148-0x4290). + * + * @return 0 on success, + * other error code on failure. + */ +int ble_gap_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets, + uint16_t *out_sugg_max_tx_time); + +/** + * Configure LE Suggested Default Data Length in controller + * (OGF = 0x08, OCF = 0x0024). + * + * @param sugg_max_tx_octets The Host's suggested value for the Controller's + * maximum transmitted number of payload octets in + * LL Data PDUs to be used for new connections. + * (Range 0x001B-0x00FB). + * @param sugg_max_tx_time The Host's suggested value for the Controller's + * maximum packet transmission time for packets + * containing LL Data PDUs to be used for new + * connections. (Range 0x0148-0x4290). + * + * @return 0 on success, + * other error code on failure. + */ +int ble_gap_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, + uint16_t sugg_max_tx_time); /** * Read LE Suggested Default Data Length in controller (OGF = 0x08, OCF = 0x0024). @@ -2557,8 +3361,8 @@ int ble_gap_set_default_subrate(uint16_t subrate_min, uint16_t subrate_max, uint int ble_gap_subrate_req(uint16_t conn_handle, uint16_t subrate_min, uint16_t subrate_max, - uint16_t max_latency, uint16_t cont_num, - uint16_t supervision_timeout); + uint16_t max_latency, uint16_t cont_num, + uint16_t supervision_timeout); #endif /** * Event listener structure @@ -2751,6 +3555,35 @@ int ble_gap_dtm_enh_tx_start(uint8_t tx_chan, uint8_t test_data_len, uint8_t pay */ int ble_gap_dtm_enh_rx_start(uint8_t rx_chan, uint8_t index, uint8_t phy); +/** + * Set Read Remote Version Information is used to retrieve the version, manufacturer, + * and subversion information of remote controller after connection established + * + * @param conn_handle Connection handle + * @param version Defines the specification version of the LE Controller + * @param manufacturer Indicates the manufacturer of the remote Controller + * @param subversion Manufacturer specific version + + * @return 0 on success; nonzero on failure +*/ + +int ble_gap_read_rem_ver_info(uint16_t conn_handle, uint8_t *version, uint16_t *manufacturer, uint16_t *subversion); + +/** + * Read local resolvable address command + * + * @param peer_addr_type Peer Identity Address type + * + * @param peer_addr Peer Identity Address + * + * @param out_addr Local Resolvable Address received from controller. + * + * @return 0 on success; nonzero on failure + */ + +int ble_gap_rd_local_resolv_addr(uint8_t peer_addr_type, const ble_addr_t *peer_addr, + uint8_t *out_addr); + #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/host/include/host/ble_gatt.h b/src/nimble/nimble/host/include/host/ble_gatt.h index 99c52f00..e73d361e 100644 --- a/src/nimble/nimble/host/include/host/ble_gatt.h +++ b/src/nimble/nimble/host/include/host/ble_gatt.h @@ -28,9 +28,10 @@ */ #include -#include "ble_att.h" -#include "ble_uuid.h" -#include "ble_esp_gatt.h" +#include "nimble/nimble/include/nimble/ble.h" +#include "nimble/nimble/host/include/host/ble_att.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "nimble/nimble/host/include/host/ble_esp_gatt.h" #include "nimble/porting/nimble/include/syscfg/syscfg.h" #ifdef __cplusplus extern "C" { @@ -40,50 +41,155 @@ struct ble_hs_conn; struct ble_att_error_rsp; struct ble_hs_cfg; +/** + * @defgroup ble_gatt_register_op_codes Generic Attribute Profile (GATT) Registration Operation Codes + * @{ + */ + +/** GATT Service registration. */ #define BLE_GATT_REGISTER_OP_SVC 1 + +/** GATT Characteristic registration. */ #define BLE_GATT_REGISTER_OP_CHR 2 + +/** GATT Descriptor registration. */ #define BLE_GATT_REGISTER_OP_DSC 3 +/** @} */ + +/** + * @defgroup ble_gatt_uuid Generic Attribute Profile (GATT) Service and Descriptor UUIDs + * @{ + */ + +/** GATT service 16-bit UUID. */ #define BLE_GATT_SVC_UUID16 0x1801 + +/** GATT Client Characteristic Configuration descriptor 16-bit UUID. */ #define BLE_GATT_DSC_CLT_CFG_UUID16 0x2902 #define BLE_GATT_DSC_CLT_PRE_FMT16 0x2904 #define BLE_GATT_DSC_CLT_AGG_FMT16 0x2905 +/** @} */ + +/** + * @defgroup ble_gatt_chr_properties Generic Attribute Profile (GATT) Characteristic Properties + * @{ + */ + +/** Characteristic property: Broadcast. */ #define BLE_GATT_CHR_PROP_BROADCAST 0x01 + +/** Characteristic property: Read. */ #define BLE_GATT_CHR_PROP_READ 0x02 + +/** Characteristic property: Write Without Response. */ #define BLE_GATT_CHR_PROP_WRITE_NO_RSP 0x04 + +/** Characteristic property: Write. */ #define BLE_GATT_CHR_PROP_WRITE 0x08 + +/** Characteristic property: Notify. */ #define BLE_GATT_CHR_PROP_NOTIFY 0x10 + +/** Characteristic property: Indicate. */ #define BLE_GATT_CHR_PROP_INDICATE 0x20 + +/** Characteristic property: Authenticated Signed Write. */ #define BLE_GATT_CHR_PROP_AUTH_SIGN_WRITE 0x40 + +/** Characteristic property: Extended Properties. */ #define BLE_GATT_CHR_PROP_EXTENDED 0x80 +/** @} */ + +/** @defgroup ble_gatt_access_op_codes Generic Attribute Profile (GATT) Access Operation Codes + * @{ + */ + +/** GATT attribute access operation: Read characteristic. */ #define BLE_GATT_ACCESS_OP_READ_CHR 0 + +/** GATT attribute access operation: Write characteristic. */ #define BLE_GATT_ACCESS_OP_WRITE_CHR 1 + +/** GATT attribute access operation: Read descriptor. */ #define BLE_GATT_ACCESS_OP_READ_DSC 2 + +/** GATT attribute access operation: Write descriptor. */ #define BLE_GATT_ACCESS_OP_WRITE_DSC 3 +/** @} */ + +/** + * @defgroup ble_gatt_chr_flags Generic Attribute Profile (GATT) Characteristic Flags + * @{ + */ + +/** GATT Characteristic Flag: Broadcast. */ #define BLE_GATT_CHR_F_BROADCAST 0x0001 + +/** GATT Characteristic Flag: Read. */ #define BLE_GATT_CHR_F_READ 0x0002 + +/** GATT Characteristic Flag: Write without Response. */ #define BLE_GATT_CHR_F_WRITE_NO_RSP 0x0004 + +/** GATT Characteristic Flag: Write. */ #define BLE_GATT_CHR_F_WRITE 0x0008 + +/** GATT Characteristic Flag: Notify. */ #define BLE_GATT_CHR_F_NOTIFY 0x0010 + +/** GATT Characteristic Flag: Indicate. */ #define BLE_GATT_CHR_F_INDICATE 0x0020 + +/** GATT Characteristic Flag: Authenticated Signed Writes. */ #define BLE_GATT_CHR_F_AUTH_SIGN_WRITE 0x0040 + +/** GATT Characteristic Flag: Reliable Writes. */ #define BLE_GATT_CHR_F_RELIABLE_WRITE 0x0080 + +/** GATT Characteristic Flag: Auxiliary Writes. */ #define BLE_GATT_CHR_F_AUX_WRITE 0x0100 + +/** GATT Characteristic Flag: Read Encrypted. */ #define BLE_GATT_CHR_F_READ_ENC 0x0200 + +/** GATT Characteristic Flag: Read Authenticated. */ #define BLE_GATT_CHR_F_READ_AUTHEN 0x0400 + +/** GATT Characteristic Flag: Read Authorized. */ #define BLE_GATT_CHR_F_READ_AUTHOR 0x0800 + +/** GATT Characteristic Flag: Write Encrypted. */ #define BLE_GATT_CHR_F_WRITE_ENC 0x1000 + +/** GATT Characteristic Flag: Write Authenticated. */ #define BLE_GATT_CHR_F_WRITE_AUTHEN 0x2000 + +/** GATT Characteristic Flag: Write Authorized. */ #define BLE_GATT_CHR_F_WRITE_AUTHOR 0x4000 + +/** @} */ + +/** + * @defgroup ble_gatt_service_types Generic Attribute Profile (GATT) Service Types + * @{ + */ + +/** GATT Service Type: End of Services. */ #define BLE_GATT_SVC_TYPE_END 0 + +/** GATT Service Type: Primary Service. */ #define BLE_GATT_SVC_TYPE_PRIMARY 1 + +/** GATT Service Type: Secondary Service. */ #define BLE_GATT_SVC_TYPE_SECONDARY 2 -/** +/** @} */ +/** * Client Presentation Format * GATT Format Types * Ref: Assigned Numbers Specification @@ -281,39 +387,83 @@ struct ble_hs_cfg; #define BLE_GATT_CHR_BT_SIG_DESC_INTERNAL 0x010F #define BLE_GATT_CHR_BT_SIG_DESC_EXTERNAL 0x0110 +/*** @server. */ +/** Represents one notification tuple in a multi notification PDU */ +struct ble_gatt_notif { + /** The attribute handle on which to notify. */ + uint16_t handle; + + /** The notification value. */ + struct os_mbuf * value; +}; + /*** @client. */ +/** Represents a GATT error. */ struct ble_gatt_error { + /** The GATT status code indicating the type of error. */ uint16_t status; + + /** The attribute handle associated with the error. */ uint16_t att_handle; }; +/** Represents a GATT Service. */ struct ble_gatt_svc { + /** The start handle of the GATT service. */ uint16_t start_handle; + + /** The end handle of the GATT service. */ uint16_t end_handle; + + /** The UUID of the GATT service. */ ble_uuid_any_t uuid; }; + +/** Represents a GATT attribute. */ struct ble_gatt_attr { + /** The handle of the GATT attribute. */ uint16_t handle; + + /** The offset of the data within the attribute. */ uint16_t offset; + + /** Pointer to the data buffer represented by an os_mbuf. */ struct os_mbuf *om; }; + +/** Represents a GATT characteristic. */ struct ble_gatt_chr { + /** The handle of the GATT characteristic definition. */ uint16_t def_handle; + + /** The handle of the GATT characteristic value. */ uint16_t val_handle; + + /** The properties of the GATT characteristic. */ uint8_t properties; + + /** The UUID of the GATT characteristic. */ ble_uuid_any_t uuid; }; + +/** Represents a GATT descriptor. */ struct ble_gatt_dsc { + /** The handle of the GATT descriptor. */ uint16_t handle; + + /** The UUID of the GATT descriptor. */ ble_uuid_any_t uuid; }; +/** Function prototype for the GATT MTU exchange callback. */ typedef int ble_gatt_mtu_fn(uint16_t conn_handle, const struct ble_gatt_error *error, uint16_t mtu, void *arg); + +/** Function prototype for the GATT service discovery callback. */ typedef int ble_gatt_disc_svc_fn(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, @@ -350,10 +500,12 @@ typedef int ble_gatt_reliable_attr_fn(uint16_t conn_handle, struct ble_gatt_attr *attrs, uint8_t num_attrs, void *arg); +/** Function prototype for the GATT characteristic callback. */ typedef int ble_gatt_chr_fn(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *chr, void *arg); +/** Function prototype for the GATT descriptor callback. */ typedef int ble_gatt_dsc_fn(uint16_t conn_handle, const struct ble_gatt_error *error, uint16_t chr_val_handle, @@ -393,7 +545,7 @@ int ble_gattc_disc_all_svcs(uint16_t conn_handle, * * @param conn_handle The connection over which to execute the * procedure. - * @param service_uuid128 The 128-bit UUID of the service to discover. + * @param uuid The 128-bit UUID of the service to discover. * @param cb The function to call to report procedure status * updates; null for no callback. * @param cb_arg The optional argument to pass to the callback @@ -453,7 +605,7 @@ int ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle, * the service definition handle). * @param end_handle The handle to end the search at (generally the * last handle in the service). - * @param chr_uuid128 The 128-bit UUID of the characteristic to + * @param uuid The 128-bit UUID of the characteristic to * discover. * @param cb The function to call to report procedure status * updates; null for no callback. @@ -471,9 +623,9 @@ int ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle, * * @param conn_handle The connection over which to execute the * procedure. - * @param chr_val_handle The handle of the characteristic value + * @param start_handle The handle of the characteristic value * attribute. - * @param chr_end_handle The last handle in the characteristic + * @param end_handle The last handle in the characteristic * definition. * @param cb The function to call to report procedure status * updates; null for no callback. @@ -511,6 +663,8 @@ int ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle, * handle of the service definition). * @param end_handle The last handle to search (generally the * last handle in the service definition). + * @param uuid The 128-bit UUID of the characteristic to + * read. * @param cb The function to call to report procedure status * updates; null for no callback. * @param cb_arg The optional argument to pass to the callback @@ -528,6 +682,8 @@ int ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle, * @param conn_handle The connection over which to execute the * procedure. * @param handle The handle of the characteristic value to read. + * @param offset The offset within the characteristic value to + * start reading. * @param cb The function to call to report procedure status * updates; null for no callback. * @param cb_arg The optional argument to pass to the callback @@ -568,7 +724,7 @@ int ble_gattc_read_mult_var(uint16_t conn_handle, const uint16_t *handles, * procedure. * @param attr_handle The handle of the characteristic value to write * to. - * @param txom The value to write to the characteristic. + * @param om The value to write to the characteristic. * * @return 0 on success; nonzero on failure. */ @@ -583,8 +739,8 @@ int ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle, * procedure. * @param attr_handle The handle of the characteristic value to write * to. - * @param value The value to write to the characteristic. - * @param value_len The number of bytes to write. + * @param data The value to write to the characteristic. + * @param data_len The number of bytes to write. * * @return 0 on success; nonzero on failure. */ @@ -614,7 +770,7 @@ int ble_gattc_signed_write(uint16_t conn_handle, uint16_t attr_handle, * procedure. * @param attr_handle The handle of the characteristic value to write * to. - * @param txom The value to write to the characteristic. + * @param om The value to write to the characteristic. * @param cb The function to call to report procedure status * updates; null for no callback. * @param cb_arg The optional argument to pass to the callback @@ -633,8 +789,8 @@ int ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, * procedure. * @param attr_handle The handle of the characteristic value to write * to. - * @param value The value to write to the characteristic. - * @param value_len The number of bytes to write. + * @param data The value to write to the characteristic. + * @param data_len The number of bytes to write. * @param cb The function to call to report procedure status * updates; null for no callback. * @param cb_arg The optional argument to pass to the callback @@ -654,7 +810,8 @@ int ble_gattc_write_flat(uint16_t conn_handle, uint16_t attr_handle, * procedure. * @param attr_handle The handle of the characteristic value to write * to. - * @param txom The value to write to the characteristic. + * @param offset The offset at which to begin writing the value. + * @param om The value to write to the characteristic. * @param cb The function to call to report procedure status * updates; null for no callback. * @param cb_arg The optional argument to pass to the callback @@ -696,15 +853,42 @@ int ble_gattc_write_reliable(uint16_t conn_handle, * * @param conn_handle The connection over which to execute the * procedure. - * @param chr_val_handle The attribute handle to indicate in the + * @param att_handle The attribute handle to indicate in the * outgoing notification. - * @param txom The value to write to the characteristic. + * @param om The value to write to the characteristic. * * @return 0 on success; nonzero on failure. */ int ble_gatts_notify_custom(uint16_t conn_handle, uint16_t att_handle, struct os_mbuf *om); +/** + * Sends a "free-form" multiple handle variable length characteristic + * notification. This function consumes supplied mbufs regardless of the + * outcome. Notifications are sent in order of supplied entries. + * Function tries to send minimum amount of PDUs. If PDU can't contain all + * of the characteristic values, multiple notifications are sent. If only one + * handle-value pair fits into PDU, or only one characteristic remains in the + * list, regular characteristic notification is sent. + * + * If GATT client doesn't support receiving multiple handle notifications, + * this will use GATT notification for each characteristic, separately. + * + * If value of characteristic is not specified it will be read from local + * GATT database. + * + * @param conn_handle The connection over which to execute the + * procedure. + * @param chr_count Number of characteristics to notify about. + * @param tuples Handle-value pairs in form of `ble_gatt_notif` + * structures. + * + * @return 0 on success; nonzero on failure. + */ +int ble_gatts_notify_multiple_custom(uint16_t conn_handle, + size_t chr_count, + struct ble_gatt_notif *tuples); + /** * Deprecated. Should not be used. Use ble_gatts_notify_custom instead. */ @@ -771,16 +955,23 @@ int ble_gatts_indicate(uint16_t conn_handle, uint16_t chr_val_handle); */ int ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle); +void ble_gattc_cache_conn_undisc_all(ble_addr_t peer_addr); + +/** Initialize the BLE GATT client. */ int ble_gattc_init(void); /*** @server. */ struct ble_gatt_access_ctxt; + +/** Type definition for GATT access callback function. */ typedef int ble_gatt_access_fn(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg); +/** Type definition for GATT characteristic flags. */ typedef uint16_t ble_gatt_chr_flags; +/** Represents the definition of a GATT characteristic. */ struct ble_gatt_chr_def { /** * Pointer to characteristic UUID; use BLE_UUIDxx_DECLARE macros to declare @@ -820,6 +1011,7 @@ struct ble_gatt_chr_def { struct ble_gatt_cpfd *cpfd; }; +/** Represents the definition of a GATT service. */ struct ble_gatt_svc_def { /** * One of the following: @@ -849,6 +1041,7 @@ struct ble_gatt_svc_def { const struct ble_gatt_chr_def *characteristics; }; +/** Represents the definition of a GATT descriptor. */ struct ble_gatt_dsc_def { /** * Pointer to descriptor UUID; use BLE_UUIDxx_DECLARE macros to declare @@ -949,6 +1142,12 @@ struct ble_gatt_access_ctxt { */ const struct ble_gatt_dsc_def *dsc; }; + + /** + * An offset in case of BLE_ATT_OP_READ_BLOB_REQ. + * If the value is greater than zero it's an indication of a long attribute read. + */ + uint16_t offset; }; /** @@ -1028,6 +1227,7 @@ struct ble_gatt_register_ctxt { }; }; +/** Type definition for GATT registration callback function. */ typedef void ble_gatt_register_fn(struct ble_gatt_register_ctxt *ctxt, void *arg); @@ -1056,7 +1256,7 @@ STAILQ_HEAD(ble_gatts_clt_cfg_list, ble_gatts_clt_cfg); * BLE_HS_ENOMEM on heap exhaustion. */ int ble_gatts_add_svcs(const struct ble_gatt_svc_def *svcs); - +void ble_gatts_free_svcs(void); #if MYNEWT_VAL(BLE_DYNAMIC_SERVICE) /** * Adds a set of services for registration. All services added @@ -1161,7 +1361,7 @@ int ble_gatts_find_chr(const ble_uuid_t *svc_uuid, const ble_uuid_t *chr_uuid, * @param svc_uuid The UUID of the grandparent service. * @param chr_uuid The UUID of the parent characteristic. * @param dsc_uuid The UUID of the descriptor ro look up. - * @param out_handle On success, populated with the handle + * @param out_dsc_handle On success, populated with the handle * of the descriptor attribute. Pass null if * you don't need this value. * @@ -1173,6 +1373,7 @@ int ble_gatts_find_chr(const ble_uuid_t *svc_uuid, const ble_uuid_t *chr_uuid, int ble_gatts_find_dsc(const ble_uuid_t *svc_uuid, const ble_uuid_t *chr_uuid, const ble_uuid_t *dsc_uuid, uint16_t *out_dsc_handle); +/** Type definition for GATT service iteration callback function. */ typedef void (*ble_gatt_svc_foreach_fn)(const struct ble_gatt_svc_def *svc, uint16_t handle, uint16_t end_group_handle, @@ -1184,6 +1385,14 @@ typedef void (*ble_gatt_svc_foreach_fn)(const struct ble_gatt_svc_def *svc, */ void ble_gatts_show_local(void); +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) +/** + * Calculates and returns the maximum + * Security Mode 1 Level requirement. + */ +uint8_t ble_gatts_security_mode_1_level(void); +#endif + /** * Resets the GATT server to its initial state. On success, this function * removes all supported services, characteristics, and descriptors. This diff --git a/src/nimble/nimble/host/include/host/ble_hs.h b/src/nimble/nimble/host/include/host/ble_hs.h index 77ba456e..7ad279a9 100644 --- a/src/nimble/nimble/host/include/host/ble_hs.h +++ b/src/nimble/nimble/host/include/host/ble_hs.h @@ -28,28 +28,29 @@ #include #include "nimble/nimble/include/nimble/hci_common.h" -#include "ble_att.h" -#include "ble_eddystone.h" -#include "ble_gap.h" -#include "ble_gatt.h" -#include "ble_hs_adv.h" -#include "ble_hs_id.h" -#include "ble_hs_hci.h" -#include "ble_hs_log.h" -#include "ble_hs_mbuf.h" -#include "ble_hs_stop.h" -#include "ble_ibeacon.h" -#include "ble_l2cap.h" -#include "ble_sm.h" -#include "ble_store.h" -#include "ble_uuid.h" +#include "nimble/nimble/host/include/host/ble_att.h" +#include "nimble/nimble/host/include/host/ble_eddystone.h" +#include "nimble/nimble/host/include/host/ble_gap.h" +#include "nimble/nimble/host/include/host/ble_gatt.h" +#include "nimble/nimble/host/include/host/ble_hs_adv.h" +#include "nimble/nimble/host/include/host/ble_hs_id.h" +#include "nimble/nimble/host/include/host/ble_hs_hci.h" +#include "nimble/nimble/host/include/host/ble_hs_log.h" +#include "nimble/nimble/host/include/host/ble_hs_mbuf.h" +#include "nimble/nimble/host/include/host/ble_hs_stop.h" +#include "nimble/nimble/host/include/host/ble_ibeacon.h" +#include "nimble/nimble/host/include/host/ble_l2cap.h" +#include "nimble/nimble/host/include/host/ble_sm.h" +#include "nimble/nimble/host/include/host/ble_store.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" #include "nimble/nimble/include/nimble/nimble_npl.h" -#include "ble_esp_hs.h" +#include "nimble/nimble/host/include/host/ble_esp_hs.h" #ifdef __cplusplus extern "C" { #endif +/** Represents an infinite value for timeouts or durations. */ #define BLE_HS_FOREVER INT32_MAX /** Connection handle not present */ @@ -67,36 +68,97 @@ extern "C" { * @{ */ +/** Operation failed and should be retried later. */ #define BLE_HS_EAGAIN 1 + +/** Operation already in progress. */ #define BLE_HS_EALREADY 2 + +/** Invalid parameter. */ #define BLE_HS_EINVAL 3 + +/** Message too long. */ #define BLE_HS_EMSGSIZE 4 + +/** No such entry. */ #define BLE_HS_ENOENT 5 + +/** Out of memory. */ #define BLE_HS_ENOMEM 6 + +/** Not connected. */ #define BLE_HS_ENOTCONN 7 + +/** Not supported. */ #define BLE_HS_ENOTSUP 8 + +/** Application error. */ #define BLE_HS_EAPP 9 + +/** Bad data. */ #define BLE_HS_EBADDATA 10 + +/** Operating System error. */ #define BLE_HS_EOS 11 + +/** Controller error. */ #define BLE_HS_ECONTROLLER 12 + +/** Operation timed out. */ #define BLE_HS_ETIMEOUT 13 + +/** Operation completed. */ #define BLE_HS_EDONE 14 + +/** Resource busy. */ #define BLE_HS_EBUSY 15 + +/** Operation rejected. */ #define BLE_HS_EREJECT 16 + +/** Unknown error. */ #define BLE_HS_EUNKNOWN 17 + +/** Role error. */ #define BLE_HS_EROLE 18 + +/** HCI operation timed out. */ #define BLE_HS_ETIMEOUT_HCI 19 + +/** Out of memory to handle an event. */ #define BLE_HS_ENOMEM_EVT 20 + +/** No valid address. */ #define BLE_HS_ENOADDR 21 + +/** Not synchronized with the controller. */ #define BLE_HS_ENOTSYNCED 22 + +/** Authentication error. */ #define BLE_HS_EAUTHEN 23 + +/** Authorization error. */ #define BLE_HS_EAUTHOR 24 + +/** Encryption error. */ #define BLE_HS_EENCRYPT 25 + +/** Invalid encryption key size. */ #define BLE_HS_EENCRYPT_KEY_SZ 26 + +/** Storage capacity exceeded. */ #define BLE_HS_ESTORE_CAP 27 + +/** Storage operation failed. */ #define BLE_HS_ESTORE_FAIL 28 + +/** Operation was preempted. */ #define BLE_HS_EPREEMPTED 29 + +/** Operation disabled. */ #define BLE_HS_EDISABLED 30 + +/** Operation stalled. */ #define BLE_HS_ESTALLED 31 /** Error base for ATT errors */ @@ -168,6 +230,25 @@ extern "C" { /** KeyboardDisplay Only IO capability */ #define BLE_HS_IO_KEYBOARD_DISPLAY 0x04 +/** + * @} + */ + +/** + * @brief LE key distribution + * @defgroup bt_host_key_dist LE key distribution + * + * @{ + */ + +/** Distibute LTK */ +#define BLE_HS_KEY_DIST_ENC_KEY 0x01 + +/** Distribute IRK */ +#define BLE_HS_KEY_DIST_ID_KEY 0x02 + +/** CSRK distibution and LinkKey are not supported */ + /** * @} */ @@ -234,12 +315,29 @@ struct ble_hs_cfg { */ unsigned sm_sc:1; + /** @brief Security Manager - Enable/Disable Secure Connections Only flag + * + * If set, this will enforce P-256 elliptic curve encryption algorithm + * during pairing. + * It will force the max key size to be used during pairing. + */ + unsigned sm_sc_only:1; + /** @brief Security Manager Key Press Notification flag * * Currently unsupported and should not be set. */ unsigned sm_keypress:1; + /** @brief Enable/Disable Enhanced ATT Support + * + * Primarily used to enable EATT behaviour; denotes the number of eatt + * channels. Set to 0 to disable eatt. + * + * Default value is CONFIG_BT_NIMBLE_EATT_CHAN_NUM. + */ + uint8_t eatt; + /** @brief Security Manager Local Key Distribution Mask */ uint8_t sm_our_key_dist; @@ -260,6 +358,9 @@ struct ble_hs_cfg { */ ble_hs_sync_fn *sync_cb; + /** Callback to handle generation of security keys */ + ble_store_gen_key_fn *store_gen_key_cb; + /* XXX: These need to go away. Instead, the nimble host package should * require the host-store API (not yet implemented).. */ @@ -286,6 +387,7 @@ struct ble_hs_cfg { void *store_status_arg; }; +/** Configuration structure for the NimBLE Host stack. */ extern struct ble_hs_cfg ble_hs_cfg; /** @@ -374,7 +476,7 @@ void ble_hs_init(void); * HAL_RESET_[...] codes or an * implementation-defined value. * - * @return SYSDOWN_IN_PROGRESS. + * @return SYSDOWN_IN_PROGRESS. */ int ble_hs_shutdown(int reason); diff --git a/src/nimble/nimble/host/include/host/ble_hs_adv.h b/src/nimble/nimble/host/include/host/ble_hs_adv.h index da846881..4626d860 100644 --- a/src/nimble/nimble/host/include/host/ble_hs_adv.h +++ b/src/nimble/nimble/host/include/host/ble_hs_adv.h @@ -21,7 +21,8 @@ #define H_BLE_HS_ADV_ #include -#include "ble_uuid.h" +#include "nimble/nimble/host/include/host/ble_uuid.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #ifdef __cplusplus extern "C" { @@ -32,6 +33,8 @@ extern "C" { /** Max field payload size (account for 2-byte header). */ #define BLE_HS_ADV_MAX_FIELD_SZ (BLE_HS_ADV_MAX_SZ - 2) +#define BLE_HS_ADV_LE_SUPP_FEAT_LEN 6 + struct ble_hs_adv_field { uint8_t length; uint8_t type; @@ -113,7 +116,7 @@ struct ble_hs_adv_fields { unsigned device_addr_type; unsigned device_addr_is_present:1; - /*** 0xF1 - 32-bit service solicitation UUIDs */ + /*** 0x1f - 32-bit service solicitation UUIDs */ const ble_uuid32_t *sol_uuids32; uint8_t sol_num_uuids32; @@ -133,6 +136,21 @@ struct ble_hs_adv_fields { const uint8_t *uri; uint8_t uri_len; + /*** 0x27 - LE Supported Features. */ + /*** Core Spec v5.4 Vol. 6 Part B 4.6 */ + uint8_t le_supp_feat[BLE_HS_ADV_LE_SUPP_FEAT_LEN]; + unsigned le_supp_feat_is_present; + + /*** 0x2f - Advertising interval - long. */ + uint32_t adv_itvl_long; + unsigned adv_itvl_long_is_present:1; + +#if MYNEWT_VAL(ENC_ADV_DATA) + /*** 0x31 - Encrypted Advertising Data. */ + const uint8_t *enc_adv_data; + uint8_t enc_adv_data_len; +#endif + /*** 0xff - Manufacturer specific data. */ const uint8_t *mfg_data; uint8_t mfg_data_len; @@ -164,9 +182,12 @@ struct ble_hs_adv_fields { #define BLE_HS_ADV_TYPE_SVC_DATA_UUID32 0x20 #define BLE_HS_ADV_TYPE_SVC_DATA_UUID128 0x21 #define BLE_HS_ADV_TYPE_URI 0x24 +#define BLE_HS_ADV_TYPE_LE_SUPP_FEAT 0x27 #define BLE_HS_ADV_TYPE_MESH_PROV 0x29 #define BLE_HS_ADV_TYPE_MESH_MESSAGE 0x2a #define BLE_HS_ADV_TYPE_MESH_BEACON 0x2b +#define BLE_HS_ADV_TYPE_ADV_ITVL_LONG 0x2f +#define BLE_HS_ADV_TYPE_ENC_ADV_DATA 0x31 #define BLE_HS_ADV_TYPE_MFG_DATA 0xff #define BLE_HS_ADV_FLAGS_LEN 1 @@ -198,6 +219,8 @@ struct ble_hs_adv_fields { #define BLE_HS_ADV_ADDR_TYPE_LEN 1 +#define BLE_HS_ADV_ADV_ITVL_LONG_LEN 4 + int ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields, struct os_mbuf *om); diff --git a/src/nimble/nimble/host/include/host/ble_hs_hci.h b/src/nimble/nimble/host/include/host/ble_hs_hci.h index 56f8bcc4..5b28d999 100644 --- a/src/nimble/nimble/host/include/host/ble_hs_hci.h +++ b/src/nimble/nimble/host/include/host/ble_hs_hci.h @@ -87,6 +87,21 @@ int ble_hs_hci_read_chan_map(uint16_t conn_handle, uint8_t *out_chan_map); */ int ble_hs_hci_set_chan_class(const uint8_t *chan_map); +/** + * Reads random data into buffer from controller. + * This allows to use BLE controller as a source of true random data. + * + * @param dst Destination buffer. + * @param len Destination buffer length. + * + * @return 0 on success; + * A BLE host HCI return code if the controller + * rejected the request; + * A BLE host core return code on unexpected + * error. + */ +int ble_hs_hci_util_rand(void *dst, int len); + #if MYNEWT_VAL(BLE_HCI_VS) /** * Send an arbitrary HCI command to the controller. diff --git a/src/nimble/nimble/host/include/host/ble_hs_log.h b/src/nimble/nimble/host/include/host/ble_hs_log.h index 0646b0ba..e56217fd 100644 --- a/src/nimble/nimble/host/include/host/ble_hs_log.h +++ b/src/nimble/nimble/host/include/host/ble_hs_log.h @@ -20,6 +20,19 @@ #ifndef H_BLE_HS_LOG_ #define H_BLE_HS_LOG_ +/** + * @file ble_hs_log.h + * + * @brief Bluetooth Host Log + * + * This header file defines macros and functions used for logging messages + * within the BLE Host Stack. + * + * @defgroup bt_host_log Bluetooth Host Log + * @ingroup bt_host + * @{ + */ + #include "nimble/porting/nimble/include/modlog/modlog.h" #include "nimble/porting/nimble/include/log/log.h" @@ -34,20 +47,62 @@ extern "C" { struct os_mbuf; +/** + * @brief Macro for logging messages at a specified log level. + * + * The BLE_HS_LOG macro allows logging messages with different severity levels, + * such as DEBUG, INFO, WARN, ERROR or CRITICAL. + * + * @param lvl The log level of the message. + * @param ... The format string and additional arguments for the log message. + */ #define BLE_HS_LOG(lvl, ...) \ BLE_HS_LOG_ ## lvl(__VA_ARGS__) +/** + * @brief Macro for logging a Bluetooth address at a specified log level. + * + * The BLE_HS_LOG_ADDR macro allows logging Bluetooth addresses in the format + * "XX:XX:XX:XX:XX:XX" at different severity levels, such as DEBUG, INFO, WARN, ERROR or CRITICAL. + * + * @param lvl The log level of the message. + * @param addr The Bluetooth address to be logged. + */ #define BLE_HS_LOG_ADDR(lvl, addr) \ BLE_HS_LOG_ ## lvl("%02x:%02x:%02x:%02x:%02x:%02x", \ (addr)[5], (addr)[4], (addr)[3], \ (addr)[2], (addr)[1], (addr)[0]) +/** + * @brief Logs the content of an `os_mbuf` structure. + * + * This function iterates over each byte in the provided `os_mbuf` and logs its + * value in hexadecimal format using the `BLE_HS_LOG` macro with the log level + * set to DEBUG. + * + * @param om The `os_mbuf` to log. + */ void ble_hs_log_mbuf(const struct os_mbuf *om); + +/** + * @brief Logs the content of a flat buffer. + * + * This function iterates over each byte in the provided buffer and logs its + * value in hexadecimal format using the `BLE_HS_LOG` macro with the log level + * set to DEBUG. + * + * @param data Pointer to the buffer to log. + * @param len Length of the buffer. + */ void ble_hs_log_flat_buf(const void *data, int len); #ifdef __cplusplus } #endif +/** + * @} + */ + #endif diff --git a/src/nimble/nimble/host/include/host/ble_hs_pvcy.h b/src/nimble/nimble/host/include/host/ble_hs_pvcy.h index 5c54d94d..cd2519bc 100644 --- a/src/nimble/nimble/host/include/host/ble_hs_pvcy.h +++ b/src/nimble/nimble/host/include/host/ble_hs_pvcy.h @@ -22,7 +22,7 @@ #ifndef H_BLE_HS_PVCY_ #define H_BLE_HS_PVCY_ -#include "ble_hs.h" +#include "nimble/nimble/host/include/host/ble_hs.h" #ifdef __cplusplus extern "C" { @@ -69,7 +69,7 @@ void ble_hs_resolv_deinit(void); #endif int ble_hs_pvcy_set_resolve_enabled(int enable); -void ble_hs_set_rpa_timeout(uint16_t timeout); +int ble_hs_set_rpa_timeout(uint16_t timeout); #ifdef __cplusplus } diff --git a/src/nimble/nimble/host/include/host/ble_hs_stop.h b/src/nimble/nimble/host/include/host/ble_hs_stop.h index e4feb62b..8b3ebd3f 100644 --- a/src/nimble/nimble/host/include/host/ble_hs_stop.h +++ b/src/nimble/nimble/host/include/host/ble_hs_stop.h @@ -20,6 +20,13 @@ #ifndef H_BLE_HS_STOP_ #define H_BLE_HS_STOP_ +/** + * @brief Bluetooth Host Stop API + * @defgroup bt_hs_stop Bluetooth Host Stop + * @ingroup bt_host + * @{ + */ + /** @typedef ble_hs_stop_fn * @brief Callback function; reports the result of a host stop procedure. * @@ -38,8 +45,13 @@ typedef void ble_hs_stop_fn(int status, void *arg); * This should be used as an opaque structure and not modified manually. */ struct ble_hs_stop_listener { + /** The callback function to be called when the stop procedure completes. */ ble_hs_stop_fn *fn; + + /** An optional argument to be passed to the callback function. */ void *arg; + + /** Singly-linked list entry. */ SLIST_ENTRY(ble_hs_stop_listener) link; }; @@ -67,4 +79,8 @@ struct ble_hs_stop_listener { int ble_hs_stop(struct ble_hs_stop_listener *listener, ble_hs_stop_fn *fn, void *arg); +/** +* @} +*/ + #endif diff --git a/src/nimble/nimble/host/include/host/ble_l2cap.h b/src/nimble/nimble/host/include/host/ble_l2cap.h index 9d92c08f..98258408 100644 --- a/src/nimble/nimble/host/include/host/ble_l2cap.h +++ b/src/nimble/nimble/host/include/host/ble_l2cap.h @@ -17,6 +17,20 @@ * under the License. */ +/** + * @file ble_l2cap.h + * + * @brief L2CAP (Logical Link Control and Adaptation Protocol) API + * + * This header file provides the public API for interacting with the L2CAP layer of the BLE + * (Bluetooth Low Energy) stack. L2CAP is responsible for managing logical channels between + * two connected BLE devices. + * + * @defgroup bt_host_l2cap Bluetooth Host Logical Link Control and Adaptation Protocol + * @ingroup bt_host + * @{ + */ + #ifndef H_BLE_L2CAP_ #define H_BLE_L2CAP_ @@ -25,89 +39,311 @@ extern "C" { #endif +/** + * @brief L2CAP Signaling Connection Parameters Update Request. + * + * This structure represents a request to update the L2CAP connection parameters. + */ struct ble_l2cap_sig_update_req; + +/** + * @brief BLE Host Connection structure. + * + * This structure represents a connection between the BLE host and a remote device. + */ struct ble_hs_conn; +/** + * @defgroup ble_l2cap_channel_ids Channel Identifiers + * @{ + */ +/** Attribute Protocol (ATT) CID. */ #define BLE_L2CAP_CID_ATT 4 + +/** L2CAP LE Signaling CID. */ #define BLE_L2CAP_CID_SIG 5 + +/** Security Manager (SM) CID. */ #define BLE_L2CAP_CID_SM 6 +/** @} */ + +/** + * @defgroup ble_l2cap_signaling_op_codes Signaling Commands Operation Codes + * @{ + */ + +/** Reject */ #define BLE_L2CAP_SIG_OP_REJECT 0x01 + +/** Connect Request */ #define BLE_L2CAP_SIG_OP_CONNECT_REQ 0x02 + +/** Connect Response */ #define BLE_L2CAP_SIG_OP_CONNECT_RSP 0x03 + +/** Configuration Request */ #define BLE_L2CAP_SIG_OP_CONFIG_REQ 0x04 + +/** Configuration Response */ #define BLE_L2CAP_SIG_OP_CONFIG_RSP 0x05 + +/** Disconnect Request */ #define BLE_L2CAP_SIG_OP_DISCONN_REQ 0x06 + +/** Disconnect Response */ #define BLE_L2CAP_SIG_OP_DISCONN_RSP 0x07 + +/** Echo Request */ #define BLE_L2CAP_SIG_OP_ECHO_REQ 0x08 + +/** Echo Response */ #define BLE_L2CAP_SIG_OP_ECHO_RSP 0x09 + +/** Information Request */ #define BLE_L2CAP_SIG_OP_INFO_REQ 0x0a + +/** Information Response */ #define BLE_L2CAP_SIG_OP_INFO_RSP 0x0b + +/** Create Channel Request */ #define BLE_L2CAP_SIG_OP_CREATE_CHAN_REQ 0x0c + +/** Create Channel Response */ #define BLE_L2CAP_SIG_OP_CREATE_CHAN_RSP 0x0d + +/** Move Channel Request */ #define BLE_L2CAP_SIG_OP_MOVE_CHAN_REQ 0x0e + +/** Move Channel Response */ #define BLE_L2CAP_SIG_OP_MOVE_CHAN_RSP 0x0f + +/** Move Channel Confirmation Request */ #define BLE_L2CAP_SIG_OP_MOVE_CHAN_CONF_REQ 0x10 + +/** Move Channel Confirmation Response */ #define BLE_L2CAP_SIG_OP_MOVE_CHAN_CONF_RSP 0x11 + +/** Update Request */ #define BLE_L2CAP_SIG_OP_UPDATE_REQ 0x12 + +/** Update Response */ #define BLE_L2CAP_SIG_OP_UPDATE_RSP 0x13 + +/** LE Credit Based Connection Request */ #define BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_REQ 0x14 + +/** LE Credit Based Connection Response */ #define BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_RSP 0x15 + +/** Credit Based Flow Control Credit */ #define BLE_L2CAP_SIG_OP_FLOW_CTRL_CREDIT 0x16 + +/** Credit Based Connection Request */ #define BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ 0x17 + +/** Credit Based Connection Response */ #define BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP 0x18 + +/** Credit Based Reconfiguration Request */ #define BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_REQ 0x19 + +/** Credit Based Reconfiguration Response */ #define BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP 0x1A + +/** Signaling Command Maximum Value */ #define BLE_L2CAP_SIG_OP_MAX 0x1B +/** @} */ + +/** + * @defgroup ble_l2cap_signaling_err_codes Signaling Commands Error Codes + * @{ + */ + +/** Command Not Understood */ #define BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD 0x0000 + +/** Maximum Transmission Unit (MTU) Exceeded */ #define BLE_L2CAP_SIG_ERR_MTU_EXCEEDED 0x0001 + +/** Invalid CID */ #define BLE_L2CAP_SIG_ERR_INVALID_CID 0x0002 +/** @} */ + +/** + * @defgroup ble_l2cap_coc_err_codes Connection-Oriented Channels (CoC) Error Codes + * @{ + */ + +/** Connection Success */ #define BLE_L2CAP_COC_ERR_CONNECTION_SUCCESS 0x0000 + +/** Unknown LE Protocol/Service Multiplexer (PSM) */ #define BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM 0x0002 + +/** No Resources */ #define BLE_L2CAP_COC_ERR_NO_RESOURCES 0x0004 + +/** Insufficient Authentication */ #define BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN 0x0005 + +/** Insufficient Authorization */ #define BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR 0x0006 + +/** Insufficient Key Size */ #define BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ 0x0007 + +/** Insufficient Encryption */ #define BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC 0x0008 + +/** Invalid Source CID */ #define BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID 0x0009 + +/** Source CID Already Used */ #define BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED 0x000A + +/** Unacceptable Parameters */ #define BLE_L2CAP_COC_ERR_UNACCEPTABLE_PARAMETERS 0x000B + +/** Invalid Parameters */ #define BLE_L2CAP_COC_ERR_INVALID_PARAMETERS 0x000C +/** @} */ + +/** + * @defgroup ble_l2cap_reconfig_err_codes Channel Reconfiguration Error Codes + * @{ + */ + +/** Reconfiguration Succeeded */ #define BLE_L2CAP_ERR_RECONFIG_SUCCEED 0x0000 + +/** Reduction of Maximum Transmission Unit (MTU) Not Allowed */ #define BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED 0x0001 + +/** Reduction of Maximum Packet Size (MPS) Not Allowed */ #define BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED 0x0002 + +/** Invalid Destination CID */ #define BLE_L2CAP_ERR_RECONFIG_INVALID_DCID 0x0003 -#define BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM 0x0004 +/** Unaccepted Parameters */ +#define BLE_L2CAP_ERR_RECONFIG_UNACCEPTED_PARAM 0x0004 + +/** @} */ + +/** + * @defgroup ble_l2cap_coc_event_types Connection-Oriented Channel (CoC) Event Types + * @{ + */ + +/** CoC Connected */ #define BLE_L2CAP_EVENT_COC_CONNECTED 0 + +/** CoC Disconnected */ #define BLE_L2CAP_EVENT_COC_DISCONNECTED 1 + +/** CoC Accept */ #define BLE_L2CAP_EVENT_COC_ACCEPT 2 + +/** CoC Data Received */ #define BLE_L2CAP_EVENT_COC_DATA_RECEIVED 3 + +/** CoC Transmission Unstalled */ #define BLE_L2CAP_EVENT_COC_TX_UNSTALLED 4 + +/** CoC Reconfiguration Completed */ #define BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED 5 + +/** CoC Peer Reconfigured */ #define BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED 6 +/** @} */ + + +/** + * @brief Function signature for L2CAP signaling update event callback. + * + * This function is used to handle signaling update events in the L2CAP layer, + * such as changes in connection parameters. + * + * @param conn_handle The connection handle associated with the signaling update event. + * @param status The status of the signaling update event. + * @param arg A pointer to additional arguments passed to the callback function. + */ typedef void ble_l2cap_sig_update_fn(uint16_t conn_handle, int status, void *arg); +/** + * @brief Represents the signaling update in L2CAP. + * + * This structure holds the parameters required for initiating a signaling update in the L2CAP layer. + * It defines the connection interval, slave latency, and supervision timeout multiplier for the update. + */ struct ble_l2cap_sig_update_params { + /** + * The minimum desired connection interval in increments of 1.25 ms. + * This value defines the lower bound for the connection interval range. + */ uint16_t itvl_min; + + /** + * The maximum desired connection interval in increments of 1.25 ms. + * This value defines the upper bound for the connection interval range. + */ uint16_t itvl_max; + + /** + * The desired number of connection events that a slave device can skip. + * It specifies the maximum allowed latency between consecutive connection events. + */ uint16_t slave_latency; + + /** + * The desired supervision timeout multiplier. + * The supervision timeout defines the time limit for detecting the loss of a connection. + * This value is multiplied by the connection interval to determine the supervision timeout duration. + */ uint16_t timeout_multiplier; }; +/** + * @brief Initiate an L2CAP connection update procedure. + * + * This function initiates an L2CAP connection update procedure for the specified connection handle. + * The update procedure is used to modify the connection parameters, such as interval, latency, and timeout. + * + * @param conn_handle The connection handle of the L2CAP connection. + * + * @param params A pointer to a structure containing the desired update parameters. + * This includes the new connection interval, slave latency, and + * supervision timeout multiplier. + * + * @param cb The callback function to be called when the update request completes. + * The function signature for the callback is defined by `ble_l2cap_sig_update_fn`. + * + * @param cb_arg An optional argument to be passed to the callback function. + * + * @return 0 on success; + * A non-zero value on failure. + */ int ble_l2cap_sig_update(uint16_t conn_handle, struct ble_l2cap_sig_update_params *params, ble_l2cap_sig_update_fn *cb, void *cb_arg); +/** + * @brief Structure representing a L2CAP channel. + * + * It is used to maintain the state and track the properties of an L2CAP channel + * during its lifecycle. + */ struct ble_l2cap_chan; /** - * Represents a L2CAP-related event. + * @brief Represents a L2CAP-related event. + * * When such an event occurs, the host notifies the application by passing an * instance of this structure to an application-specified callback. */ @@ -234,33 +470,161 @@ struct ble_l2cap_event { }; }; +/** + * @brief Represents information about an L2CAP channel. + * + * This structure is typically used to retrieve or provide information about an existing L2CAP channel. + */ struct ble_l2cap_chan_info { + /** Source Channel Identifier. */ uint16_t scid; + + /** Destination Channel Identifier. */ uint16_t dcid; + + /** Local L2CAP Maximum Transmission Unit. */ uint16_t our_l2cap_mtu; + + /** Peer L2CAP Maximum Transmission Unit. */ uint16_t peer_l2cap_mtu; + + /** Protocol/Service Multiplexer of the channel. */ uint16_t psm; + + /** Local CoC Maximum Transmission Unit. */ uint16_t our_coc_mtu; + + /** Peer CoC Maximum Transmission Unit. */ uint16_t peer_coc_mtu; }; +/** + * @brief Function pointer type for handling L2CAP events. + * + * @param event A pointer to the L2CAP event structure. + * @param arg A pointer to additional arguments passed to the callback function. + * + * @return Integer value representing the status or result of the event handling. + */ typedef int ble_l2cap_event_fn(struct ble_l2cap_event *event, void *arg); - +/** + * @brief Get the connection handle associated with an L2CAP channel. + * + * This function retrieves the connection handle associated with the specified L2CAP channel. + * + * @param chan A pointer to the L2CAP channel structure. + * + * @return The connection handle associated with the L2CAP channel on success; + * A Bluetooth Host Error Code on failure: + * BLE_HS_CONN_HANDLE_NONE: if the provided channel pointer is NULL. + */ uint16_t ble_l2cap_get_conn_handle(struct ble_l2cap_chan *chan); + +/** + * @brief Create an L2CAP server. + * + * This function creates an L2CAP server with the specified Protocol/Service Multiplexer (PSM) and Maximum + * Transmission Unit (MTU) size. The server is used to accept incoming L2CAP connections from remote clients. + * When a connection request is received, the provided callback function will be invoked with the corresponding + * event information. + * + * @param psm The Protocol/Service Multiplexer (PSM) for the server. + * @param mtu The Maximum Transmission Unit (MTU) size for the server. + * @param cb Pointer to the callback function to be invoked when a connection request is received. + * @param cb_arg An optional argument to be passed to the callback function. + * + * @return 0 on success; + * A non-zero value on failure. + */ int ble_l2cap_create_server(uint16_t psm, uint16_t mtu, ble_l2cap_event_fn *cb, void *cb_arg); +/** + * @brief Initiate an L2CAP connection. + * + * This function initiates an L2CAP connection to a remote device with the specified connection handle, + * Protocol/Service Multiplexer (PSM), Maximum Transmission Unit (MTU) size, and receive SDU buffer. + * When the connection is established or if there is an error during the connection process, the provided + * callback function will be invoked with the corresponding event information. + * + * @param conn_handle The connection handle for the remote device. + * @param psm The Protocol/Service Multiplexer (PSM) for the connection. + * @param mtu The Maximum Transmission Unit (MTU) size for the connection. + * @param sdu_rx Pointer to the receive Service Data Unit (SDU) buffer. + * @param cb Pointer to the callback function to be invoked when the connection is established. + * @param cb_arg An optional argument to be passed to the callback function. + * + * @return 0 on success; + * A non-zero value on failure. + */ int ble_l2cap_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, struct os_mbuf *sdu_rx, ble_l2cap_event_fn *cb, void *cb_arg); + +/** + * @brief Disconnect an L2CAP channel. + * + * This function disconnects the specified L2CAP channel by sending a disconnect signal. + * + * @param chan Pointer to the L2CAP channel structure representing the channel to disconnect. + * + * @return 0 on success; + * A non-zero value on failure. + */ int ble_l2cap_disconnect(struct ble_l2cap_chan *chan); + +/** + * @brief Send an SDU (Service Data Unit) over an L2CAP channel. + * + * This function sends an SDU over the specified L2CAP channel. The SDU is encapsulated + * in L2CAP frames and transmitted to the remote device. + * + * @param chan Pointer to the L2CAP channel structure representing the channel to send the SDU on. + * @param sdu_tx Pointer to the os_mbuf structure containing the SDU (Service Data Unit) to send. + * + * @return 0 on success; + * BLE_HS_ESTALLED: if there was not enough credits available to send whole SDU. + * The application needs to wait for the event 'BLE_L2CAP_EVENT_COC_TX_UNSTALLED' + * before being able to transmit more data; + * Another non-zero value on failure. + */ int ble_l2cap_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx); + +/** + * @brief Check if the L2CAP channel is ready to receive an SDU. + * + * This function checks if the specified L2CAP channel is ready to receive an SDU (Service Data Unit). + * It can be used to determine if the channel is in a state where it can accept incoming data. + * + * @param chan Pointer to the L2CAP channel structure to check. + * @param sdu_rx Pointer to the os_mbuf structure to receive the incoming SDU. + * + * @return 0 if the channel is ready to receive an SDU; + * A non-zero value on failure. + */ int ble_l2cap_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx); + +/** + * @brief Get information about an L2CAP channel. + * + * This function retrieves information about the specified L2CAP channel and populates + * the provided `ble_l2cap_chan_info` structure with the channel's details. + * + * @param chan Pointer to the L2CAP channel structure to retrieve information from. + * @param chan_info Pointer to the `ble_l2cap_chan_info` structure to populate with channel information. + * + * @return 0 on success; + * A non-zero value on failure. + */ int ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info *chan_info); #ifdef __cplusplus } #endif +/** + * @} + */ + #endif diff --git a/src/nimble/nimble/host/include/host/ble_sm.h b/src/nimble/nimble/host/include/host/ble_sm.h index 42414d58..e5b2f552 100644 --- a/src/nimble/nimble/host/include/host/ble_sm.h +++ b/src/nimble/nimble/host/include/host/ble_sm.h @@ -27,6 +27,7 @@ extern "C" { #endif +#define BLE_SM_ERR_SUCCESS 0x00 #define BLE_SM_ERR_PASSKEY 0x01 #define BLE_SM_ERR_OOB 0x02 #define BLE_SM_ERR_AUTHREQ 0x03 @@ -41,7 +42,8 @@ extern "C" { #define BLE_SM_ERR_NUMCMP 0x0c #define BLE_SM_ERR_ALREADY 0x0d #define BLE_SM_ERR_CROSS_TRANS 0x0e -#define BLE_SM_ERR_MAX_PLUS_1 0x0f +#define BLE_SM_ERR_KEY_REJ 0x0f +#define BLE_SM_ERR_MAX_PLUS_1 0x10 #define BLE_SM_PAIR_ALG_JW 0 #define BLE_SM_PAIR_ALG_PASSKEY 1 diff --git a/src/nimble/nimble/host/include/host/ble_store.h b/src/nimble/nimble/host/include/host/ble_store.h index 325dbb3e..8fcfb487 100644 --- a/src/nimble/nimble/host/include/host/ble_store.h +++ b/src/nimble/nimble/host/include/host/ble_store.h @@ -38,6 +38,7 @@ extern "C" { #define BLE_STORE_OBJ_TYPE_PEER_ADDR 6 #define BLE_STORE_OBJ_TYPE_LOCAL_IRK 7 +#define BLE_STORE_OBJ_TYPE_CSFC 8 /** Failed to persist record; insufficient storage capacity. */ #define BLE_STORE_EVENT_OVERFLOW 1 @@ -57,14 +58,6 @@ struct ble_store_key_sec { */ ble_addr_t peer_addr; - /** Key by ediv; ediv_rand_present=0 means don't key off ediv. */ - uint16_t ediv; - - /** Key by rand_num; ediv_rand_present=0 means don't key off rand_num. */ - uint64_t rand_num; - - unsigned ediv_rand_present:1; - /** Number of results to skip; 0 means retrieve the first match. */ uint8_t idx; }; @@ -129,6 +122,29 @@ struct ble_store_value_cccd { unsigned value_changed:1; }; +/** + * Used as a key for lookups of stored client supported features characteristic (CSFC). + * This struct corresponds to the BLE_STORE_OBJ_TYPE_CSFC store object type. + */ +struct ble_store_key_csfc { + /** + * Key by peer identity address; + */ + ble_addr_t peer_addr; + + /** Number of results to skip; 0 means retrieve the first match. */ + uint8_t idx; +}; + +/** + * Represents a stored client supported features characteristic (CSFC). + * This struct corresponds to the BLE_STORE_OBJ_TYPE_CSFC store object type. + */ +struct ble_store_value_csfc { + ble_addr_t peer_addr; + uint8_t csfc[MYNEWT_VAL(BLE_GATT_CSFC_SIZE)]; +}; + #if MYNEWT_VAL(ENC_ADV_DATA) /** * Used as a key for lookups of encrypted advertising data. This struct corresponds @@ -189,6 +205,7 @@ union ble_store_key { #endif struct ble_store_key_rpa_rec rpa_rec; struct ble_store_key_local_irk local_irk; + struct ble_store_key_csfc csfc; }; /** @@ -203,6 +220,7 @@ union ble_store_value { #endif struct ble_store_value_rpa_rec rpa_rec; struct ble_store_value_local_irk local_irk; + struct ble_store_value_csfc csfc; }; struct ble_store_status_event { @@ -245,6 +263,42 @@ struct ble_store_status_event { }; }; +/* Generate LTK, EDIT and Rand */ +#define BLE_STORE_GEN_KEY_LTK 0x01 +/* Generate IRK */ +#define BLE_STORE_GEN_KEY_IRK 0x02 +/* Generate CSRK */ +#define BLE_STORE_GEN_KEY_CSRK 0x03 + +struct ble_store_gen_key { + union { + uint8_t ltk_periph[16]; + uint8_t irk[16]; + uint8_t csrk[16]; + }; + uint16_t ediv; + uint64_t rand; +}; + +/** + * Generates key required by security module. + * This can be used to use custom routines to generate keys instead of simply + * randomizing them. + * + * \p conn_handle is set to \p BLE_HS_CONN_HANDLE_NONE if key is not requested + * for a specific connection (e.g. an IRK). + * + * @param key Key that shall be generated. + * @param gen_key Storage for generated key. + * @param conn_handle Connection handle for which keys are generated. + * + * @return 0 if keys were generated successfully + * Other nonzero on error. + */ +typedef int ble_store_gen_key_fn(uint8_t key, + struct ble_store_gen_key *gen_key, + uint16_t conn_handle); + /** * Searches the store for an object matching the specified criteria. If a * match is found, it is read from the store and the dst parameter is populated @@ -333,10 +387,18 @@ int ble_store_read_cccd(const struct ble_store_key_cccd *key, int ble_store_write_cccd(const struct ble_store_value_cccd *value); int ble_store_delete_cccd(const struct ble_store_key_cccd *key); +int ble_store_read_csfc(const struct ble_store_key_csfc *key, + struct ble_store_value_csfc *out_value); +int ble_store_write_csfc(const struct ble_store_value_csfc *value); +int ble_store_delete_csfc(const struct ble_store_key_csfc *key); + void ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, const struct ble_store_value_sec *value); void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key, const struct ble_store_value_cccd *value); +void ble_store_key_from_value_csfc(struct ble_store_key_csfc *out_key, + const struct ble_store_value_csfc *value); + #if MYNEWT_VAL(ENC_ADV_DATA) int ble_store_read_ead(const struct ble_store_key_ead *key, struct ble_store_value_ead *out_value); diff --git a/src/nimble/nimble/host/include/host/ble_uuid.h b/src/nimble/nimble/host/include/host/ble_uuid.h index cc368368..54d2b5e2 100644 --- a/src/nimble/nimble/host/include/host/ble_uuid.h +++ b/src/nimble/nimble/host/include/host/ble_uuid.h @@ -56,30 +56,55 @@ typedef struct { /** 16-bit UUID */ typedef struct { + /** Generic UUID structure */ ble_uuid_t u; + + /** 16-bit UUID value */ uint16_t value; } ble_uuid16_t; /** 32-bit UUID */ typedef struct { + /** Generic UUID structure */ ble_uuid_t u; + + /** 32-bit UUID value */ uint32_t value; } ble_uuid32_t; /** 128-bit UUID */ typedef struct { + /** Generic UUID structure */ ble_uuid_t u; + + /** 128-bit UUID value */ uint8_t value[16]; } ble_uuid128_t; /** Universal UUID type, to be used for any-UUID static allocation */ typedef union { + /** Generic UUID structure */ ble_uuid_t u; + + /** 16-bit UUID structure */ ble_uuid16_t u16; + + /** 32-bit UUID structure */ ble_uuid32_t u32; + + /** 128-bit UUID structure */ ble_uuid128_t u128; } ble_uuid_any_t; +/** + * @brief Macro for initializing a 16-bit UUID. + * + * This macro initializes a 16-bit UUID with the provided value. + * + * @param uuid16 The value of the 16-bit UUID. + * + * @return The initialized 16-bit UUID structure. + */ #define BLE_UUID16_INIT(uuid16) \ { \ .u = { \ @@ -88,6 +113,15 @@ typedef union { .value = (uuid16), \ } +/** + * @brief Macro for initializing a 32-bit UUID. + * + * This macro initializes a 32-bit UUID with the provided value. + * + * @param uuid32 The value of the 32-bit UUID. + * + * @return The initialized 32-bit UUID structure. + */ #define BLE_UUID32_INIT(uuid32) \ { \ .u = { \ @@ -104,21 +138,63 @@ typedef union { .value = { uuid128 }, \ } +/** + * @brief Macro for declaring a pointer to a 16-bit UUID structure initialized with a specific 16-bit UUID value. + * + * @param uuid16 The 16-bit UUID value to initialize the structure with. + * + * @return Pointer to a `ble_uuid_t` structure. + */ #define BLE_UUID16_DECLARE(uuid16) \ ((ble_uuid_t *) (&(ble_uuid16_t) BLE_UUID16_INIT(uuid16))) +/** + * @brief Macro for declaring a pointer to a 32-bit UUID structure initialized with a specific 32-bit UUID value. + * + * @param uuid32 The 32-bit UUID value to initialize the structure with. + * + * @return Pointer to a `ble_uuid_t` structure. + */ #define BLE_UUID32_DECLARE(uuid32) \ ((ble_uuid_t *) (&(ble_uuid32_t) BLE_UUID32_INIT(uuid32))) +/** + * @brief Macro for declaring a pointer to a 128-bit UUID structure initialized with specific 128-bit UUID values. + * + * @param uuid128 The 128-bit UUID value to initialize the structure with. + * + * @return Pointer to a `ble_uuid_t` structure. + */ #define BLE_UUID128_DECLARE(uuid128...) \ ((ble_uuid_t *) (&(ble_uuid128_t) BLE_UUID128_INIT(uuid128))) +/** + * @brief Macro for casting a pointer to a `ble_uuid_t` structure to a pointer to 16-bit UUID structure. + * + * @param u Pointer to a `ble_uuid_t` structure. + * + * @return Pointer to a `ble_uuid16_t` structure. + */ #define BLE_UUID16(u) \ ((ble_uuid16_t *) (u)) +/** + * @brief Macro for casting a pointer to a `ble_uuid_t` structure to a pointer to 32-bit UUID structure. + * + * @param u Pointer to a `ble_uuid_t` structure. + * + * @return Pointer to a `ble_uuid32_t` structure. + */ #define BLE_UUID32(u) \ ((ble_uuid32_t *) (u)) +/** + * @brief Macro for casting a pointer to a `ble_uuid_t` structure to a pointer to 128-bit UUID structure. + * + * @param u Pointer to a `ble_uuid_t` structure. + * + * @return Pointer to a `ble_uuid128_t` structure. + */ #define BLE_UUID128(u) \ ((ble_uuid128_t *) (u)) @@ -168,6 +244,25 @@ void ble_uuid_copy(ble_uuid_any_t *dst, const ble_uuid_t *src); */ char *ble_uuid_to_str(const ble_uuid_t *uuid, char *dst); +/** + * @brief Converts the specified UUID string to ble_uuid_any_t representation. + * If the UUID is recognised as Bluetooth SIG UUID, it will provide its + * 32-bit or 16-bit representation. + * + * Example 128-bit string representations: + * o "12345678-1234-1234-1234-123456789abc" + * o "12345678123412341234123456789abc" + * + * @param uuid Destination UUID. + * @param str The source string UUID. + * + * @return 0 on success, + * BLE_HS_EINVAL if the specified UUID string has wrong size or + * contains disallowed characters. + */ +int +ble_uuid_from_str(ble_uuid_any_t *uuid, const char *str); + /** @brief Converts the specified 16-bit UUID to a uint16_t. * * @param uuid The source UUID to convert. diff --git a/src/nimble/nimble/host/mesh/include/mesh/glue.h b/src/nimble/nimble/host/mesh/include/mesh/glue.h index 81c063b6..3fa52979 100644 --- a/src/nimble/nimble/host/mesh/include/mesh/glue.h +++ b/src/nimble/nimble/host/mesh/include/mesh/glue.h @@ -38,7 +38,7 @@ #include "nimble/nimble/host/src/ble_hs_hci_priv.h" #if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) -#include "mbedtls/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" #include "mbedtls/cipher.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" diff --git a/src/nimble/nimble/host/mesh/include/mesh/mesh.h b/src/nimble/nimble/host/mesh/include/mesh/mesh.h index 1df6c7a7..7d260bd2 100644 --- a/src/nimble/nimble/host/mesh/include/mesh/mesh.h +++ b/src/nimble/nimble/host/mesh/include/mesh/mesh.h @@ -27,7 +27,7 @@ #include "cdb.h" #include "cfg.h" #include "heartbeat.h" -#include "../../src/app_keys.h" -#include "../../src/net.h" +#include "nimble/nimble/host/mesh/src/app_keys.h" +#include "nimble/nimble/host/mesh/src/net.h" #endif /* __BT_MESH_H */ diff --git a/src/nimble/nimble/host/mesh/src/access.c b/src/nimble/nimble/host/mesh/src/access.c index 23b2a13c..a400c2db 100644 --- a/src/nimble/nimble/host/mesh/src/access.c +++ b/src/nimble/nimble/host/mesh/src/access.c @@ -7,15 +7,13 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_ACCESS_LOG #include #include -#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" @@ -26,7 +24,7 @@ #include "foundation.h" #include "settings.h" #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS) -#include "../include/mesh/model_cli.h" +#include "nimble/nimble/host/mesh/include/mesh/model_cli.h" #endif /* bt_mesh_model.flags */ @@ -308,7 +306,7 @@ static int bt_mesh_vnd_mod_msg_cid_check(struct bt_mesh_model *mod) } BT_ERR("Invalid vendor model(company:0x%04x" - " id:0x%04x) message opcode 0x%08x", + " id:0x%04x) message opcode 0x%08" PRIx32, mod->vnd.company, mod->vnd.id, op->opcode); return -EINVAL; @@ -703,10 +701,10 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct os_mbuf *buf) } if ((op->len >= 0) && (buf->om_len < (size_t)op->len)) { - BT_ERR("Too short message for OpCode 0x%08x", opcode); + BT_ERR("Too short message for OpCode 0x%08" PRIx32, opcode); continue; } else if ((op->len < 0) && (buf->om_len != (size_t)(-op->len))) { - BT_ERR("Invalid message size for OpCode 0x%08x", + BT_ERR("Invalid message size for OpCode 0x%08" PRIx32, opcode); continue; } @@ -1313,4 +1311,3 @@ void bt_mesh_access_init(void) "Failed to register bt_mesh_access conf"); #endif } -#endif diff --git a/src/nimble/nimble/host/mesh/src/access.h b/src/nimble/nimble/host/mesh/src/access.h index 297711cc..9b359e5b 100644 --- a/src/nimble/nimble/host/mesh/src/access.h +++ b/src/nimble/nimble/host/mesh/src/access.h @@ -9,7 +9,7 @@ #ifndef __ACCESS_H__ #define __ACCESS_H__ -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" /* Tree walk return codes */ enum bt_mesh_walk { diff --git a/src/nimble/nimble/host/mesh/src/adv.c b/src/nimble/nimble/host/mesh/src/adv.c index c1a36e9c..88ea60c7 100644 --- a/src/nimble/nimble/host/mesh/src/adv.c +++ b/src/nimble/nimble/host/mesh/src/adv.c @@ -8,15 +8,14 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_ADV_LOG -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "nimble/nimble/host/include/host/ble_hs_adv.h" #include "nimble/nimble/host/include/host/ble_gap.h" -#include "../include/mesh/porting.h" +#include "nimble/nimble/host/mesh/include/mesh/porting.h" #include "nimble/porting/nimble/include/nimble/nimble_port.h" + #include "adv.h" #include "net.h" #include "foundation.h" @@ -256,4 +255,3 @@ int bt_mesh_scan_disable(void) return 0; } -#endif diff --git a/src/nimble/nimble/host/mesh/src/adv.h b/src/nimble/nimble/host/mesh/src/adv.h index 74d33327..3aa56c5e 100644 --- a/src/nimble/nimble/host/mesh/src/adv.h +++ b/src/nimble/nimble/host/mesh/src/adv.h @@ -10,7 +10,7 @@ #define __ADV_H__ /* Maximum advertising data payload for a single data type */ -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #define BT_MESH_ADV(om) (*(struct bt_mesh_adv **) OS_MBUF_USRHDR(om)) diff --git a/src/nimble/nimble/host/mesh/src/adv_ext.c b/src/nimble/nimble/host/mesh/src/adv_ext.c index b411341c..5839e7b1 100644 --- a/src/nimble/nimble/host/mesh/src/adv_ext.c +++ b/src/nimble/nimble/host/mesh/src/adv_ext.c @@ -7,18 +7,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_ADV_LOG + #include "adv.h" #include "net.h" #include "proxy.h" #include "pb_gatt_srv.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/nimble/host/include/host/ble_gap.h" - #if MYNEWT_VAL(BLE_MESH_ADV_EXT) /* Convert from ms to 0.625ms units */ #define ADV_INT_FAST_MS 20 @@ -345,5 +343,3 @@ int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, return adv_start(¶ms, adv_timeout, ad, ad_len, sd, sd_len); } #endif - -#endif // #if MYNEWT_VAL(BLE_MESH) diff --git a/src/nimble/nimble/host/mesh/src/adv_legacy.c b/src/nimble/nimble/host/mesh/src/adv_legacy.c index 9a2ca83b..879ac2e0 100644 --- a/src/nimble/nimble/host/mesh/src/adv_legacy.c +++ b/src/nimble/nimble/host/mesh/src/adv_legacy.c @@ -7,9 +7,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_ADV_LOG #include "adv.h" @@ -18,7 +15,7 @@ #include "beacon.h" #include "prov.h" #include "proxy.h" -#include "../include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" #include "pb_gatt_srv.h" #ifndef min @@ -51,7 +48,7 @@ static int adv_initialized = false; /* TinyCrypt PRNG consumes a lot of stack space, so we need to have * an increased call stack whenever it's used. */ -#if MYNEWT +#ifdef MYNEWT OS_TASK_STACK_DEFINE(g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); struct os_task adv_task; #endif @@ -72,7 +69,7 @@ static inline void adv_send(struct os_mbuf *buf) struct bt_data ad; int err; - adv_int = max(adv_int_min, + adv_int = MAX(adv_int_min, BT_MESH_TRANSMIT_INT(BT_MESH_ADV(buf)->xmit)); #if MYNEWT_VAL(BLE_CONTROLLER) duration = ((BT_MESH_TRANSMIT_COUNT(BT_MESH_ADV(buf)->xmit) + 1) * @@ -225,7 +222,7 @@ void bt_mesh_adv_init(void) ble_npl_eventq_init(&bt_mesh_adv_queue); -#if MYNEWT +#ifdef MYNEWT os_task_init(&adv_task, "mesh_adv", mesh_adv_thread, NULL, MYNEWT_VAL(BLE_MESH_ADV_TASK_PRIO), OS_WAIT_FOREVER, g_blemesh_stack, MYNEWT_VAL(BLE_MESH_ADV_STACK_SIZE)); @@ -253,5 +250,3 @@ int bt_mesh_adv_start(const struct ble_gap_adv_params *param, int32_t duration, return bt_le_adv_start(param, ad, ad_len, sd, sd_len); } #endif - -#endif // MYNEWT_VAL(BLE_MESH_ADV_EXT) \ No newline at end of file diff --git a/src/nimble/nimble/host/mesh/src/aes-ccm.c b/src/nimble/nimble/host/mesh/src/aes-ccm.c index 2bc7e1ac..ab23c264 100644 --- a/src/nimble/nimble/host/mesh/src/aes-ccm.c +++ b/src/nimble/nimble/host/mesh/src/aes-ccm.c @@ -5,9 +5,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #include "crypto.h" #define MESH_LOG_MODULE BLE_MESH_LOG @@ -225,5 +222,3 @@ int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t *msg, return 0; } - -#endif /* MYNEWT_VAL(BLE_MESH) */ \ No newline at end of file diff --git a/src/nimble/nimble/host/mesh/src/app_keys.c b/src/nimble/nimble/host/mesh/src/app_keys.c index e64a4ed5..52d14d23 100644 --- a/src/nimble/nimble/host/mesh/src/app_keys.c +++ b/src/nimble/nimble/host/mesh/src/app_keys.c @@ -5,12 +5,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #include #include -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "mesh_priv.h" #include "net.h" #include "app_keys.h" @@ -718,4 +715,3 @@ void bt_mesh_app_key_init(void) "Failed to register bt_mesh_app_key conf"); #endif } -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/app_keys.h b/src/nimble/nimble/host/mesh/src/app_keys.h index 6255f7c6..d936e8a8 100644 --- a/src/nimble/nimble/host/mesh/src/app_keys.h +++ b/src/nimble/nimble/host/mesh/src/app_keys.h @@ -7,7 +7,7 @@ #ifndef _BT_MESH_APP_KEYS_H_ #define _BT_MESH_APP_KEYS_H_ -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "subnet.h" /** @brief Reset the app keys module. */ diff --git a/src/nimble/nimble/host/mesh/src/beacon.c b/src/nimble/nimble/host/mesh/src/beacon.c index f6cba91a..c5bfb680 100644 --- a/src/nimble/nimble/host/mesh/src/beacon.c +++ b/src/nimble/nimble/host/mesh/src/beacon.c @@ -7,14 +7,12 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_BEACON_LOG #include #include #include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "adv.h" #include "mesh_priv.h" @@ -472,4 +470,3 @@ void bt_mesh_beacon_disable(void) (void)k_work_cancel_delayable(&beacon_timer); } } -#endif diff --git a/src/nimble/nimble/host/mesh/src/cdb.c b/src/nimble/nimble/host/mesh/src/cdb.c index 25d4f850..05ee464b 100644 --- a/src/nimble/nimble/host/mesh/src/cdb.c +++ b/src/nimble/nimble/host/mesh/src/cdb.c @@ -4,9 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_LOG #include "nimble/porting/nimble/include/log/log.h" #include @@ -16,7 +13,7 @@ #include "rpl.h" #include "settings.h" #include "mesh_priv.h" -#include "../include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" #if MYNEWT_VAL(BLE_MESH_CDB) /* Tracking of what storage changes are pending for App and Net Keys. We @@ -1143,5 +1140,3 @@ void bt_mesh_cdb_init(void) #endif } #endif - -#endif // MYNEWT_VAL(BLE_MESH) \ No newline at end of file diff --git a/src/nimble/nimble/host/mesh/src/cfg.c b/src/nimble/nimble/host/mesh/src/cfg.c index 78264873..d0140348 100644 --- a/src/nimble/nimble/host/mesh/src/cfg.c +++ b/src/nimble/nimble/host/mesh/src/cfg.c @@ -4,10 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "mesh_priv.h" #include "net.h" #include "rpl.h" @@ -16,7 +13,7 @@ #include "heartbeat.h" #include "friend.h" #include "cfg.h" -#include "../include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" #define MESH_LOG_MODULE BLE_MESH_LOG #include "nimble/porting/nimble/include/log/log.h" @@ -389,5 +386,3 @@ void bt_mesh_cfg_default_set(void) atomic_set_bit(bt_mesh.flags, BT_MESH_FRIEND); } } - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/cfg_cli.c b/src/nimble/nimble/host/mesh/src/cfg_cli.c index f823c43b..f7590e20 100644 --- a/src/nimble/nimble/host/mesh/src/cfg_cli.c +++ b/src/nimble/nimble/host/mesh/src/cfg_cli.c @@ -7,12 +7,10 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #if MYNEWT_VAL(BLE_MESH_CFG_CLI) -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include #include @@ -54,7 +52,7 @@ static int comp_data_status(struct bt_mesh_model *model, if (param->page) { *(param->page) = net_buf_simple_pull_u8(buf); } - to_copy = min(net_buf_simple_tailroom(param->comp), buf->om_len); + to_copy = MIN(net_buf_simple_tailroom(param->comp), buf->om_len); net_buf_simple_add_mem(param->comp, buf->om_data, to_copy); bt_mesh_msg_ack_ctx_rx(&cli->ack_ctx); @@ -2714,4 +2712,3 @@ struct bt_mesh_mod_id_vnd bt_mesh_comp_p0_elem_mod_vnd(struct bt_mesh_comp_p0_el return mod; } #endif -#endif \ No newline at end of file diff --git a/src/nimble/nimble/host/mesh/src/cfg_srv.c b/src/nimble/nimble/host/mesh/src/cfg_srv.c index 2ccfe258..4fa936d3 100644 --- a/src/nimble/nimble/host/mesh/src/cfg_srv.c +++ b/src/nimble/nimble/host/mesh/src/cfg_srv.c @@ -7,15 +7,13 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #include #include #include -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" @@ -31,6 +29,7 @@ #include "proxy.h" #include "foundation.h" #include "friend.h" +#include "testing.h" #include "settings.h" #include "cfg.h" @@ -1964,6 +1963,10 @@ static int mod_app_bind(struct bt_mesh_model *model, status = mod_bind(mod, key_app_idx); + if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) { + bt_test_mesh_model_bound(ctx->addr, mod, key_app_idx); + } + send_status: BT_DBG("status 0x%02x", status); create_mod_app_status(msg, mod, vnd, elem_addr, key_app_idx, status, @@ -2022,6 +2025,10 @@ static int mod_app_unbind(struct bt_mesh_model *model, status = mod_unbind(mod, key_app_idx, true); + if (IS_ENABLED(CONFIG_BT_TESTING) && status == STATUS_SUCCESS) { + bt_test_mesh_model_unbound(ctx->addr, mod, key_app_idx); + } + send_status: BT_DBG("status 0x%02x", status); create_mod_app_status(msg, mod, vnd, elem_addr, key_app_idx, status, @@ -2043,7 +2050,7 @@ static int mod_app_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx, struct os_mbuf *buf) { - struct os_mbuf *msg = NET_BUF_SIMPLE(max(BT_MESH_MODEL_BUF_LEN(OP_VND_MOD_APP_LIST, + struct os_mbuf *msg = NET_BUF_SIMPLE(MAX(BT_MESH_MODEL_BUF_LEN(OP_VND_MOD_APP_LIST, 9 + KEY_LIST_LEN), BT_MESH_MODEL_BUF_LEN(OP_SIG_MOD_APP_LIST, 9 + KEY_LIST_LEN))); @@ -2636,4 +2643,3 @@ void bt_mesh_model_reset(void) { bt_mesh_model_foreach(mod_reset, NULL); } -#endif \ No newline at end of file diff --git a/src/nimble/nimble/host/mesh/src/crypto.c b/src/nimble/nimble/host/mesh/src/crypto.c index cc75f65f..e5392287 100644 --- a/src/nimble/nimble/host/mesh/src/crypto.c +++ b/src/nimble/nimble/host/mesh/src/crypto.c @@ -7,16 +7,15 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_CRYPTO_LOG #include #include #include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #if (MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS)) -#include "mbedtls/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" #include "mbedtls/cipher.h" #include "mbedtls/entropy.h" #include "mbedtls/ctr_drbg.h" @@ -25,11 +24,11 @@ #include "mbedtls/ecp.h" #else -#include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" -#include "nimble/ext/tinycrypt/include/tinycrypt/ccm_mode.h" +#include +#include +#include +#include +#include #endif #include "crypto.h" @@ -604,4 +603,3 @@ int bt_mesh_beacon_auth(const uint8_t beacon_key[16], uint8_t flags, return err; } -#endif diff --git a/src/nimble/nimble/host/mesh/src/crypto.h b/src/nimble/nimble/host/mesh/src/crypto.h index 4fbbc119..37098301 100644 --- a/src/nimble/nimble/host/mesh/src/crypto.h +++ b/src/nimble/nimble/host/mesh/src/crypto.h @@ -8,7 +8,7 @@ #ifndef __CRYPTO_H__ #define __CRYPTO_H__ -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" struct bt_mesh_sg { const void *data; diff --git a/src/nimble/nimble/host/mesh/src/friend.c b/src/nimble/nimble/host/mesh/src/friend.c index ec971277..694c3c33 100644 --- a/src/nimble/nimble/host/mesh/src/friend.c +++ b/src/nimble/nimble/host/mesh/src/friend.c @@ -7,8 +7,6 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_FRIEND_LOG #if MYNEWT_VAL(BLE_MESH_FRIEND) @@ -17,9 +15,9 @@ #include #include -#include "../include/mesh/mesh.h" -#include "../include/mesh/slist.h" -#include "../include/mesh_priv.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/slist.h" +#include "mesh_priv.h" #include "crypto.h" #include "adv.h" #include "net.h" @@ -1688,9 +1686,9 @@ void bt_mesh_friend_enqueue_rx(struct bt_mesh_net_rx *rx, continue; } - if (friend_lpn_matches(frnd, rx->sub->net_idx, - rx->ctx.addr)) { - continue; + if (friend_lpn_matches(frnd, rx->sub->net_idx, + rx->ctx.addr)) { + continue; } if (friend_lpn_matches(frnd, rx->sub->net_idx, @@ -1791,5 +1789,3 @@ void bt_mesh_friend_clear_incomplete(struct bt_mesh_subnet *sub, uint16_t src, } #endif /* MYNEWT_VAL(BLE_MESH_FRIEND) */ - -#endif /* MYNEWT_VAL(BLE_MESH) */ \ No newline at end of file diff --git a/src/nimble/nimble/host/mesh/src/friend.h b/src/nimble/nimble/host/mesh/src/friend.h index 04998c2e..9e79f966 100644 --- a/src/nimble/nimble/host/mesh/src/friend.h +++ b/src/nimble/nimble/host/mesh/src/friend.h @@ -9,7 +9,7 @@ #ifndef __FRIEND_H__ #define __FRIEND_H__ -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" enum bt_mesh_friend_pdu_type { BT_MESH_FRIEND_PDU_SINGLE, diff --git a/src/nimble/nimble/host/mesh/src/glue.c b/src/nimble/nimble/host/mesh/src/glue.c index 617768ac..ad166568 100644 --- a/src/nimble/nimble/host/mesh/src/glue.c +++ b/src/nimble/nimble/host/mesh/src/glue.c @@ -18,13 +18,11 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_LOG -#include "../include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" #include "adv.h" -#include "../../src/ble_hs_conn_priv.h" +#include "nimble/nimble/host/src/ble_hs_conn_priv.h" #ifndef MYNEWT #include "nimble/porting/nimble/include/nimble/nimble_port.h" #endif @@ -63,7 +61,7 @@ bt_hex(const void *buf, size_t len) str = hexbufs[curbuf++]; curbuf %= ARRAY_SIZE(hexbufs); - len = min(len, (sizeof(hexbufs[0]) - 1) / 2); + len = MIN(len, (sizeof(hexbufs[0]) - 1) / 2); for (i = 0; i < len; i++) { str[i * 2] = hex[b[i] >> 4]; @@ -1039,4 +1037,3 @@ char *settings_str_from_bytes(const void *vp, int vp_len, } #endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */ -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/health_cli.c b/src/nimble/nimble/host/mesh/src/health_cli.c index 75e08c15..4e5f49a7 100644 --- a/src/nimble/nimble/host/mesh/src/health_cli.c +++ b/src/nimble/nimble/host/mesh/src/health_cli.c @@ -7,21 +7,19 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #include #include #include -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" #include "net.h" #include "transport.h" #include "foundation.h" -#include "../include/mesh/health_cli.h" +#include "nimble/nimble/host/mesh/include/mesh/health_cli.h" static int32_t msg_timeout = K_SECONDS(5); @@ -525,4 +523,3 @@ static int health_cli_init(struct bt_mesh_model *model) const struct bt_mesh_model_cb bt_mesh_health_cli_cb = { .init = health_cli_init, }; -#endif diff --git a/src/nimble/nimble/host/mesh/src/health_srv.c b/src/nimble/nimble/host/mesh/src/health_srv.c index e202672b..33f31bed 100644 --- a/src/nimble/nimble/host/mesh/src/health_srv.c +++ b/src/nimble/nimble/host/mesh/src/health_srv.c @@ -7,15 +7,13 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG #include #include #include -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "mesh_priv.h" #include "adv.h" #include "net.h" @@ -475,4 +473,3 @@ void bt_mesh_attention(struct bt_mesh_model *model, uint8_t time) } k_work_reschedule(&srv->attn_timer, K_SECONDS(time)); } -#endif diff --git a/src/nimble/nimble/host/mesh/src/heartbeat.c b/src/nimble/nimble/host/mesh/src/heartbeat.c index 204206ee..4abb82bc 100644 --- a/src/nimble/nimble/host/mesh/src/heartbeat.c +++ b/src/nimble/nimble/host/mesh/src/heartbeat.c @@ -4,9 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_HEARTBEAT_LOG #include "mesh_priv.h" @@ -18,7 +15,7 @@ #include "transport.h" #include "heartbeat.h" #include "foundation.h" -#include "../include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" /* Heartbeat Publication information for persistent storage. */ struct hb_pub_val { @@ -286,7 +283,7 @@ uint8_t bt_mesh_hb_sub_set(uint16_t src, uint16_t dst, uint32_t period) } if (period > (1U << 16)) { - BT_WARN("Prohibited subscription period %u s", period); + BT_WARN("Prohibited subscription period %" PRIu32 "s", period); return STATUS_CANNOT_SET; } @@ -465,4 +462,3 @@ void bt_mesh_hb_pub_init(void) "Failed to register bt_mesh_hb_pub conf"); #endif } -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/heartbeat.h b/src/nimble/nimble/host/mesh/src/heartbeat.h index e84e21b3..c21afb88 100644 --- a/src/nimble/nimble/host/mesh/src/heartbeat.h +++ b/src/nimble/nimble/host/mesh/src/heartbeat.h @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "../include/mesh/heartbeat.h" +#include "nimble/nimble/host/mesh/include/mesh/heartbeat.h" static inline uint16_t bt_mesh_hb_pwr2(uint8_t val) { diff --git a/src/nimble/nimble/host/mesh/src/light_model.c b/src/nimble/nimble/host/mesh/src/light_model.c index fc8f6618..975262ff 100644 --- a/src/nimble/nimble/host/mesh/src/light_model.c +++ b/src/nimble/nimble/host/mesh/src/light_model.c @@ -1,8 +1,12 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "nimble/console/console.h" #include "light_model.h" @@ -56,4 +60,3 @@ int light_model_light_lightness_set(struct bt_mesh_model *model, int16_t lightne { return light_model_gen_level_set(model, lightness); } -#endif diff --git a/src/nimble/nimble/host/mesh/src/light_model.h b/src/nimble/nimble/host/mesh/src/light_model.h index 574db548..162b9b14 100644 --- a/src/nimble/nimble/host/mesh/src/light_model.h +++ b/src/nimble/nimble/host/mesh/src/light_model.h @@ -7,7 +7,7 @@ #define __BT_MESH_LIGHT_MODEL_H #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" int light_model_gen_onoff_get(struct bt_mesh_model *model, uint8_t *state); int light_model_gen_onoff_set(struct bt_mesh_model *model, uint8_t state); diff --git a/src/nimble/nimble/host/mesh/src/lpn.c b/src/nimble/nimble/host/mesh/src/lpn.c index d0a01af7..ea0276ff 100644 --- a/src/nimble/nimble/host/mesh/src/lpn.c +++ b/src/nimble/nimble/host/mesh/src/lpn.c @@ -7,15 +7,13 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_LOW_POWER_LOG #if MYNEWT_VAL(BLE_MESH_LOW_POWER) #include -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "mesh_priv.h" #include "crypto.h" #include "adv.h" @@ -34,7 +32,7 @@ #endif #define LPN_RECV_DELAY MYNEWT_VAL(BLE_MESH_LPN_RECV_DELAY) -#define SCAN_LATENCY min(MYNEWT_VAL(BLE_MESH_LPN_SCAN_LATENCY), \ +#define SCAN_LATENCY MIN(MYNEWT_VAL(BLE_MESH_LPN_SCAN_LATENCY), \ LPN_RECV_DELAY) #define FRIEND_REQ_RETRY_TIMEOUT K_SECONDS(MYNEWT_VAL(BLE_MESH_LPN_RETRY_TIMEOUT)) @@ -154,12 +152,12 @@ static int32_t poll_timeout(struct bt_mesh_lpn *lpn) { /* If we're waiting for segment acks keep polling at high freq */ if (bt_mesh_tx_in_progress()) { - return min(POLL_TIMEOUT_MAX(lpn), K_SECONDS(1)); + return MIN(POLL_TIMEOUT_MAX(lpn), K_SECONDS(1)); } if (lpn->poll_timeout < POLL_TIMEOUT_MAX(lpn)) { lpn->poll_timeout *= 2; - lpn->poll_timeout = min(lpn->poll_timeout, + lpn->poll_timeout = MIN(lpn->poll_timeout, POLL_TIMEOUT_MAX(lpn)); } @@ -1002,7 +1000,7 @@ int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, } /* Set initial poll timeout */ - lpn->poll_timeout = min(POLL_TIMEOUT_MAX(lpn), + lpn->poll_timeout = MIN(POLL_TIMEOUT_MAX(lpn), POLL_TIMEOUT_INIT); } @@ -1101,4 +1099,3 @@ int bt_mesh_lpn_init(void) } #endif /* MYNEWT_VAL(BLE_MESH_LOW_POWER) */ -#endif diff --git a/src/nimble/nimble/host/mesh/src/lpn.h b/src/nimble/nimble/host/mesh/src/lpn.h index 37f57bca..3abbc705 100644 --- a/src/nimble/nimble/host/mesh/src/lpn.h +++ b/src/nimble/nimble/host/mesh/src/lpn.h @@ -8,7 +8,7 @@ #ifndef __LPN_H__ #define __LPN_H__ -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" int bt_mesh_lpn_friend_update(struct bt_mesh_net_rx *rx, struct os_mbuf *buf); diff --git a/src/nimble/nimble/host/mesh/src/mesh.c b/src/nimble/nimble/host/mesh/src/mesh.c index 12461d95..8208fe4c 100644 --- a/src/nimble/nimble/host/mesh/src/mesh.c +++ b/src/nimble/nimble/host/mesh/src/mesh.c @@ -7,15 +7,13 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_LOG #include #include #include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "nimble/nimble/host/include/host/ble_uuid.h" #include "adv.h" @@ -416,4 +414,3 @@ int bt_mesh_start(void) return 0; } -#endif diff --git a/src/nimble/nimble/host/mesh/src/model_cli.c b/src/nimble/nimble/host/mesh/src/model_cli.c index 294691d9..ef8b0cec 100644 --- a/src/nimble/nimble/host/mesh/src/model_cli.c +++ b/src/nimble/nimble/host/mesh/src/model_cli.c @@ -5,12 +5,10 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG -#include "../include/mesh/mesh.h" -#include "../include/mesh/model_cli.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/model_cli.h" #include "mesh_priv.h" static int32_t msg_timeout = K_SECONDS(5); @@ -304,4 +302,3 @@ int bt_mesh_gen_level_set(uint16_t net_idx, uint16_t addr, uint16_t app_idx, os_mbuf_free_chain(msg); return err; } -#endif diff --git a/src/nimble/nimble/host/mesh/src/model_srv.c b/src/nimble/nimble/host/mesh/src/model_srv.c index 0c0948b7..1666cad6 100644 --- a/src/nimble/nimble/host/mesh/src/model_srv.c +++ b/src/nimble/nimble/host/mesh/src/model_srv.c @@ -5,12 +5,10 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_MODEL_LOG -#include "../include/mesh/mesh.h" -#include "../include/mesh/model_srv.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/model_srv.h" #include "mesh_priv.h" static struct bt_mesh_gen_onoff_srv *gen_onoff_srv; @@ -282,4 +280,3 @@ static int lightness_srv_init(struct bt_mesh_model *model) const struct bt_mesh_model_cb light_lightness_srv_cb = { .init = lightness_srv_init, }; -#endif diff --git a/src/nimble/nimble/host/mesh/src/msg.c b/src/nimble/nimble/host/mesh/src/msg.c index be1e1857..7c6270ff 100644 --- a/src/nimble/nimble/host/mesh/src/msg.c +++ b/src/nimble/nimble/host/mesh/src/msg.c @@ -6,10 +6,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" void bt_mesh_model_msg_init(struct os_mbuf *msg, uint32_t opcode) { @@ -85,5 +82,3 @@ bool bt_mesh_msg_ack_ctx_match(const struct bt_mesh_msg_ack_ctx *ack, return true; } - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/net.c b/src/nimble/nimble/host/mesh/src/net.c index d8bcc4f6..3f780435 100644 --- a/src/nimble/nimble/host/mesh/src/net.c +++ b/src/nimble/nimble/host/mesh/src/net.c @@ -7,8 +7,6 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_NET_LOG #include @@ -16,7 +14,7 @@ #include #include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "crypto.h" #include "adv.h" @@ -33,8 +31,8 @@ #include "settings.h" #include "prov.h" #include "cfg.h" -#include "../include/mesh/glue.h" -#include "../include/mesh/slist.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/slist.h" #define LOOPBACK_MAX_PDU_LEN (BT_MESH_NET_HDR_LEN + 16) #define LOOPBACK_USER_DATA_SIZE sizeof(struct bt_mesh_subnet *) @@ -1223,4 +1221,3 @@ void bt_mesh_net_settings_commit(void) k_work_reschedule(&bt_mesh.ivu_timer, BT_MESH_IVU_TIMEOUT); } } -#endif diff --git a/src/nimble/nimble/host/mesh/src/net.h b/src/nimble/nimble/host/mesh/src/net.h index 5c6c0557..e6b89cda 100644 --- a/src/nimble/nimble/host/mesh/src/net.h +++ b/src/nimble/nimble/host/mesh/src/net.h @@ -16,8 +16,8 @@ #include #include "atomic.h" -#include "../include/mesh/mesh.h" -#include "../include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" /* How many hours in between updating IVU duration */ #define BT_MESH_IVU_MIN_HOURS 96 diff --git a/src/nimble/nimble/host/mesh/src/nodes.c b/src/nimble/nimble/host/mesh/src/nodes.c deleted file mode 100644 index 199550d9..00000000 --- a/src/nimble/nimble/host/mesh/src/nodes.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2019 Tobias Svehagen - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - -#define MESH_LOG_MODULE BLE_MESH_PROV_LOG - -#if MYNEWT_VAL(BLE_MESH_PROVISIONER) - -#include "../include/mesh/mesh.h" - -#include "mesh_priv.h" -#include "net.h" -#include "access.h" -#include "settings.h" - -/* - * Check if an address range from addr_start for addr_start + num_elem - 1 is - * free for use. When a conflict is found, next will be set to the next address - * available after the conflicting range and -EAGAIN will be returned. - */ -static int addr_is_free(u16_t addr_start, u8_t num_elem, u16_t *next) -{ - const struct bt_mesh_comp *comp = bt_mesh_comp_get(); - u16_t addr_end = addr_start + num_elem - 1; - u16_t other_start, other_end; - int i; - - if (comp == NULL) { - return -EINVAL; - } - - if (!BT_MESH_ADDR_IS_UNICAST(addr_start) || - !BT_MESH_ADDR_IS_UNICAST(addr_end) || - num_elem == 0 || next == NULL) { - return -EINVAL; - } - - other_start = bt_mesh_primary_addr(); - other_end = other_start + comp->elem_count - 1; - - /* Compare with local element addresses */ - if (!(addr_end < other_start || addr_start > other_end)) { - *next = other_end + 1; - return -EAGAIN; - } - - for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) { - struct bt_mesh_node *node = &bt_mesh.nodes[i]; - - if (node->net_idx == BT_MESH_KEY_UNUSED) { - continue; - } - - other_start = node->addr; - other_end = other_start + node->num_elem - 1; - - if (!(addr_end < other_start || addr_start > other_end)) { - *next = other_end + 1; - return -EAGAIN; - } - } - - return 0; -} - -/* - * Find the lowest possible starting address that can fit num_elem elements. If - * a free address range cannot be found, BT_MESH_ADDR_UNASSIGNED will be - * returned. Otherwise the first address in the range is returned. - * - * NOTE: This is quite an ineffective algorithm as it might need to look - * through the array of nodes N+2 times. A more effective algorithm - * could be used if the nodes were stored in a sorted list. - */ -static u16_t find_lowest_free_addr(u8_t num_elem) -{ - u16_t addr = 1, next; - int err, i; - - /* - * It takes a maximum of node count + 2 to find a free address if there - * is any. +1 for our own address and +1 for making sure that the - * address range is valid. - */ - for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes) + 2; ++i) { - err = addr_is_free(addr, num_elem, &next); - if (err == 0) { - break; - } else if (err != -EAGAIN) { - addr = BT_MESH_ADDR_UNASSIGNED; - break; - } - - addr = next; - } - - return addr; -} - -struct bt_mesh_node *bt_mesh_node_find(u16_t addr) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) { - struct bt_mesh_node *node = &bt_mesh.nodes[i]; - - if (addr >= node->addr && - addr <= node->addr + node->num_elem - 1) { - return node; - } - } - - return NULL; -} - -struct bt_mesh_node *bt_mesh_node_alloc(u16_t addr, u8_t num_elem, - u16_t net_idx) -{ - int i; - - BT_DBG(""); - - if (addr == BT_MESH_ADDR_UNASSIGNED) { - addr = find_lowest_free_addr(num_elem); - if (addr == BT_MESH_ADDR_UNASSIGNED) { - return NULL; - } - } else if (!addr_is_free(addr, num_elem, NULL)) { - return NULL; - } - - for (i = 0; i < ARRAY_SIZE(bt_mesh.nodes); i++) { - struct bt_mesh_node *node = &bt_mesh.nodes[i]; - - if (node->addr == BT_MESH_ADDR_UNASSIGNED) { - node->addr = addr; - node->num_elem = num_elem; - node->net_idx = net_idx; - return node; - } - } - - return NULL; -} - -void bt_mesh_node_del(struct bt_mesh_node *node, bool store) -{ - BT_DBG("Node addr 0x%04x store %u", node->addr, store); - - if (IS_ENABLED(CONFIG_BT_SETTINGS) && store) { - bt_mesh_clear_node(node); - } - - node->addr = BT_MESH_ADDR_UNASSIGNED; - (void)memset(node->dev_key, 0, sizeof(node->dev_key)); -} - -#endif -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/nodes.h b/src/nimble/nimble/host/mesh/src/nodes.h deleted file mode 100644 index f86193d9..00000000 --- a/src/nimble/nimble/host/mesh/src/nodes.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2019 Tobias Svehagen - * - * SPDX-License-Identifier: Apache-2.0 - */ - -struct bt_mesh_node *bt_mesh_node_find(u16_t addr); -struct bt_mesh_node *bt_mesh_node_alloc(u16_t addr, u8_t num_elem, - u16_t net_idx); -void bt_mesh_node_del(struct bt_mesh_node *node, bool store); \ No newline at end of file diff --git a/src/nimble/nimble/host/mesh/src/pb_adv.c b/src/nimble/nimble/host/mesh/src/pb_adv.c index 8929cbab..be8977fa 100644 --- a/src/nimble/nimble/host/mesh/src/pb_adv.c +++ b/src/nimble/nimble/host/mesh/src/pb_adv.c @@ -8,21 +8,19 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_PROV_LOG #include #include -#include "../include/mesh/mesh.h" -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "../include/mesh/testing.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" +#include +#include "testing.h" #include "net.h" #include "prov.h" #include "adv.h" #include "crypto.h" #include "beacon.h" -#include "../include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" #define GPCF(gpc) (gpc & 0x03) #define GPC_START(last_seg) (((last_seg) << 2) | 0x00) @@ -32,6 +30,7 @@ #define START_PAYLOAD_MAX 20 #define CONT_PAYLOAD_MAX 23 +#define RX_BUFFER_MAX 65 #define START_LAST_SEG(gpc) (gpc >> 2) #define CONT_SEG_INDEX(gpc) (gpc >> 2) @@ -41,7 +40,8 @@ #define LINK_ACK 0x01 #define LINK_CLOSE 0x02 -#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[20 + ((_seg - 1) * 23)]) +#define XACT_SEG_OFFSET(_seg) (20 + ((_seg - 1) * 23)) +#define XACT_SEG_DATA(_seg) (&link.rx.buf->om_data[XACT_SEG_OFFSET(_seg)]) #define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg))) #define XACT_ID_MAX 0x7f @@ -224,7 +224,7 @@ static void reset_adv_link(void) } link.tx.pending_ack = XACT_ID_NVAL; if (!rx_buf) { - rx_buf = NET_BUF_SIMPLE(65); + rx_buf = NET_BUF_SIMPLE(RX_BUFFER_MAX); } link.rx.buf = rx_buf; net_buf_simple_reset(link.rx.buf); @@ -388,6 +388,11 @@ static void gen_prov_cont(struct prov_rx *rx, struct os_mbuf *buf) return; } + if (XACT_SEG_OFFSET(seg) + buf->om_len > RX_BUFFER_MAX) { + BT_WARN("Rx buffer overflow. Malformed generic prov frame?"); + return; + } + memcpy(XACT_SEG_DATA(seg), buf->om_data, buf->om_len); XACT_SEG_RECV(seg); @@ -520,6 +525,11 @@ static void gen_prov_ctl(struct prov_rx *rx, struct os_mbuf *buf) break; default: BT_ERR("Unknown bearer opcode: 0x%02x", BEARER_CTL(rx->gpc)); + + if (IS_ENABLED(CONFIG_BT_TESTING)) { + bt_test_mesh_prov_invalid_bearer(BEARER_CTL(rx->gpc)); + } + return; } } @@ -887,7 +897,7 @@ void pb_adv_init(void) k_work_init_delayable(&link.tx.retransmit, prov_retransmit); if (!rx_buf) { - rx_buf = NET_BUF_SIMPLE(65); + rx_buf = NET_BUF_SIMPLE(RX_BUFFER_MAX); } link.rx.buf = rx_buf; net_buf_simple_reset(link.rx.buf); @@ -906,5 +916,3 @@ const struct prov_bearer pb_adv = { .send = prov_send_adv, .clear_tx = prov_clear_tx, }; - -#endif /* MYNEWT_VAL(BLE_MESH) */ \ No newline at end of file diff --git a/src/nimble/nimble/host/mesh/src/pb_gatt.c b/src/nimble/nimble/host/mesh/src/pb_gatt.c index da65b959..0d0a5db7 100644 --- a/src/nimble/nimble/host/mesh/src/pb_gatt.c +++ b/src/nimble/nimble/host/mesh/src/pb_gatt.c @@ -7,12 +7,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_PROV_LOG -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "prov.h" #include "net.h" #include "proxy.h" @@ -175,5 +172,3 @@ const struct prov_bearer pb_gatt = { .clear_tx = clear_tx, }; #endif - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/pb_gatt_srv.c b/src/nimble/nimble/host/mesh/src/pb_gatt_srv.c index e1473536..ab75442c 100644 --- a/src/nimble/nimble/host/mesh/src/pb_gatt_srv.c +++ b/src/nimble/nimble/host/mesh/src/pb_gatt_srv.c @@ -5,9 +5,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_PROV_LOG #include "mesh_priv.h" @@ -466,5 +463,3 @@ int bt_mesh_pb_gatt_adv_start(void) return err; } #endif - -#endif /* MYNEWT_VAL(BLE_MESH) */ \ No newline at end of file diff --git a/src/nimble/nimble/host/mesh/src/prov.c b/src/nimble/nimble/host/mesh/src/prov.c index 4a36970c..204c0940 100644 --- a/src/nimble/nimble/host/mesh/src/prov.c +++ b/src/nimble/nimble/host/mesh/src/prov.c @@ -7,13 +7,11 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_PROV_LOG #include -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "mesh_priv.h" #include "crypto.h" @@ -22,7 +20,7 @@ #include "access.h" #include "foundation.h" #include "prov.h" -#include "../include/mesh/testing.h" +#include "testing.h" struct bt_mesh_prov_link bt_mesh_prov_link; const struct bt_mesh_prov *bt_mesh_prov; @@ -459,5 +457,3 @@ int bt_mesh_prov_init(const struct bt_mesh_prov *prov_info) return bt_mesh_prov_reset_state(NULL); } - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/prov.h b/src/nimble/nimble/host/mesh/src/prov.h index fb283b7c..5b7b4b87 100644 --- a/src/nimble/nimble/host/mesh/src/prov.h +++ b/src/nimble/nimble/host/mesh/src/prov.h @@ -11,7 +11,7 @@ #include "prov_bearer.h" #include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "nimble/nimble/host/src/ble_hs_conn_priv.h" #define PROV_ERR_NONE 0x00 diff --git a/src/nimble/nimble/host/mesh/src/prov_device.c b/src/nimble/nimble/host/mesh/src/prov_device.c index 464467ce..013dade1 100644 --- a/src/nimble/nimble/host/mesh/src/prov_device.c +++ b/src/nimble/nimble/host/mesh/src/prov_device.c @@ -7,14 +7,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_PROV_LOG +#include "testing.h" #include "crypto.h" #include "adv.h" -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "net.h" #include "rpl.h" #include "beacon.h" @@ -305,11 +303,11 @@ static void prov_dh_key_gen(void) #if !CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS if (MYNEWT_VAL(BLE_MESH_PROV_OOB_PUBLIC_KEY) && atomic_test_bit(bt_mesh_prov_link.flags, OOB_PUB_KEY)) { - if (uECC_valid_public_key(remote_pk, &curve_secp256r1)) { + if (uECC_valid_public_key(remote_pk, uECC_secp256r1())) { BT_ERR("Public key is not valid"); } else if (uECC_shared_secret(remote_pk, bt_mesh_prov->private_key_be, bt_mesh_prov_link.dhkey, - &curve_secp256r1) != TC_CRYPTO_SUCCESS) { + uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { BT_ERR("DHKey generation failed"); } else { dh_key_gen_complete(); @@ -636,5 +634,3 @@ int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers) return 0; } - -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/provisioner.c b/src/nimble/nimble/host/mesh/src/provisioner.c index f84b63a7..fcc72864 100644 --- a/src/nimble/nimble/host/mesh/src/provisioner.c +++ b/src/nimble/nimble/host/mesh/src/provisioner.c @@ -8,14 +8,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_PROV_LOG +#include "testing.h" + #include "crypto.h" #include "adv.h" -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "net.h" #include "rpl.h" #include "beacon.h" @@ -750,4 +749,3 @@ int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr, return err; } #endif -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/proxy.c b/src/nimble/nimble/host/mesh/src/proxy.c index 50214dfd..a2784a9c 100644 --- a/src/nimble/nimble/host/mesh/src/proxy.c +++ b/src/nimble/nimble/host/mesh/src/proxy.c @@ -7,13 +7,11 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_PROXY_LOG #if MYNEWT_VAL(BLE_MESH_PROXY) -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "nimble/nimble/host/include/host/ble_att.h" #include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" #include "nimble/nimble/host/src/ble_hs_priv.h" @@ -1576,4 +1574,3 @@ void bt_mesh_proxy_on_idle(struct bt_mesh_proxy_idle_cb *cb) } #endif /* MYNEWT_VAL(BLE_MESH_PROXY) */ -#endif diff --git a/src/nimble/nimble/host/mesh/src/proxy.h b/src/nimble/nimble/host/mesh/src/proxy.h index 35c63d89..0f86e1c7 100644 --- a/src/nimble/nimble/host/mesh/src/proxy.h +++ b/src/nimble/nimble/host/mesh/src/proxy.h @@ -9,7 +9,7 @@ #ifndef __PROXY_H__ #define __PROXY_H__ -#include "../include/mesh/slist.h" +#include "nimble/nimble/host/mesh/include/mesh/slist.h" #if CONFIG_BT_MESH_DEBUG_USE_ID_ADDR #define ADV_OPT_USE_IDENTITY BT_LE_ADV_OPT_USE_IDENTITY diff --git a/src/nimble/nimble/host/mesh/src/proxy_msg.c b/src/nimble/nimble/host/mesh/src/proxy_msg.c index db2c272d..bf9a6f1e 100644 --- a/src/nimble/nimble/host/mesh/src/proxy_msg.c +++ b/src/nimble/nimble/host/mesh/src/proxy_msg.c @@ -8,14 +8,14 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH_PROXY) - #define MESH_LOG_MODULE BLE_MESH_PROXY_LOG -#include "../include/mesh/mesh.h" +#if MYNEWT_VAL(BLE_MESH_PROXY) + +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "nimble/nimble/host/include/host/ble_att.h" #include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" -#include "../../host/src/ble_hs_priv.h" +#include "nimble/nimble/host/src/ble_hs_priv.h" #include "mesh_priv.h" #include "adv.h" diff --git a/src/nimble/nimble/host/mesh/src/proxy_srv.c b/src/nimble/nimble/host/mesh/src/proxy_srv.c index 09d7c4ed..76c66edf 100644 --- a/src/nimble/nimble/host/mesh/src/proxy_srv.c +++ b/src/nimble/nimble/host/mesh/src/proxy_srv.c @@ -7,13 +7,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH_PROXY) - #define MESH_LOG_MODULE BLE_MESH_PROXY_LOG -#include "../include/mesh/slist.h" -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/slist.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "nimble/nimble/host/src/ble_hs_priv.h" #include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" @@ -272,7 +269,7 @@ static void proxy_cfg(struct bt_mesh_proxy_role *role) rx.local_match = 1U; if (bt_mesh_rpl_check(&rx, NULL)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06lx", + BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06" PRIx32, rx.ctx.addr, rx.ctx.recv_dst, rx.seq); return; } @@ -592,8 +589,8 @@ static int gatt_proxy_advertise(struct bt_mesh_subnet *sub) * 6 slices, but make sure that a slice is at least one * second long (to avoid excessive rotation). */ - max_timeout = NODE_ID_TIMEOUT / max(subnet_count, 6); - max_timeout = max(max_timeout, K_SECONDS(1)); + max_timeout = NODE_ID_TIMEOUT / MAX(subnet_count, 6); + max_timeout = MAX(max_timeout, K_SECONDS(1)); if (remaining > max_timeout || remaining < 0) { remaining = max_timeout; @@ -942,9 +939,11 @@ static void ble_mesh_handle_connect(struct ble_gap_event *event, void *arg) return; } +#if MYNEWT_VAL(BLE_MESH_PROXY) if (event->adv_complete.instance != BT_MESH_ADV_GATT_INST) { return; } +#endif gatt_connected(event->adv_complete.conn_handle); #if MYNEWT_VAL(BLE_MESH_PB_GATT) @@ -1014,5 +1013,3 @@ int bt_mesh_proxy_init(void) return 0; } - -#endif //MYNEWT_VAL(BLE_MESH_PROXY) \ No newline at end of file diff --git a/src/nimble/nimble/host/mesh/src/rpl.c b/src/nimble/nimble/host/mesh/src/rpl.c index 95359aaf..2b7c2173 100644 --- a/src/nimble/nimble/host/mesh/src/rpl.c +++ b/src/nimble/nimble/host/mesh/src/rpl.c @@ -7,9 +7,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_RPL_LOG #include "nimble/porting/nimble/include/log/log.h" @@ -381,4 +378,3 @@ void bt_mesh_rpl_init(void) "Failed to register bt_mesh_rpl conf"); #endif } -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/settings.c b/src/nimble/nimble/host/mesh/src/settings.c index f1757744..2cb3dec1 100644 --- a/src/nimble/nimble/host/mesh/src/settings.c +++ b/src/nimble/nimble/host/mesh/src/settings.c @@ -5,14 +5,12 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_SETTINGS_LOG #if MYNEWT_VAL(BLE_MESH_SETTINGS) #include "mesh_priv.h" -#include "../include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" #include "subnet.h" #include "app_keys.h" #include "net.h" @@ -216,4 +214,3 @@ void bt_mesh_settings_init(void) } #endif /* MYNEWT_VAL(BLE_MESH_SETTINGS) */ -#endif diff --git a/src/nimble/nimble/host/mesh/src/shell.c b/src/nimble/nimble/host/mesh/src/shell.c index abe615b5..789d4a45 100644 --- a/src/nimble/nimble/host/mesh/src/shell.c +++ b/src/nimble/nimble/host/mesh/src/shell.c @@ -10,19 +10,18 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) #if MYNEWT_VAL(BLE_MESH_SHELL) #include #include #include -#include "shell/shell.h" -#include "console/console.h" -#include "mesh/mesh.h" -#include "mesh/main.h" -#include "mesh/glue.h" -#include "../include/mesh/testing.h" +#include "nimble/nimble/host/mesh/src/shell.h" +#include "nimble/console/console.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/main.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/testing.h" /* Private includes for raw Network & Transport layer access */ #include "net.h" @@ -32,11 +31,12 @@ #include "lpn.h" #include "transport.h" #include "foundation.h" +#include "testing.h" #include "settings.h" #if MYNEWT_VAL(BLE_MESH_SHELL_MODELS) -#include "mesh/model_srv.h" -#include "mesh/model_cli.h" +#include "nimble/nimble/host/mesh/include/mesh/model_srv.h" +#include "nimble/nimble/host/mesh/include/mesh/model_cli.h" #include "light_model.h" #endif @@ -3688,4 +3688,3 @@ void ble_mesh_shell_init(void) #endif } -#endif diff --git a/src/nimble/nimble/host/mesh/src/shell.h b/src/nimble/nimble/host/mesh/src/shell.h index 53cc83a2..98d3f8c6 100644 --- a/src/nimble/nimble/host/mesh/src/shell.h +++ b/src/nimble/nimble/host/mesh/src/shell.h @@ -1,3 +1,9 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + #ifndef __SHELL_H__ #define __SHELL_H__ diff --git a/src/nimble/nimble/host/mesh/src/subnet.c b/src/nimble/nimble/host/mesh/src/subnet.c index 5a9f6c4c..a6b784ac 100644 --- a/src/nimble/nimble/host/mesh/src/subnet.c +++ b/src/nimble/nimble/host/mesh/src/subnet.c @@ -4,17 +4,15 @@ * * SPDX-License-Identifier: Apache-2.0 */ - -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #define MESH_LOG_MODULE BLE_MESH_NET_KEYS_LOG #include "nimble/porting/nimble/include/log/log.h" + #include "crypto.h" #include "adv.h" -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #include "net.h" #include "mesh_priv.h" #include "lpn.h" @@ -233,7 +231,7 @@ static void key_refresh(struct bt_mesh_subnet *sub, uint8_t new_phase) if (sub->kr_phase == BT_MESH_KR_NORMAL) { return; } - /* __fallthrough; */ + /* fall through */ case BT_MESH_KR_NORMAL: sub->kr_phase = BT_MESH_KR_NORMAL; memcpy(&sub->keys[0], &sub->keys[1], sizeof(sub->keys[0])); @@ -428,7 +426,7 @@ uint8_t bt_mesh_subnet_update(uint16_t net_idx, const uint8_t key[16]) if (!memcmp(key, sub->keys[1].net, 16)) { return STATUS_SUCCESS; } - /* __fallthrough; */ + /* fall through */ case BT_MESH_KR_PHASE_2: case BT_MESH_KR_PHASE_3: return STATUS_CANNOT_UPDATE; @@ -885,4 +883,3 @@ void bt_mesh_net_key_init(void) "Failed to register bt_mesh_net_key conf"); #endif } -#endif /* MYNEWT_VAL(BLE_MESH) */ diff --git a/src/nimble/nimble/host/mesh/src/subnet.h b/src/nimble/nimble/host/mesh/src/subnet.h index 83b72532..b59c3ba4 100644 --- a/src/nimble/nimble/host/mesh/src/subnet.h +++ b/src/nimble/nimble/host/mesh/src/subnet.h @@ -9,7 +9,7 @@ #include #include -#include "../include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" #define BT_MESH_NET_FLAG_KR BIT(0) #define BT_MESH_NET_FLAG_IVU BIT(1) diff --git a/src/nimble/nimble/host/mesh/src/testing.c b/src/nimble/nimble/host/mesh/src/testing.c new file mode 100644 index 00000000..84690e6a --- /dev/null +++ b/src/nimble/nimble/host/mesh/src/testing.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "nimble/console/console.h" +#include "nimble/nimble/host/mesh/include/mesh/testing.h" +#include "nimble/nimble/host/mesh/include/mesh/slist.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/access.h" + +#include "net.h" +#include "app_keys.h" +#include "rpl.h" +#include "testing.h" +#include "access.h" +#include "foundation.h" +#include "lpn.h" +#include "transport.h" + +static sys_slist_t cb_slist; + +void bt_test_cb_register(struct bt_test_cb *cb) +{ + sys_slist_append(&cb_slist, &cb->node); +} + +void bt_test_cb_unregister(struct bt_test_cb *cb) +{ + sys_slist_find_and_remove(&cb_slist, &cb->node); +} + +void bt_test_mesh_net_recv(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, + const void *payload, size_t payload_len) +{ + struct bt_test_cb *cb; + + SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { + if (cb->mesh_net_recv) { + cb->mesh_net_recv(ttl, ctl, src, dst, payload, + payload_len); + } + } +} + +void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model, + uint16_t key_idx) +{ + struct bt_test_cb *cb; + + SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { + if (cb->mesh_model_bound) { + cb->mesh_model_bound(addr, model, key_idx); + } + } +} + +void bt_test_mesh_model_unbound(uint16_t addr, struct bt_mesh_model *model, + uint16_t key_idx) +{ + struct bt_test_cb *cb; + + SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { + if (cb->mesh_model_unbound) { + cb->mesh_model_unbound(addr, model, key_idx); + } + } +} + +void bt_test_mesh_prov_invalid_bearer(uint8_t opcode) +{ + struct bt_test_cb *cb; + + SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { + if (cb->mesh_prov_invalid_bearer) { + cb->mesh_prov_invalid_bearer(opcode); + } + } +} + +void bt_test_mesh_trans_incomp_timer_exp(void) +{ + struct bt_test_cb *cb; + + SYS_SLIST_FOR_EACH_CONTAINER(&cb_slist, cb, node) { + if (cb->mesh_trans_incomp_timer_exp) { + cb->mesh_trans_incomp_timer_exp(); + } + } +} + +int bt_test_mesh_lpn_group_add(uint16_t group) +{ + bt_mesh_lpn_group_add(group); + + return 0; +} + +int bt_test_mesh_lpn_group_remove(uint16_t *groups, size_t groups_count) +{ + bt_mesh_lpn_group_del(groups, groups_count); + + return 0; +} + +int bt_test_mesh_rpl_clear(void) +{ + bt_mesh_rpl_clear(); + + return 0; +} + +void bt_test_print_credentials(void) +{ + +#if MYNEWT_VAL(BLE_MESH_CDB) + int i; + struct bt_mesh_cdb_subnet *sub; + struct bt_mesh_cdb_app_key *app_key; + struct bt_mesh_subnet *subnet; +#endif + + console_printf("IV Index: %08lx\n", (long) bt_mesh.iv_index); + console_printf("Dev key: %s\n", bt_hex(bt_mesh.dev_key, 16)); + +#if MYNEWT_VAL(BLE_MESH_CDB) + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) + { + app_key = &bt_mesh_cdb.app_keys[i]; + if (app_key->net_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + sub = bt_mesh_cdb_subnet_get(i); + + console_printf("Subnet: %d\n", i); + console_printf("\tNetKeyIdx: %04x\n", + sub->net_idx); + } + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.app_keys); ++i) + { + app_key = &bt_mesh_cdb.app_keys[i]; + if (app_key->net_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + sub = bt_mesh_cdb_subnet_get(i); + app_key = &bt_mesh_cdb.app_keys[i]; + + console_printf("AppKey: %d\n", i); + console_printf("\tNetKeyIdx: %04x\n", + app_key->net_idx); + console_printf("\tAppKeyIdx: %04x\n", + app_key->app_idx); + } + + for (i = 0; i < ARRAY_SIZE(bt_mesh_cdb.subnets); ++i) + { + sub = bt_mesh_cdb_subnet_get(i); + app_key = &bt_mesh_cdb.app_keys[i]; + if (sub[i].net_idx == BT_MESH_KEY_UNUSED) { + continue; + } + + subnet = bt_mesh_subnet_get(app_key->net_idx); + + console_printf("Friend cred: %d\n", i); + console_printf("\tNetKeyIdx: %04x\n", + sub[i].net_idx); + if (subnet) { + console_printf("\tNID: %02x\n", subnet->keys->msg.nid); + console_printf("\tEncKey: %s\n", + bt_hex(subnet->keys->msg.enc, 16)); + console_printf("\tPrivKey: %s\n", + bt_hex(subnet->keys->msg.privacy, 16)); + } + } +#endif +} + +int bt_test_shell_init(void) +{ +#if MYNEWT_VAL(BLE_MESH_SHELL) + return cmd_mesh_init(0, NULL); +#else + return -ENOTSUP; +#endif +} + +int bt_test_bind_app_key_to_model(struct bt_mesh_model *model, uint16_t key_idx, uint16_t id) +{ + struct bt_mesh_model *found_model; + + found_model = bt_mesh_model_find(bt_mesh_model_elem(model), id); + if (!found_model) { + return STATUS_INVALID_MODEL; + } + + return mod_bind(found_model, key_idx); +} diff --git a/src/nimble/nimble/host/mesh/src/testing.h b/src/nimble/nimble/host/mesh/src/testing.h new file mode 100644 index 00000000..0c08db9b --- /dev/null +++ b/src/nimble/nimble/host/mesh/src/testing.h @@ -0,0 +1,23 @@ +/** + * @file testing.h + * @brief Internal API for Bluetooth testing. + */ + +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nimble/nimble/host/mesh/include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/access.h" + +void bt_test_mesh_model_bound(uint16_t addr, struct bt_mesh_model *model, + uint16_t key_idx); +void bt_test_mesh_model_unbound(uint16_t addr, struct bt_mesh_model *model, + uint16_t key_idx); +void bt_test_mesh_prov_invalid_bearer(uint8_t opcode); +void bt_test_mesh_net_recv(uint8_t ttl, uint8_t ctl, uint16_t src, uint16_t dst, + const void *payload, size_t payload_len); +void bt_test_mesh_trans_incomp_timer_exp(void); +void bt_test_print_credentials(void); diff --git a/src/nimble/nimble/host/mesh/src/transport.c b/src/nimble/nimble/host/mesh/src/transport.c index 9b0d4376..e6fe02a0 100644 --- a/src/nimble/nimble/host/mesh/src/transport.c +++ b/src/nimble/nimble/host/mesh/src/transport.c @@ -7,16 +7,14 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#if MYNEWT_VAL(BLE_MESH) - #define MESH_LOG_MODULE BLE_MESH_TRANS_LOG #include #include #include -#include "../include/mesh/mesh.h" -#include "../include/mesh/glue.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/glue.h" #include "mesh_priv.h" #include "crypto.h" @@ -31,7 +29,7 @@ #include "settings.h" #include "heartbeat.h" #include "transport.h" -#include "../include/mesh/testing.h" +#include "testing.h" #define AID_MASK ((uint8_t)(BIT_MASK(6))) @@ -1017,7 +1015,7 @@ static inline int32_t ack_timeout(struct seg_rx *rx) /* Make sure we don't send more frequently than the duration for * each packet (default is 300ms). */ - return max(to, K_MSEC(400)); + return MAX(to, K_MSEC(400)); } int bt_mesh_ctl_send(struct bt_mesh_net_tx *tx, uint8_t ctl_op, void *data, @@ -1163,6 +1161,10 @@ static void seg_ack(struct ble_npl_event *work) BT_WARN("Incomplete timer expired"); seg_rx_reset(rx, false); + if (IS_ENABLED(CONFIG_BT_TESTING)) { + bt_test_mesh_trans_incomp_timer_exp(); + } + return; } @@ -1296,7 +1298,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx, } if (bt_mesh_rpl_check(net_rx, &rpl)) { - BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06x", + BT_WARN("Replay: src 0x%04x dst 0x%04x seq 0x%06" PRIx32, net_rx->ctx.addr, net_rx->ctx.recv_dst, net_rx->seq); return -EINVAL; } @@ -1424,7 +1426,7 @@ static int trans_seg(struct os_mbuf *buf, struct bt_mesh_net_rx *net_rx, */ if (rpl && rpl->src && auth_seqnum <= rpl->seg && (!rpl->old_iv || net_rx->old_iv)) { - BT_WARN("Ignoring old SeqAuth 0x%06x", auth_seqnum); + BT_WARN("Ignoring old SeqAuth 0x%06" PRIx32, auth_seqnum); return -EALREADY; } @@ -1575,6 +1577,11 @@ int bt_mesh_trans_recv(struct os_mbuf *buf, struct bt_mesh_net_rx *rx) BT_DBG("Payload %s", bt_hex(buf->om_data, buf->om_len)); + if (IS_ENABLED(CONFIG_BT_TESTING)) { + bt_test_mesh_net_recv(rx->ctx.recv_ttl, rx->ctl, rx->ctx.addr, + rx->ctx.recv_dst, buf->om_data, buf->om_len); + } + /* If LPN mode is enabled messages are only accepted when we've * requested the Friend to send them. The messages must also * be encrypted using the Friend Credentials. @@ -1924,4 +1931,3 @@ void bt_mesh_va_pending_store(void) /* Do nothing. */ } #endif /* CONFIG_BT_MESH_LABEL_COUNT > 0 */ -#endif diff --git a/src/nimble/nimble/host/mesh/src/transport.h b/src/nimble/nimble/host/mesh/src/transport.h index 32d00a2e..e85d0e4e 100644 --- a/src/nimble/nimble/host/mesh/src/transport.h +++ b/src/nimble/nimble/host/mesh/src/transport.h @@ -7,7 +7,7 @@ */ #include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "../include/mesh/mesh.h" +#include "nimble/nimble/host/mesh/include/mesh/mesh.h" #define TRANS_SEQ_AUTH_NVAL 0xffffffffffffffff diff --git a/src/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h b/src/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h deleted file mode 100644 index 435e9e11..00000000 --- a/src/nimble/nimble/host/services/ans/include/services/ans/ble_svc_ans.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_SVC_ANS_ -#define H_BLE_SVC_ANS_ - -struct ble_hs_cfg; - -/* 16 Bit Alert Notification Service UUID */ -#define BLE_SVC_ANS_UUID16 0x1811 - -/* 16 Bit Alert Notification Service Characteristic UUIDs */ -#define BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT 0x2a47 -#define BLE_SVC_ANS_CHR_UUID16_NEW_ALERT 0x2a46 -#define BLE_SVC_ANS_CHR_UUID16_SUP_UNR_ALERT_CAT 0x2a48 -#define BLE_SVC_ANS_CHR_UUID16_UNR_ALERT_STAT 0x2a45 -#define BLE_SVC_ANS_CHR_UUID16_ALERT_NOT_CTRL_PT 0x2a44 - -/* Alert Notification Service Category ID Bit Masks - * - * TODO: Add remaining 2 optional categories */ -#define BLE_SVC_ANS_CAT_BM_NONE 0x00 -#define BLE_SVC_ANS_CAT_BM_SIMPLE_ALERT 0x01 -#define BLE_SVC_ANS_CAT_BM_EMAIL 0x02 -#define BLE_SVC_ANS_CAT_BM_NEWS 0x04 -#define BLE_SVC_ANS_CAT_BM_CALL 0x08 -#define BLE_SVC_ANS_CAT_BM_MISSED_CALL 0x10 -#define BLE_SVC_ANS_CAT_BM_SMS 0x20 -#define BLE_SVC_ANS_CAT_BM_VOICE_MAIL 0x40 -#define BLE_SVC_ANS_CAT_BM_SCHEDULE 0x80 - -/* Alert Notification Service Category IDs - * - * TODO: Add remaining 2 optional categories */ -#define BLE_SVC_ANS_CAT_ID_SIMPLE_ALERT 0 -#define BLE_SVC_ANS_CAT_ID_EMAIL 1 -#define BLE_SVC_ANS_CAT_ID_NEWS 2 -#define BLE_SVC_ANS_CAT_ID_CALL 3 -#define BLE_SVC_ANS_CAT_ID_MISSED_CALL 4 -#define BLE_SVC_ANS_CAT_ID_SMS 5 -#define BLE_SVC_ANS_CAT_ID_VOICE_MAIL 6 -#define BLE_SVC_ANS_CAT_ID_SCHEDULE 7 - -/* Number of valid ANS categories - * - * TODO: Add remaining 2 optional categories */ -#define BLE_SVC_ANS_CAT_NUM 8 - -/* Alert Notification Control Point Command IDs */ -#define BLE_SVC_ANS_CMD_EN_NEW_ALERT_CAT 0 -#define BLE_SVC_ANS_CMD_EN_UNR_ALERT_CAT 1 -#define BLE_SVC_ANS_CMD_DIS_NEW_ALERT_CAT 2 -#define BLE_SVC_ANS_CMD_DIS_UNR_ALERT_CAT 3 -#define BLE_SVC_ANS_CMD_NOT_NEW_ALERT_IMMEDIATE 4 -#define BLE_SVC_ANS_CMD_NOT_UNR_ALERT_IMMEDIATE 5 - -/* Error Definitions */ -#define BLE_SVC_ANS_ERR_CMD_NOT_SUPPORTED 0xA0 - -void ble_svc_ans_on_gap_connect(uint16_t conn_handle); - -int ble_svc_ans_new_alert_add(uint8_t cat_id, - const char * info_str); -int ble_svc_ans_unr_alert_add(uint8_t cat_id); - -void ble_svc_ans_init(void); - -#endif - diff --git a/src/nimble/nimble/host/services/ans/src/ble_svc_ans.c b/src/nimble/nimble/host/services/ans/src/ble_svc_ans.c deleted file mode 100644 index eb40b056..00000000 --- a/src/nimble/nimble/host/services/ans/src/ble_svc_ans.c +++ /dev/null @@ -1,463 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include - -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "nimble/nimble/host/include/host/ble_gap.h" -#include "../include/services/ans/ble_svc_ans.h" - -/* Max length of new alert info string */ -#define BLE_SVC_ANS_INFO_STR_MAX_LEN 18 -/* Max length of a new alert notification, max string length + 2 bytes - * for category ID and count. */ -#define BLE_SVC_ANS_NEW_ALERT_MAX_LEN (BLE_SVC_ANS_INFO_STR_MAX_LEN + 2) - -/* Supported categories bitmasks */ -static uint8_t ble_svc_ans_new_alert_cat; -static uint8_t ble_svc_ans_unr_alert_cat; - -/* Characteristic values */ -static uint8_t ble_svc_ans_new_alert_val[BLE_SVC_ANS_NEW_ALERT_MAX_LEN]; -static uint16_t ble_svc_ans_new_alert_val_len; -static uint8_t ble_svc_ans_unr_alert_stat[2]; -static uint8_t ble_svc_ans_alert_not_ctrl_pt[2]; - -/* Alert counts, one value for each category */ -static uint8_t ble_svc_ans_new_alert_cnt[BLE_SVC_ANS_CAT_NUM]; -static uint8_t ble_svc_ans_unr_alert_cnt[BLE_SVC_ANS_CAT_NUM]; - -/* Characteristic value handles */ -static uint16_t ble_svc_ans_new_alert_val_handle; -static uint16_t ble_svc_ans_unr_alert_val_handle; - -/* Connection handle - * - * TODO: In order to support multiple connections we would need to save - * the handles for every connection, not just the most recent. Then - * we would need to notify each connection when needed. - * */ -static uint16_t ble_svc_ans_conn_handle; - -/* Access function */ -static int -ble_svc_ans_access(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg); - -/* Notify new alert */ -static int -ble_svc_ans_new_alert_notify(uint8_t cat_id, const char * info_str); - -/* Notify unread alert */ -static int -ble_svc_ans_unr_alert_notify(uint8_t cat_id); - -/* Save written value to local characteristic value */ -static int -ble_svc_ans_chr_write(struct os_mbuf *om, uint16_t min_len, uint16_t max_len, - void *dst, uint16_t *len); - -static const struct ble_gatt_svc_def ble_svc_ans_defs[] = { - { - /*** Alert Notification Service. */ - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BLE_SVC_ANS_UUID16), - .characteristics = (struct ble_gatt_chr_def[]) { { - /** Supported New Alert Catagory - * - * This characteristic exposes what categories of new - * alert are supported in the server. - */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT), - .access_cb = ble_svc_ans_access, - .flags = BLE_GATT_CHR_F_READ, - }, { - /** New Alert - * - * This characteristic exposes information about - * the count of new alerts (for a given category). - */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_ANS_CHR_UUID16_NEW_ALERT), - .access_cb = ble_svc_ans_access, - .val_handle = &ble_svc_ans_new_alert_val_handle, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - /** Supported Unread Alert Catagory - * - * This characteristic exposes what categories of - * unread alert are supported in the server. - */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_ANS_CHR_UUID16_SUP_UNR_ALERT_CAT), - .access_cb = ble_svc_ans_access, - .flags = BLE_GATT_CHR_F_READ, - }, { - /** Unread Alert Status - * - * This characteristic exposes the count of unread - * alert events existing in the server. - */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_ANS_CHR_UUID16_UNR_ALERT_STAT), - .access_cb = ble_svc_ans_access, - .val_handle = &ble_svc_ans_unr_alert_val_handle, - .flags = BLE_GATT_CHR_F_NOTIFY, - }, { - /** Alert Notification Control Point - * - * This characteristic allows the peer device to - * enable/disable the alert notification of new alert - * and unread event more selectively than can be done - * by setting or clearing the notification bit in the - * Client Characteristic Configuration for each alert - * characteristic. - */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_ANS_CHR_UUID16_ALERT_NOT_CTRL_PT), - .access_cb = ble_svc_ans_access, - .flags = BLE_GATT_CHR_F_WRITE, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, - - { - 0, /* No more services. */ - }, -}; - -/** - * ANS access function - */ -static int -ble_svc_ans_access(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, - void *arg) -{ - uint16_t uuid16; - int rc; - - /* ANS Control point command and catagory variables */ - uint8_t cmd_id; - uint8_t cat_id; - uint8_t cat_bit_mask; - int i; - - uuid16 = ble_uuid_u16(ctxt->chr->uuid); - assert(uuid16 != 0); - - switch (uuid16) { - case BLE_SVC_ANS_CHR_UUID16_SUP_NEW_ALERT_CAT: - assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); - rc = os_mbuf_append(ctxt->om, &ble_svc_ans_new_alert_cat, - sizeof ble_svc_ans_new_alert_cat); - return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; - - case BLE_SVC_ANS_CHR_UUID16_NEW_ALERT: - if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { - rc = ble_svc_ans_chr_write(ctxt->om, 0, - sizeof ble_svc_ans_new_alert_val, - ble_svc_ans_new_alert_val, - &ble_svc_ans_new_alert_val_len); - return rc; - - } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { - rc = os_mbuf_append(ctxt->om, &ble_svc_ans_new_alert_val, - sizeof ble_svc_ans_new_alert_val); - return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; - } - - assert(0); - return BLE_ATT_ERR_UNLIKELY; - case BLE_SVC_ANS_CHR_UUID16_SUP_UNR_ALERT_CAT: - assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); - rc = os_mbuf_append(ctxt->om, &ble_svc_ans_unr_alert_cat, - sizeof ble_svc_ans_unr_alert_cat); - return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; - - case BLE_SVC_ANS_CHR_UUID16_UNR_ALERT_STAT: - if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { - rc = ble_svc_ans_chr_write(ctxt->om, - sizeof ble_svc_ans_unr_alert_stat, - sizeof ble_svc_ans_unr_alert_stat, - &ble_svc_ans_unr_alert_stat, - NULL); - return rc; - } else { - rc = os_mbuf_append(ctxt->om, &ble_svc_ans_unr_alert_stat, - sizeof ble_svc_ans_unr_alert_stat); - return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; - } - - case BLE_SVC_ANS_CHR_UUID16_ALERT_NOT_CTRL_PT: - if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { - rc = ble_svc_ans_chr_write(ctxt->om, - sizeof ble_svc_ans_alert_not_ctrl_pt, - sizeof ble_svc_ans_alert_not_ctrl_pt, - &ble_svc_ans_alert_not_ctrl_pt, - NULL); - if (rc != 0) { - return rc; - } - - /* Get command ID and category ID */ - cmd_id = ble_svc_ans_alert_not_ctrl_pt[0]; - cat_id = ble_svc_ans_alert_not_ctrl_pt[1]; - - - /* Set cat_bit_mask to the appropriate bitmask based on cat_id */ - if (cat_id < BLE_SVC_ANS_CAT_NUM) { - cat_bit_mask = (1 << cat_id); - } else if (cat_id == 0xff) { - cat_bit_mask = cat_id; - } else { - /* invalid category ID */ - return BLE_ATT_ERR_UNLIKELY; - } - - switch (cmd_id) { - case BLE_SVC_ANS_CMD_EN_NEW_ALERT_CAT: - ble_svc_ans_new_alert_cat |= cat_bit_mask; - break; - case BLE_SVC_ANS_CMD_EN_UNR_ALERT_CAT: - ble_svc_ans_unr_alert_cat |= cat_bit_mask; - break; - case BLE_SVC_ANS_CMD_DIS_NEW_ALERT_CAT: - ble_svc_ans_new_alert_cat &= ~cat_bit_mask; - break; - case BLE_SVC_ANS_CMD_DIS_UNR_ALERT_CAT: - ble_svc_ans_unr_alert_cat &= ~cat_bit_mask; - break; - case BLE_SVC_ANS_CMD_NOT_NEW_ALERT_IMMEDIATE: - if (cat_id == 0xff) { - /* If cat_id is 0xff, notify on all enabled categories */ - for (i = BLE_SVC_ANS_CAT_NUM - 1; i > 0; --i) { - if ((ble_svc_ans_new_alert_cat >> i) & 0x01) { - ble_svc_ans_new_alert_notify(i, NULL); - } - } - } else { - ble_svc_ans_new_alert_notify(cat_id, NULL); - } - break; - case BLE_SVC_ANS_CMD_NOT_UNR_ALERT_IMMEDIATE: - if (cat_id == 0xff) { - /* If cat_id is 0xff, notify on all enabled categories */ - for (i = BLE_SVC_ANS_CAT_NUM - 1; i > 0; --i) { - if ((ble_svc_ans_unr_alert_cat >> i) & 0x01) { - ble_svc_ans_unr_alert_notify(i); - } - } - } else { - ble_svc_ans_unr_alert_notify(cat_id); - } - break; - default: - return BLE_SVC_ANS_ERR_CMD_NOT_SUPPORTED; - } - return 0; - } else { - rc = BLE_ATT_ERR_UNLIKELY; - } - return rc; - - default: - assert(0); - return BLE_ATT_ERR_UNLIKELY; - } -} - -/** - * This function must be called with the connection handlewhen a gap - * connect event is received in order to send notifications to the - * client. - * - * @params conn_handle The connection handle for the current - * connection. - */ -void -ble_svc_ans_on_gap_connect(uint16_t conn_handle) -{ - ble_svc_ans_conn_handle = conn_handle; -} - -/** - * Adds a new alert to the given category then notifies the client - * if the given category is valid and enabled. - * - * @param cat_flag The id for the category which should - * should be incremented and notified - * @param info_str The info string to be sent to the client - * with the notification. - * - * @return 0 on success, non-zero error code otherwise. - */ -int -ble_svc_ans_new_alert_add(uint8_t cat_id, const char * info_str) -{ - uint8_t cat_bit_mask; - - if (cat_id < BLE_SVC_ANS_CAT_NUM) { - cat_bit_mask = (1 << cat_id); - } else { - return BLE_HS_EINVAL; - } - - if ((cat_bit_mask & ble_svc_ans_new_alert_cat) == 0) { - return BLE_HS_EINVAL; - } - - ble_svc_ans_new_alert_cnt[cat_id] += 1; - return ble_svc_ans_new_alert_notify(cat_id, info_str); -} - -/** - * Adds an unread alert to the given category then notifies the client - * if the given category is valid and enabled. - * - * @param cat_flag The flag for the category which should - * should be incremented and notified - * - * @return 0 on success, non-zero error code otherwise. - */ -int -ble_svc_ans_unr_alert_add(uint8_t cat_id) -{ - uint8_t cat_bit_mask; - - if (cat_id < BLE_SVC_ANS_CAT_NUM) { - cat_bit_mask = 1 << cat_id; - } else { - return BLE_HS_EINVAL; - } - - if ((cat_bit_mask & ble_svc_ans_unr_alert_cat) == 0) { - return BLE_HS_EINVAL; - } - - ble_svc_ans_unr_alert_cnt[cat_id] += 1; - return ble_svc_ans_unr_alert_notify(cat_id); -} - -/** - * Send a new alert notification to the given category with the - * given info string. - * - * @param cat_id The ID of the category to send the - * notification to. - * @param info_str The info string to send with the - * notification - * - * @return 0 on success, non-zero error code otherwise. - */ -static int -ble_svc_ans_new_alert_notify(uint8_t cat_id, const char * info_str) -{ - int info_str_len; - - /* Clear notification to remove old infomation that may persist */ - memset(&ble_svc_ans_new_alert_val, '\0', - BLE_SVC_ANS_NEW_ALERT_MAX_LEN); - - /* Set ID and count values */ - ble_svc_ans_new_alert_val[0] = cat_id; - ble_svc_ans_new_alert_val[1] = ble_svc_ans_new_alert_cnt[cat_id]; - - if (info_str) { - info_str_len = strlen(info_str); - if (info_str_len > BLE_SVC_ANS_INFO_STR_MAX_LEN) { - /* If info_str is longer than the max string length only - * write up to the maximum length */ - memcpy(&ble_svc_ans_new_alert_val[2], info_str, - BLE_SVC_ANS_INFO_STR_MAX_LEN); - } else { - memcpy(&ble_svc_ans_new_alert_val[2], info_str, info_str_len); - } - } - return ble_gatts_notify(ble_svc_ans_conn_handle, - ble_svc_ans_new_alert_val_handle); -} - -/** - * Send an unread alert notification to the given category. - * - * @param cat_id The ID of the category to send the - * notificaiton to. - * - * @return 0 on success, non-zer0 error code otherwise. - */ -static int -ble_svc_ans_unr_alert_notify(uint8_t cat_id) -{ - ble_svc_ans_unr_alert_stat[0] = cat_id; - ble_svc_ans_unr_alert_stat[1] = ble_svc_ans_unr_alert_cnt[cat_id]; - return ble_gatts_notify(ble_svc_ans_conn_handle, - ble_svc_ans_unr_alert_val_handle); -} - -/** - * Writes the received value from a characteristic write to - * the given destination. - */ -static int -ble_svc_ans_chr_write(struct os_mbuf *om, uint16_t min_len, - uint16_t max_len, void *dst, - uint16_t *len) -{ - uint16_t om_len; - int rc; - - om_len = OS_MBUF_PKTLEN(om); - if (om_len < min_len || om_len > max_len) { - return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; - } - - rc = ble_hs_mbuf_to_flat(om, dst, max_len, len); - if (rc != 0) { - return BLE_ATT_ERR_UNLIKELY; - } - - return 0; -} - -/** - * Initialize the ANS with initial values for enabled categories - * for new and unread alert characteristics. Bitwise or the - * catagory bitmasks to enable multiple catagories. - * - * XXX: We should technically be able to change the new alert and - * unread alert catagories when we have no active connections. - */ -void -ble_svc_ans_init(void) -{ - int rc; - - /* Ensure this function only gets called by sysinit. */ - SYSINIT_ASSERT_ACTIVE(); - - rc = ble_gatts_count_cfg(ble_svc_ans_defs); - SYSINIT_PANIC_ASSERT(rc == 0); - - rc = ble_gatts_add_svcs(ble_svc_ans_defs); - SYSINIT_PANIC_ASSERT(rc == 0); - - ble_svc_ans_new_alert_cat = MYNEWT_VAL(BLE_SVC_ANS_NEW_ALERT_CAT); - ble_svc_ans_unr_alert_cat = MYNEWT_VAL(BLE_SVC_ANS_UNR_ALERT_CAT); -} diff --git a/src/nimble/nimble/host/services/bas/src/ble_svc_bas.c b/src/nimble/nimble/host/services/bas/src/ble_svc_bas.c deleted file mode 100644 index 317b1162..00000000 --- a/src/nimble/nimble/host/services/bas/src/ble_svc_bas.c +++ /dev/null @@ -1,127 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include - -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "nimble/nimble/host/include/host/ble_gap.h" -#include "../include/services/bas/ble_svc_bas.h" - -/* Characteristic value handles */ -#if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0 -static uint16_t ble_svc_bas_battery_handle; -#endif - -/* Battery level */ -uint8_t ble_svc_bas_battery_level; - -/* Access function */ -static int -ble_svc_bas_access(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg); - -static const struct ble_gatt_svc_def ble_svc_bas_defs[] = { - { - /*** Battery Service. */ - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BLE_SVC_BAS_UUID16), - .characteristics = (struct ble_gatt_chr_def[]) { { - /*** Battery level characteristic */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_BAS_CHR_UUID16_BATTERY_LEVEL), - .access_cb = ble_svc_bas_access, -#if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0 - .val_handle = &ble_svc_bas_battery_handle, -#endif - .flags = BLE_GATT_CHR_F_READ | -#if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0 - BLE_GATT_CHR_F_NOTIFY | -#endif - MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_READ_PERM), - }, { - 0, /* No more characteristics in this service. */ - } }, - }, - - { - 0, /* No more services. */ - }, -}; - -/** - * BAS access function - */ -static int -ble_svc_bas_access(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, - void *arg) -{ - uint16_t uuid16 = ble_uuid_u16(ctxt->chr->uuid); - int rc; - - switch (uuid16) { - case BLE_SVC_BAS_CHR_UUID16_BATTERY_LEVEL: - assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); - rc = os_mbuf_append(ctxt->om, &ble_svc_bas_battery_level, - sizeof ble_svc_bas_battery_level); - return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; - - default: - assert(0); - return BLE_ATT_ERR_UNLIKELY; - } -} - - -/** - * Set the battery level, must be between 0 and 100. - * If greater than 100, it will be silently set to 100. - */ -int -ble_svc_bas_battery_level_set(uint8_t level) { - if (level > 100) - level = 100; - if (ble_svc_bas_battery_level != level) { - ble_svc_bas_battery_level = level; -#if MYNEWT_VAL(BLE_SVC_BAS_BATTERY_LEVEL_NOTIFY_ENABLE) > 0 - ble_gatts_chr_updated(ble_svc_bas_battery_handle); -#endif - } - return 0; -} - -/** - * Initialize the Battery Service. - */ -void -ble_svc_bas_init(void) -{ - int rc; - - /* Ensure this function only gets called by sysinit. */ - SYSINIT_ASSERT_ACTIVE(); - - rc = ble_gatts_count_cfg(ble_svc_bas_defs); - SYSINIT_PANIC_ASSERT(rc == 0); - - rc = ble_gatts_add_svcs(ble_svc_bas_defs); - SYSINIT_PANIC_ASSERT(rc == 0); -} diff --git a/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h b/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h index 7e779230..16628ef9 100644 --- a/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h +++ b/src/nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h @@ -23,7 +23,7 @@ #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include #if MYNEWT_VAL(ENC_ADV_DATA) -#include "nimble/nimble/host/include/nimble/host/ble_ead.h" +#include "nimble/nimble/host/include/host/ble_ead.h" #endif #ifdef __cplusplus extern "C" { @@ -34,6 +34,7 @@ extern "C" { #define BLE_SVC_GAP_CHR_UUID16_APPEARANCE 0x2a01 #define BLE_SVC_GAP_CHR_UUID16_PERIPH_PREF_CONN_PARAMS 0x2a04 #define BLE_SVC_GAP_CHR_UUID16_CENTRAL_ADDRESS_RESOLUTION 0x2aa6 +#define BLE_SVC_GAP_CHR_UUID16_LE_GATT_SECURITY_LEVELS 0x2BF5 #if MYNEWT_VAL(ENC_ADV_DATA) #define BLE_SVC_GAP_CHR_UUID16_KEY_MATERIAL 0x2B88 @@ -57,6 +58,7 @@ int ble_svc_gap_device_key_material_set(uint8_t *session_key, uint8_t *iv); #endif void ble_svc_gap_init(void); +void ble_svc_gap_deinit(void); #ifdef __cplusplus } diff --git a/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c b/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c index 29cb0ae1..baa34e6b 100644 --- a/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c +++ b/src/nimble/nimble/host/services/gap/src/ble_svc_gap.c @@ -22,7 +22,7 @@ #include "nimble/porting/nimble/include/sysinit/sysinit.h" #include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/services/gap/ble_svc_gap.h" +#include "nimble/nimble/host/services/gap/include/services/gap/ble_svc_gap.h" #include "nimble/porting/nimble/include/os/endian.h" #define PPCP_ENABLED \ @@ -42,6 +42,7 @@ static char ble_svc_gap_name[BLE_SVC_GAP_NAME_MAX_LEN + 1] = static uint16_t ble_svc_gap_appearance = MYNEWT_VAL(BLE_SVC_GAP_APPEARANCE); #if MYNEWT_VAL(ENC_ADV_DATA) +static uint16_t ble_svc_gap_enc_adv_data_handle; static struct key_material km = { .session_key = {0}, .iv = {0}, @@ -97,6 +98,14 @@ static const struct ble_gatt_svc_def ble_svc_gap_defs[] = { #if MYNEWT_VAL(ENC_ADV_DATA) .uuid = BLE_UUID16_DECLARE(BLE_SVC_GAP_CHR_UUID16_KEY_MATERIAL), .access_cb = ble_svc_gap_access, + .val_handle = &ble_svc_gap_enc_adv_data_handle, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_READ_AUTHOR | BLE_GATT_CHR_F_INDICATE, + }, { +#endif +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) + /*** Characteristic: LE GATT Security Levels. */ + .uuid = BLE_UUID16_DECLARE(BLE_SVC_GAP_CHR_UUID16_LE_GATT_SECURITY_LEVELS), + .access_cb = ble_svc_gap_access, .flags = BLE_GATT_CHR_F_READ, }, { #endif @@ -190,6 +199,26 @@ ble_svc_gap_appearance_write_access(struct ble_gatt_access_ctxt *ctxt) #endif } +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) +static int +ble_svc_gap_security_level_read_access(uint16_t conn_handle, struct os_mbuf * om) +{ + uint8_t security_level[2]; + int rc; + + /* Currently this characteristic is only supported for + * Security Mode 1 + */ + security_level[0] = 0x01; //Mode 1 + security_level[1] = ble_gatts_security_mode_1_level(); //Mode 1 Level + + rc = os_mbuf_append(om, security_level, sizeof(security_level)); + + return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; +} +#endif + + static int ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) @@ -256,6 +285,13 @@ ble_svc_gap_access(uint16_t conn_handle, uint16_t attr_handle, return rc == 0 ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; #endif +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) + case BLE_SVC_GAP_CHR_UUID16_LE_GATT_SECURITY_LEVELS: + assert(ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR); + rc = ble_svc_gap_security_level_read_access(conn_handle, ctxt->om); + return rc; +#endif + default: assert(0); return BLE_ATT_ERR_UNLIKELY; @@ -311,6 +347,7 @@ ble_svc_gap_device_key_material_set(uint8_t *session_key, uint8_t *iv) { memcpy(&km.session_key, session_key, BLE_EAD_KEY_SIZE); memcpy(&km.iv, iv, BLE_EAD_IV_SIZE); + ble_gatts_chr_updated(ble_svc_gap_enc_adv_data_handle); return 0; } #endif @@ -333,3 +370,9 @@ ble_svc_gap_init(void) SYSINIT_PANIC_ASSERT(rc == 0); #endif } + +void +ble_svc_gap_deinit(void) +{ + ble_gatts_free_svcs(); +} diff --git a/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h b/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h index d2e85eb4..7db837a3 100644 --- a/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h +++ b/src/nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h @@ -29,10 +29,16 @@ extern "C" { struct ble_hs_cfg; -#define BLE_SVC_GATT_CHR_SERVICE_CHANGED_UUID16 0x2a05 +#define BLE_SVC_GATT_CHR_SERVICE_CHANGED_UUID16 0x2a05 #define BLE_SVC_GATT_CHR_SERVER_SUPPORTED_FEAT_UUID16 0x2b3a #define BLE_SVC_GATT_CHR_CLIENT_SUPPORTED_FEAT_UUID16 0x2b29 +#define BLE_SVR_GATT_CHR_SVR_SUP_FEAT_EATT_FLAG 0x01 + +#define BLE_SVR_GATT_CHR_CLT_SUP_FEAT_ROBUST_CACHING_FLAG 0x01 +#define BLE_SVR_GATT_CHR_CLT_SUP_FEAT_EATT_FLAG 0x02 +#define BLE_SVR_GATT_CHR_CLT_SUP_FEAT_MULTI_NOTIF_FLAG 0x04 + #if MYNEWT_VAL(BLE_GATT_CACHING) #define BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16 0x2b2a @@ -45,7 +51,7 @@ uint8_t ble_svc_gatt_get_csfs(void); uint8_t ble_svc_gatt_get_local_cl_supported_feat(void); void ble_svc_gatt_changed(uint16_t start_handle, uint16_t end_handle); void ble_svc_gatt_init(void); - +void ble_svc_gatt_deinit(void); #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c b/src/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c index a318cf43..83101ca2 100644 --- a/src/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c +++ b/src/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c @@ -21,7 +21,7 @@ #include "nimble/porting/nimble/include/sysinit/sysinit.h" #include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/services/gatt/ble_svc_gatt.h" +#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" #if MYNEWT_VAL(BLE_GATT_CACHING) static uint16_t ble_svc_gatt_db_hash_handle; @@ -232,4 +232,26 @@ ble_svc_gatt_init(void) rc = ble_gatts_add_svcs(ble_svc_gatt_defs); SYSINIT_PANIC_ASSERT(rc == 0); + + if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 && ble_hs_cfg.eatt) { + ble_svc_gatt_local_srv_sup_feat |= (1 << BLE_SVC_GATT_SRV_SUP_FEAT_EATT_BIT); + } + + if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 && ble_hs_cfg.eatt) { + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_EATT_BIT); + } + + if (MYNEWT_VAL(BLE_ATT_SVR_NOTIFY_MULTI) > 0) { + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_MULT_NTF_BIT); + } + + if (MYNEWT_VAL(BLE_GATT_CACHING) > 0) { + ble_svc_gatt_local_cl_sup_feat |= (1 << BLE_SVC_GATT_CLI_SUP_FEAT_ROBUST_CATCHING_BIT); + } +} + +void +ble_svc_gatt_deinit(void) +{ + ble_gatts_free_svcs(); } diff --git a/src/nimble/nimble/host/services/ias/src/ble_svc_ias.c b/src/nimble/nimble/host/services/ias/src/ble_svc_ias.c deleted file mode 100644 index 98be867f..00000000 --- a/src/nimble/nimble/host/services/ias/src/ble_svc_ias.c +++ /dev/null @@ -1,149 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/services/ias/ble_svc_ias.h" - -/* Callback function */ -static ble_svc_ias_event_fn *ble_svc_ias_cb_fn; - -/* Alert level */ -static uint8_t ble_svc_ias_alert_level; - -/* Write characteristic function */ -static int -ble_svc_ias_chr_write(struct os_mbuf *om, uint16_t min_len, - uint16_t max_len, void *dst, - uint16_t *len); - -/* Access function */ -static int -ble_svc_ias_access(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg); - -static const struct ble_gatt_svc_def ble_svc_ias_defs[] = { - { - /*** Service: Immediate Alert Service (IAS). */ - .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = BLE_UUID16_DECLARE(BLE_SVC_IAS_UUID16), - .characteristics = (struct ble_gatt_chr_def[]) { { - /*** Characteristic: Alert Level. */ - .uuid = BLE_UUID16_DECLARE(BLE_SVC_IAS_CHR_UUID16_ALERT_LEVEL), - .access_cb = ble_svc_ias_access, - .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, - }, { - 0, /* No more characteristics in this service. */ - } }, - }, - - { - 0, /* No more services. */ - }, -}; - -/** - * Writes the received value from a characteristic write to - * the given destination. - */ -static int -ble_svc_ias_chr_write(struct os_mbuf *om, uint16_t min_len, - uint16_t max_len, void *dst, - uint16_t *len) -{ - uint16_t om_len; - int rc; - - om_len = OS_MBUF_PKTLEN(om); - if (om_len < min_len || om_len > max_len) { - return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; - } - - rc = ble_hs_mbuf_to_flat(om, dst, max_len, len); - if (rc != 0) { - return BLE_ATT_ERR_UNLIKELY; - } - - return 0; -} - -/** - * Simple write access callback for the alert level - * characteristic. - */ -static int -ble_svc_ias_access(uint16_t conn_handle, uint16_t attr_handle, - struct ble_gatt_access_ctxt *ctxt, void *arg) -{ - int rc; - - assert(ctxt->chr == &ble_svc_ias_defs[0].characteristics[0]); - - switch (ctxt->op) { - case BLE_GATT_ACCESS_OP_WRITE_CHR: - rc = ble_svc_ias_chr_write(ctxt->om, - sizeof ble_svc_ias_alert_level, - sizeof ble_svc_ias_alert_level, - &ble_svc_ias_alert_level, NULL); - /* Call the IAS event function */ - if (ble_svc_ias_cb_fn) { - ble_svc_ias_cb_fn(ble_svc_ias_alert_level); - } - return rc; - - default: - assert(0); - return BLE_ATT_ERR_UNLIKELY; - } - - return 0; -} - -/** - * Designates the specified function as the IAS callback. This callback is - * necessary for this service to function properly. - * - * @param cb The callback function to call when - * the client signals an alert. - */ -void -ble_svc_ias_set_cb(ble_svc_ias_event_fn *cb) -{ - ble_svc_ias_cb_fn = cb; -} - -/** - * Initialize the IAS package. - */ -void -ble_svc_ias_init(void) -{ - int rc; - - /* Ensure this function only gets called by sysinit. */ - SYSINIT_ASSERT_ACTIVE(); - - rc = ble_gatts_count_cfg(ble_svc_ias_defs); - SYSINIT_PANIC_ASSERT(rc == 0); - - rc = ble_gatts_add_svcs(ble_svc_ias_defs); - SYSINIT_PANIC_ASSERT(rc == 0); -} diff --git a/src/nimble/nimble/host/src/ble_aes_ccm.c b/src/nimble/nimble/host/src/ble_aes_ccm.c index bebe168d..49b32219 100644 --- a/src/nimble/nimble/host/src/ble_aes_ccm.c +++ b/src/nimble/nimble/host/src/ble_aes_ccm.c @@ -6,8 +6,8 @@ #include #include -#include "../include/host/ble_aes_ccm.h" -#include "../src/ble_hs_conn_priv.h" +#include "nimble/nimble/host/include/host/ble_aes_ccm.h" +#include "nimble/nimble/host/src/ble_hs_conn_priv.h" #if MYNEWT_VAL(ENC_ADV_DATA) @@ -265,14 +265,20 @@ int ble_aes_ccm_decrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t uint8_t *out_msg, size_t mic_size) { uint8_t mic[16]; + uint8_t key_reversed[16]; if (aad_len >= 0xff00 || mic_size > sizeof(mic)) { return BLE_HS_EINVAL; } - ble_aes_ccm_crypt(key, nonce, enc_msg, out_msg, msg_len); + /** Setting the correct endian-ness of the key */ + for (int i = 0; i < 16; i++) { + key_reversed[i] = key[15 - i]; + } + + ble_aes_ccm_crypt(key_reversed, nonce, enc_msg, out_msg, msg_len); - ble_aes_ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size); + ble_aes_ccm_auth(key_reversed, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size); /*if (memcmp(mic, enc_msg + msg_len, mic_size)) { printf("\n%s return here", __func__); @@ -286,16 +292,25 @@ int ble_aes_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13], const uint8_t size_t msg_len, const uint8_t *aad, size_t aad_len, uint8_t *out_msg, size_t mic_size) { + /** MIC starts after encrypted message and is part of encrypted advertisement data */ uint8_t *mic = out_msg + msg_len; + uint8_t key_reversed[16]; /* Unsupported AAD size */ if (aad_len >= 0xff00 || mic_size > 16) { return BLE_HS_EINVAL; } - ble_aes_ccm_auth(key, nonce, out_msg, msg_len, aad, aad_len, mic, mic_size); + /* Correcting the endian-ness of the key */ + for (int i = 0; i < 16; i++) { + key_reversed[i] = key[15 - i]; + } + + /** Calculating MIC */ + ble_aes_ccm_auth(key_reversed, nonce, msg, msg_len, aad, aad_len, mic, mic_size); - ble_aes_ccm_crypt(key, nonce, msg, out_msg, msg_len); + /** Encrypting advertisment */ + ble_aes_ccm_crypt(key_reversed, nonce, msg, out_msg, msg_len); return 0; } diff --git a/src/nimble/nimble/host/src/ble_att.c b/src/nimble/nimble/host/src/ble_att.c index ffe4c324..1cefbfba 100644 --- a/src/nimble/nimble/host/src/ble_att.c +++ b/src/nimble/nimble/host/src/ble_att.c @@ -20,7 +20,7 @@ #include #include #include "ble_hs_priv.h" -#include "../include/host/ble_att.h" +#include "nimble/nimble/host/include/host/ble_att.h" #if NIMBLE_BLE_CONNECT @@ -35,7 +35,7 @@ static uint16_t ble_att_preferred_mtu_val; /** Dispatch table for incoming ATT requests. Sorted by op code. */ -typedef int ble_att_rx_fn(uint16_t conn_handle, struct os_mbuf **om); +typedef int ble_att_rx_fn(uint16_t conn_handle, uint16_t cid, struct os_mbuf **om); struct ble_att_rx_dispatch_entry { uint8_t bde_op; ble_att_rx_fn *bde_fn; @@ -71,10 +71,9 @@ static const struct ble_att_rx_dispatch_entry ble_att_rx_dispatch[] = { { BLE_ATT_OP_INDICATE_RSP, ble_att_clt_rx_indicate }, { BLE_ATT_OP_READ_MULT_VAR_REQ, ble_att_svr_rx_read_mult_var }, { BLE_ATT_OP_READ_MULT_VAR_RSP, ble_att_clt_rx_read_mult_var }, + { BLE_ATT_OP_NOTIFY_MULTI_REQ, ble_att_svr_rx_notify_multi }, { BLE_ATT_OP_WRITE_CMD, ble_att_svr_rx_write_no_rsp }, -#ifdef ESP_PLATFORM { BLE_ATT_OP_SIGNED_WRITE_CMD, ble_att_svr_rx_signed_write }, -#endif }; #define BLE_ATT_RX_DISPATCH_SZ \ @@ -134,6 +133,8 @@ STATS_NAME_START(ble_att_stats) STATS_NAME(ble_att_stats, indicate_req_tx) STATS_NAME(ble_att_stats, indicate_rsp_rx) STATS_NAME(ble_att_stats, indicate_rsp_tx) + STATS_NAME(ble_att_stats, multi_notify_req_rx) + STATS_NAME(ble_att_stats, multi_notify_req_tx) STATS_NAME(ble_att_stats, write_cmd_rx) STATS_NAME(ble_att_stats, write_cmd_tx) STATS_NAME_END(ble_att_stats) @@ -142,7 +143,7 @@ static const struct ble_att_rx_dispatch_entry * ble_att_rx_dispatch_entry_find(uint8_t op) { const struct ble_att_rx_dispatch_entry *entry; - int i; + unsigned int i; for (i = 0; i < BLE_ATT_RX_DISPATCH_SZ; i++) { entry = ble_att_rx_dispatch + i; @@ -159,13 +160,21 @@ ble_att_rx_dispatch_entry_find(uint8_t op) } int -ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn, +ble_att_conn_chan_find(uint16_t conn_handle, uint16_t cid, struct ble_hs_conn **out_conn, struct ble_l2cap_chan **out_chan) { - return ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, + return ble_hs_misc_conn_chan_find(conn_handle, cid, out_conn, out_chan); } +int +ble_att_conn_chan_find_by_psm(uint16_t conn_handle, uint16_t psm, + struct ble_hs_conn **out_conn, + struct ble_l2cap_chan **out_chan) +{ + return ble_hs_misc_conn_chan_find(conn_handle, psm, out_conn, out_chan); +} + void ble_att_inc_tx_stat(uint8_t att_op) { @@ -274,6 +283,10 @@ ble_att_inc_tx_stat(uint8_t att_op) STATS_INC(ble_att_stats, indicate_rsp_tx); break; + case BLE_ATT_OP_NOTIFY_MULTI_REQ: + STATS_INC(ble_att_stats, multi_notify_req_tx); + break; + case BLE_ATT_OP_WRITE_CMD: STATS_INC(ble_att_stats, write_cmd_tx); break; @@ -391,6 +404,10 @@ ble_att_inc_rx_stat(uint8_t att_op) STATS_INC(ble_att_stats, indicate_rsp_rx); break; + case BLE_ATT_OP_NOTIFY_MULTI_REQ: + STATS_INC(ble_att_stats, multi_notify_req_rx); + break; + case BLE_ATT_OP_WRITE_CMD: STATS_INC(ble_att_stats, write_cmd_rx); break; @@ -415,7 +432,7 @@ ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan, } uint16_t -ble_att_mtu(uint16_t conn_handle) +ble_att_mtu_by_cid(uint16_t conn_handle, uint16_t cid) { struct ble_l2cap_chan *chan; struct ble_hs_conn *conn; @@ -424,7 +441,7 @@ ble_att_mtu(uint16_t conn_handle) ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, cid, &conn, &chan); if (rc == 0) { mtu = ble_att_chan_mtu(chan); } else { @@ -436,6 +453,12 @@ ble_att_mtu(uint16_t conn_handle) return mtu; } +uint16_t +ble_att_mtu(uint16_t conn_handle) +{ + return ble_att_mtu_by_cid(conn_handle, BLE_L2CAP_CID_ATT); +} + void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu) { @@ -451,6 +474,16 @@ ble_att_chan_mtu(const struct ble_l2cap_chan *chan) { uint16_t mtu; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (ble_hs_cfg.eatt && chan->psm == BLE_EATT_PSM) { + /* The ATT_MTU for the Enhanced ATT bearer shall be set to the minimum of the + * MTU field values of the two devices. Reference: + * Core v5.4 Vol 3 Part G 5.3.1 ATT_MTU + */ + return min(chan->coc_tx.mtu, chan->coc_rx.mtu); + } +#endif + /* If either side has not exchanged MTU size, use the default. Otherwise, * use the lesser of the two exchanged values. */ @@ -469,7 +502,7 @@ ble_att_chan_mtu(const struct ble_l2cap_chan *chan) static void ble_att_rx_handle_unknown_request(uint8_t op, uint16_t conn_handle, - struct os_mbuf **om) + uint16_t cid, struct os_mbuf **om) { /* If this is command (bit6 is set to 1), do nothing */ if (op & 0x40) { @@ -477,27 +510,37 @@ ble_att_rx_handle_unknown_request(uint8_t op, uint16_t conn_handle, } os_mbuf_adj(*om, OS_MBUF_PKTLEN(*om)); - ble_att_svr_tx_error_rsp(conn_handle, *om, op, 0, + ble_att_svr_tx_error_rsp(conn_handle, cid, *om, op, 0, BLE_ATT_ERR_REQ_NOT_SUPPORTED); *om = NULL; } +static void +ble_att_send_outstanding_after_response(uint16_t conn_handle) +{ + struct ble_hs_conn *conn; + struct ble_l2cap_chan *chan; + int rc; + + ble_hs_lock(); + rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn, + &chan); + if (rc) { + return; + } + conn->client_att_busy = false; + ble_att_tx_with_conn(conn, chan, NULL); + ble_hs_unlock(); +} + static int -ble_att_rx(struct ble_l2cap_chan *chan) +ble_att_rx_extended(uint16_t conn_handle, uint16_t cid, struct os_mbuf **om) { const struct ble_att_rx_dispatch_entry *entry; uint8_t op; - uint16_t conn_handle; - struct os_mbuf **om; int rc; - conn_handle = ble_l2cap_get_conn_handle(chan); - if (conn_handle == BLE_HS_CONN_HANDLE_NONE) { - return BLE_HS_ENOTCONN; - } - - om = &chan->rx_buf; BLE_HS_DBG_ASSERT(*om != NULL); rc = os_mbuf_copydata(*om, 0, 1, &op); @@ -505,9 +548,13 @@ ble_att_rx(struct ble_l2cap_chan *chan) return BLE_HS_EMSGSIZE; } + if (cid == BLE_L2CAP_CID_ATT && ble_att_is_response_op(op)) { + ble_att_send_outstanding_after_response(conn_handle); + } + entry = ble_att_rx_dispatch_entry_find(op); if (entry == NULL) { - ble_att_rx_handle_unknown_request(op, conn_handle, om); + ble_att_rx_handle_unknown_request(op, conn_handle, cid, om); return BLE_HS_ENOTSUP; } @@ -516,10 +563,10 @@ ble_att_rx(struct ble_l2cap_chan *chan) /* Strip L2CAP ATT header from the front of the mbuf. */ os_mbuf_adj(*om, 1); - rc = entry->bde_fn(conn_handle, om); + rc = entry->bde_fn(conn_handle, cid, om); if (rc != 0) { if (rc == BLE_HS_ENOTSUP) { - ble_att_rx_handle_unknown_request(op, conn_handle, om); + ble_att_rx_handle_unknown_request(op, conn_handle, cid, om); } return rc; } @@ -527,6 +574,19 @@ ble_att_rx(struct ble_l2cap_chan *chan) return 0; } +static int +ble_att_rx(struct ble_l2cap_chan *chan) +{ + uint16_t conn_handle; + + conn_handle = ble_l2cap_get_conn_handle(chan); + if (conn_handle == BLE_HS_CONN_HANDLE_NONE) { + return BLE_HS_ENOTCONN; + } + + return ble_att_rx_extended(conn_handle, chan->scid, &chan->rx_buf); +} + uint16_t ble_att_preferred_mtu(void) { @@ -587,6 +647,105 @@ ble_att_create_chan(uint16_t conn_handle) return chan; } +bool +ble_att_is_request_op(uint8_t opcode) +{ + switch (opcode) { + case BLE_ATT_OP_MTU_REQ: + case BLE_ATT_OP_FIND_INFO_REQ: + case BLE_ATT_OP_FIND_TYPE_VALUE_REQ: + case BLE_ATT_OP_READ_TYPE_REQ: + case BLE_ATT_OP_READ_REQ: + case BLE_ATT_OP_READ_BLOB_REQ: + case BLE_ATT_OP_READ_MULT_REQ: + case BLE_ATT_OP_READ_GROUP_TYPE_REQ: + case BLE_ATT_OP_WRITE_REQ: + case BLE_ATT_OP_PREP_WRITE_REQ: + case BLE_ATT_OP_EXEC_WRITE_REQ: + case BLE_ATT_OP_INDICATE_REQ: + case BLE_ATT_OP_READ_MULT_VAR_REQ: + return true; + } + return false; +} + +bool +ble_att_is_response_op(uint8_t opcode) +{ + switch (opcode) { + case BLE_ATT_OP_MTU_RSP: + case BLE_ATT_OP_ERROR_RSP: + case BLE_ATT_OP_FIND_INFO_RSP: + case BLE_ATT_OP_FIND_TYPE_VALUE_RSP: + case BLE_ATT_OP_READ_TYPE_RSP: + case BLE_ATT_OP_INDICATE_RSP: + case BLE_ATT_OP_READ_RSP: + case BLE_ATT_OP_READ_BLOB_RSP: + case BLE_ATT_OP_READ_MULT_RSP: + case BLE_ATT_OP_READ_GROUP_TYPE_RSP: + case BLE_ATT_OP_WRITE_RSP: + case BLE_ATT_OP_PREP_WRITE_RSP: + case BLE_ATT_OP_EXEC_WRITE_RSP: + case BLE_ATT_OP_READ_MULT_VAR_RSP: + return true; + } + + return false; +} + +bool +ble_att_is_att_pdu_op(uint8_t opcode) +{ + if (ble_att_is_request_op(opcode)) { + return true; + } + + if (ble_att_is_response_op(opcode)) { + return true; + } + + switch (opcode) { + case BLE_ATT_OP_NOTIFY_MULTI_REQ: + case BLE_ATT_OP_WRITE_CMD: + case BLE_ATT_OP_SIGNED_WRITE_CMD: + case BLE_ATT_OP_NOTIFY_REQ: + return true; + } + return false; +} + +int +ble_att_set_default_bearer_using_cid(uint16_t conn_handle, uint16_t cid) { +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + struct ble_hs_conn * conn; + + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); + + if (conn == NULL) { + return BLE_HS_ENOTCONN; + } + conn->default_cid = cid; + return 0; +#endif + return BLE_HS_ENOTSUP; +} + +uint16_t +ble_att_get_default_bearer_cid(uint16_t conn_handle) { +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + struct ble_hs_conn * conn; + + conn = ble_hs_conn_find(conn_handle); + if (conn == NULL) { + return 0; + } + return conn->default_cid; +#endif + return 0; +} + int ble_att_init(void) { @@ -601,6 +760,8 @@ ble_att_init(void) return BLE_HS_EOS; } + ble_eatt_init(ble_att_rx_extended); + return 0; } diff --git a/src/nimble/nimble/host/src/ble_att_clt.c b/src/nimble/nimble/host/src/ble_att_clt.c index 89078078..b1baa627 100644 --- a/src/nimble/nimble/host/src/ble_att_clt.c +++ b/src/nimble/nimble/host/src/ble_att_clt.c @@ -25,7 +25,11 @@ #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/host/include/host/ble_uuid.h" #include "ble_hs_priv.h" +#ifdef ESP_PLATFORM #include "nimble/esp_port/port/include/esp_nimble_mem.h" +#else +#include "nimble/porting/nimble/include/mem/mem.h" +#endif #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) @@ -37,7 +41,7 @@ *****************************************************************************/ int -ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_error(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { struct ble_att_error_rsp *rsp; int rc; @@ -49,7 +53,7 @@ ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom) rsp = (struct ble_att_error_rsp *)(*rxom)->om_data; - ble_gattc_rx_err(conn_handle, le16toh(rsp->baep_handle), + ble_gattc_rx_err(conn_handle, cid, le16toh(rsp->baep_handle), le16toh(rsp->baep_error_code)); return 0; @@ -74,7 +78,7 @@ ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu) ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc != 0) { rc = BLE_HS_ENOTCONN; } else if (chan->flags & BLE_L2CAP_CHAN_F_TXED_MTU) { @@ -95,14 +99,14 @@ ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu) req->bamc_mtu = htole16(mtu); - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, BLE_L2CAP_CID_ATT, txom); if (rc != 0) { return rc; } ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc == 0) { chan->flags |= BLE_L2CAP_CHAN_F_TXED_MTU; } @@ -113,7 +117,7 @@ ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu) } int -ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { struct ble_att_mtu_cmd *cmd; struct ble_l2cap_chan *chan; @@ -122,13 +126,19 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) mtu = 0; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (ble_hs_cfg.eatt && cid != BLE_L2CAP_CID_ATT) { + return BLE_HS_ENOTSUP; + } +#endif + rc = ble_hs_mbuf_pullup_base(rxom, sizeof(*cmd)); if (rc == 0) { cmd = (struct ble_att_mtu_cmd *)(*rxom)->om_data; ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, NULL, &chan); + rc = ble_att_conn_chan_find(conn_handle, cid, NULL, &chan); if (rc == 0) { ble_att_set_peer_mtu(chan, le16toh(cmd->bamc_mtu)); mtu = ble_att_chan_mtu(chan); @@ -141,7 +151,7 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) } } - ble_gattc_rx_mtu(conn_handle, rc, mtu); + ble_gattc_rx_mtu(conn_handle, BLE_L2CAP_CID_ATT, rc, mtu); return rc; } @@ -150,7 +160,7 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, +ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO @@ -172,7 +182,7 @@ ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, req->bafq_start_handle = htole16(start_handle); req->bafq_end_handle = htole16(end_handle); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } static int @@ -227,7 +237,7 @@ ble_att_clt_parse_find_info_entry(struct os_mbuf **rxom, uint8_t rsp_format, } int -ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om) +ble_att_clt_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **om) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO return BLE_HS_ENOTSUP; @@ -254,14 +264,14 @@ ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om) } /* Hand find-info entry to GATT. */ - ble_gattc_rx_find_info_idata(conn_handle, &idata); + ble_gattc_rx_find_info_idata(conn_handle, cid, &idata); } rc = 0; done: /* Notify GATT that response processing is done. */ - ble_gattc_rx_find_info_complete(conn_handle, rc); + ble_gattc_rx_find_info_complete(conn_handle, cid, rc); return rc; } @@ -274,8 +284,9 @@ ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **om) * anyway */ int -ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, - uint16_t end_handle, uint16_t attribute_type, +ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t cid, + uint16_t start_handle, uint16_t end_handle, + uint16_t attribute_type, const void *attribute_value, int value_len) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE @@ -300,7 +311,7 @@ ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, req->bavq_attr_type = htole16(attribute_type); memcpy(req->bavq_value, attribute_value, value_len); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } static int @@ -326,7 +337,7 @@ ble_att_clt_parse_find_type_value_hinfo( } int -ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE return BLE_HS_ENOTSUP; @@ -343,11 +354,11 @@ ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) break; } - ble_gattc_rx_find_type_value_hinfo(conn_handle, &hinfo); + ble_gattc_rx_find_type_value_hinfo(conn_handle, cid, &hinfo); } /* Notify GATT client that the full response has been parsed. */ - ble_gattc_rx_find_type_value_complete(conn_handle, rc); + ble_gattc_rx_find_type_value_complete(conn_handle, cid, rc); return 0; } @@ -357,7 +368,7 @@ ble_att_clt_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, +ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE @@ -382,11 +393,11 @@ ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, ble_uuid_flat(uuid, req->uuid); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } int -ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE return BLE_HS_ENOTSUP; @@ -428,13 +439,13 @@ ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) adata.value_len = data_len - sizeof(*data); adata.value = data->value; - ble_gattc_rx_read_type_adata(conn_handle, &adata); + ble_gattc_rx_read_type_adata(conn_handle, cid, &adata); os_mbuf_adj(*rxom, data_len); } done: /* Notify GATT that the response is done being parsed. */ - ble_gattc_rx_read_type_complete(conn_handle, rc); + ble_gattc_rx_read_type_complete(conn_handle, cid, rc); return rc; } @@ -444,7 +455,7 @@ ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle) +ble_att_clt_tx_read(uint16_t conn_handle, uint16_t cid, uint16_t handle) { #if !NIMBLE_BLE_ATT_CLT_READ return BLE_HS_ENOTSUP; @@ -465,7 +476,7 @@ ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle) req->barq_handle = htole16(handle); - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, cid, txom); if (rc != 0) { return rc; } @@ -474,14 +485,14 @@ ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle) } int -ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_rsp(conn_handle, 0, rxom); + ble_gattc_rx_read_rsp(conn_handle, cid, 0, rxom); return 0; } @@ -490,7 +501,7 @@ ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, uint16_t offset) +ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t offset) { #if !NIMBLE_BLE_ATT_CLT_READ_BLOB return BLE_HS_ENOTSUP; @@ -512,7 +523,7 @@ ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, uint16_t offset) req->babq_handle = htole16(handle); req->babq_offset = htole16(offset); - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, cid, txom); if (rc != 0) { return rc; } @@ -521,14 +532,14 @@ ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, uint16_t offset) } int -ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_BLOB return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_blob_rsp(conn_handle, 0, rxom); + ble_gattc_rx_read_blob_rsp(conn_handle, cid, 0, rxom); return 0; } @@ -536,8 +547,8 @@ ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) * $read multiple * *****************************************************************************/ int -ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *handles, - int num_handles, bool variable) +ble_att_clt_tx_read_mult(uint16_t conn_handle, uint16_t cid, + const uint16_t *handles, int num_handles, bool variable) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT return BLE_HS_ENOTSUP; @@ -565,30 +576,30 @@ ble_att_clt_tx_read_mult(uint16_t conn_handle, const uint16_t *handles, req->handles[i] = htole16(handles[i]); } - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } int -ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom, false); + ble_gattc_rx_read_mult_rsp(conn_handle, cid, 0, rxom, false); return 0; } int -ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT_VAR return BLE_HS_ENOTSUP; #endif /* Pass the Attribute Value field to GATT. */ - ble_gattc_rx_read_mult_rsp(conn_handle, 0, rxom, true); + ble_gattc_rx_read_mult_rsp(conn_handle, cid, 0, rxom, true); return 0; } @@ -597,7 +608,7 @@ ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_read_group_type(uint16_t conn_handle, +ble_att_clt_tx_read_group_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid) { @@ -622,7 +633,7 @@ ble_att_clt_tx_read_group_type(uint16_t conn_handle, req->bagq_end_handle = htole16(end_handle); ble_uuid_flat(uuid, req->uuid); - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } static int @@ -650,7 +661,7 @@ ble_att_clt_parse_read_group_type_adata( } int -ble_att_clt_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE return BLE_HS_ENOTSUP; @@ -680,13 +691,13 @@ ble_att_clt_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) goto done; } - ble_gattc_rx_read_group_type_adata(conn_handle, &adata); + ble_gattc_rx_read_group_type_adata(conn_handle, cid, &adata); os_mbuf_adj(*rxom, len); } done: /* Notify GATT that the response is done being parsed. */ - ble_gattc_rx_read_group_type_complete(conn_handle, rc); + ble_gattc_rx_read_group_type_complete(conn_handle, cid, rc); return rc; } @@ -695,7 +706,7 @@ ble_att_clt_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, +ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t cid, uint16_t handle, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_WRITE @@ -714,12 +725,12 @@ ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, req->bawq_handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); } int -ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom) +ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_WRITE_NO_RSP return BLE_HS_ENOTSUP; @@ -753,24 +764,24 @@ ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, cmd->handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); } int -ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_WRITE return BLE_HS_ENOTSUP; #endif /* No payload. */ - ble_gattc_rx_write_rsp(conn_handle); + ble_gattc_rx_write_rsp(conn_handle, cid); return 0; } int -ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, uint8_t *csrk, - uint32_t counter, struct os_mbuf *txom) +ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t cid, uint16_t handle, + uint8_t *csrk, uint32_t counter, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_SIGNED_WRITE return BLE_HS_ENOTSUP; @@ -817,7 +828,7 @@ ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, uint8_t * /** Copying sign counter */ memcpy(&message[BLE_ATT_SIGNED_WRITE_DATA_OFFSET + OS_MBUF_PKTLEN(txom)], &counter, sizeof(counter)); - + /* ble_sm_alg_aes_cmac takes data in little-endian format, * so converting it to LE. */ @@ -856,7 +867,7 @@ ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, uint8_t * if(message != NULL) nimble_platform_mem_free(message); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); err: if(message != NULL) nimble_platform_mem_free(message); os_mbuf_free_chain(txom2); @@ -868,7 +879,7 @@ ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, uint8_t * *****************************************************************************/ int -ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, +ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t offset, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_PREP_WRITE @@ -897,7 +908,7 @@ ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, #endif if (OS_MBUF_PKTLEN(txom) > - ble_att_mtu(conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ) { + ble_att_mtu_by_cid(conn_handle, cid) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ) { rc = BLE_HS_EINVAL; goto err; } @@ -912,7 +923,7 @@ ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, req->bapc_offset = htole16(offset); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); err: os_mbuf_free_chain(txom); @@ -920,7 +931,7 @@ ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, } int -ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_prep_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_PREP_WRITE return BLE_HS_ENOTSUP; @@ -949,7 +960,7 @@ ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) done: /* Notify GATT client that the full response has been parsed. */ - ble_gattc_rx_prep_write_rsp(conn_handle, rc, handle, offset, rxom); + ble_gattc_rx_prep_write_rsp(conn_handle, cid, rc, handle, offset, rxom); return rc; } @@ -958,7 +969,7 @@ ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) *****************************************************************************/ int -ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags) +ble_att_clt_tx_exec_write(uint16_t conn_handle, uint16_t cid, uint8_t flags) { #if !NIMBLE_BLE_ATT_CLT_EXEC_WRITE return BLE_HS_ENOTSUP; @@ -975,7 +986,7 @@ ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags) req->baeq_flags = flags; - rc = ble_att_tx(conn_handle, txom); + rc = ble_att_tx(conn_handle, cid, txom); if (rc != 0) { return rc; } @@ -984,13 +995,13 @@ ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags) } int -ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_EXEC_WRITE return BLE_HS_ENOTSUP; #endif - ble_gattc_rx_exec_write_rsp(conn_handle, 0); + ble_gattc_rx_exec_write_rsp(conn_handle, cid, 0); return 0; } @@ -1008,6 +1019,7 @@ ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, struct ble_att_notify_req *req; struct os_mbuf *txom2; + uint16_t cid; int rc; if (handle == 0) { @@ -1024,7 +1036,10 @@ ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, req->banq_handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + cid = ble_eatt_get_available_chan_cid(conn_handle, BLE_GATT_OP_DUMMY); + rc = ble_att_tx(conn_handle, cid, txom2); + ble_eatt_release_chan(conn_handle, BLE_GATT_OP_DUMMY); + return rc; err: os_mbuf_free_chain(txom); @@ -1036,8 +1051,8 @@ ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, *****************************************************************************/ int -ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom) +ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom) { #if !NIMBLE_BLE_ATT_CLT_INDICATE return BLE_HS_ENOTSUP; @@ -1061,7 +1076,7 @@ ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, req->baiq_handle = htole16(handle); os_mbuf_concat(txom2, txom); - return ble_att_tx(conn_handle, txom2); + return ble_att_tx(conn_handle, cid, txom2); err: os_mbuf_free_chain(txom); @@ -1069,15 +1084,45 @@ ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, } int -ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_clt_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !NIMBLE_BLE_ATT_CLT_INDICATE return BLE_HS_ENOTSUP; #endif /* No payload. */ - ble_gatts_rx_indicate_rsp(conn_handle); + ble_gatts_rx_indicate_rsp(conn_handle, cid); return 0; } +/***************************************************************************** +* $multiple handle value notification * +*****************************************************************************/ + +int +ble_att_clt_tx_notify_mult(uint16_t conn_handle, struct os_mbuf *txom) +{ +#if !NIMBLE_BLE_ATT_CLT_NOTIFY_MULT + return BLE_HS_ENOTSUP; +#endif + + struct os_mbuf *txom2; + uint16_t cid; + int rc; + + if (ble_att_cmd_get(BLE_ATT_OP_NOTIFY_MULTI_REQ, 0, &txom2) == NULL) { + return BLE_HS_ENOMEM; + } + + os_mbuf_concat(txom2, txom); + + cid = ble_eatt_get_available_chan_cid(conn_handle, BLE_GATT_OP_DUMMY); + rc = ble_att_tx(conn_handle, cid, txom2); + if (cid != BLE_L2CAP_CID_ATT) { + ble_eatt_release_chan(conn_handle, BLE_GATT_OP_DUMMY); + } + + return rc; +} + #endif diff --git a/src/nimble/nimble/host/src/ble_att_cmd.c b/src/nimble/nimble/host/src/ble_att_cmd.c index 2e29b17e..a8ed2979 100644 --- a/src/nimble/nimble/host/src/ble_att_cmd.c +++ b/src/nimble/nimble/host/src/ble_att_cmd.c @@ -55,28 +55,67 @@ ble_att_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom) } int -ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom) +ble_att_tx_with_conn(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, struct os_mbuf *txom) { - struct ble_l2cap_chan *chan; - struct ble_hs_conn *conn; int rc; + struct os_mbuf_pkthdr *omp; + + if (!txom) { + if (conn->client_att_busy) { + return 0; + } + omp = STAILQ_FIRST(&conn->att_tx_q); + if (omp == NULL) { + return 0; + } + STAILQ_REMOVE_HEAD(&conn->att_tx_q, omp_next); + txom = OS_MBUF_PKTHDR_TO_MBUF(omp); + BLE_EATT_LOG_DEBUG("%s: wakeup will send %p\n", __func__, txom); + } BLE_HS_DBG_ASSERT_EVAL(txom->om_len >= 1); + + if (ble_att_is_request_op(txom->om_data[0])) { + if (conn->client_att_busy) { + BLE_EATT_LOG_DEBUG("ATT Queue %p, client busy %d\n", txom, conn->client_att_busy); + STAILQ_INSERT_TAIL(&conn->att_tx_q, OS_MBUF_PKTHDR(txom), omp_next); + return 0; + } + conn->client_att_busy = true; + } + ble_att_inc_tx_stat(txom->om_data[0]); - ble_hs_lock(); + ble_att_truncate_to_mtu(chan, txom); + rc = ble_l2cap_tx(conn, chan, txom); + assert(rc == 0); + return rc; +} + +int +ble_att_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom) +{ + struct ble_l2cap_chan *chan; + struct ble_hs_conn *conn; + int rc; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (ble_hs_cfg.eatt && cid != BLE_L2CAP_CID_ATT) { + return ble_eatt_tx(conn_handle, cid, txom); + } +#endif + + ble_hs_lock(); rc = ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc != 0) { + ble_hs_unlock(); os_mbuf_free_chain(txom); - } else { - ble_att_truncate_to_mtu(chan, txom); - rc = ble_l2cap_tx(conn, chan, txom); + return rc; } + rc = ble_att_tx_with_conn(conn, chan, txom); ble_hs_unlock(); - return rc; } diff --git a/src/nimble/nimble/host/src/ble_att_cmd_priv.h b/src/nimble/nimble/host/src/ble_att_cmd_priv.h index 8377fce7..3828e9e9 100644 --- a/src/nimble/nimble/host/src/ble_att_cmd_priv.h +++ b/src/nimble/nimble/host/src/ble_att_cmd_priv.h @@ -309,6 +309,20 @@ struct ble_att_exec_write_req { */ #define BLE_ATT_EXEC_WRITE_RSP_SZ 1 +/** + * | Parameter | Size (octets) | + * +-----------------------------------------------+-------------------+ + * | Attribute Opcode | 1 | + * | Attribute Handle Length Value Tuple List | 8 to (ATT_MTU-1) | + */ +#define BLE_ATT_NOTIFY_MULTI_REQ_BASE_SZ 9 + +struct ble_att_tuple_list { + uint16_t handle; + uint16_t value_len; + uint8_t data[0]; +} __attribute__((packed)); + /** * | Parameter | Size (octets) | * +------------------------------------+-------------------+ @@ -454,8 +468,15 @@ void ble_att_indicate_rsp_write(void *payload, int len); void *ble_att_cmd_prepare(uint8_t opcode, size_t len, struct os_mbuf *txom); void *ble_att_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom); -int ble_att_tx(uint16_t conn_handle, struct os_mbuf *txom); - +int ble_att_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom); + +struct ble_l2cap_chan; +struct ble_hs_conn; +int ble_att_tx_with_conn(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan, + struct os_mbuf *txom); +bool ble_att_is_response_op(uint8_t opcode); +bool ble_att_is_request_op(uint8_t opcode); +bool ble_att_is_att_pdu_op(uint8_t opcode); #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/host/src/ble_att_priv.h b/src/nimble/nimble/host/src/ble_att_priv.h index 3b58d56c..e2b741ec 100644 --- a/src/nimble/nimble/host/src/ble_att_priv.h +++ b/src/nimble/nimble/host/src/ble_att_priv.h @@ -102,6 +102,8 @@ STATS_SECT_START(ble_att_stats) STATS_SECT_ENTRY(indicate_req_tx) STATS_SECT_ENTRY(indicate_rsp_rx) STATS_SECT_ENTRY(indicate_rsp_tx) + STATS_SECT_ENTRY(multi_notify_req_rx) + STATS_SECT_ENTRY(multi_notify_req_tx) STATS_SECT_ENTRY(write_cmd_rx) STATS_SECT_ENTRY(write_cmd_tx) STATS_SECT_END @@ -171,13 +173,15 @@ SLIST_HEAD(ble_att_clt_entry_list, ble_att_clt_entry); /*** @gen */ struct ble_l2cap_chan *ble_att_create_chan(uint16_t conn_handle); -int ble_att_conn_chan_find(uint16_t conn_handle, struct ble_hs_conn **out_conn, +int ble_att_conn_chan_find(uint16_t conn_handle, uint16_t cid, + struct ble_hs_conn **out_conn, struct ble_l2cap_chan **out_chan); void ble_att_inc_tx_stat(uint8_t att_op); void ble_att_truncate_to_mtu(const struct ble_l2cap_chan *att_chan, struct os_mbuf *txom); void ble_att_set_peer_mtu(struct ble_l2cap_chan *chan, uint16_t peer_mtu); uint16_t ble_att_chan_mtu(const struct ble_l2cap_chan *chan); +uint16_t ble_att_mtu_by_cid(uint16_t conn_handle, uint16_t cid); int ble_att_init(void); /*** @svr */ @@ -190,38 +194,38 @@ ble_att_svr_find_by_uuid(struct ble_att_svr_entry *start_at, const ble_uuid_t *uuid, uint16_t end_handle); uint16_t ble_att_svr_prev_handle(void); -int ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_svr_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); struct ble_att_svr_entry *ble_att_svr_find_by_handle(uint16_t handle_id); int32_t ble_att_svr_ticks_until_tmo(const struct ble_att_svr_conn *svr, ble_npl_time_t now); -int ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_svr_rx_find_type_value(uint16_t conn_handle, +int ble_att_svr_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_type(uint16_t conn_handle, +int ble_att_svr_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_group_type(uint16_t conn_handle, +int ble_att_svr_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read(uint16_t conn_handle, +int ble_att_svr_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_blob(uint16_t conn_handle, +int ble_att_svr_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_mult_var(uint16_t conn_handle, +int ble_att_svr_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_read_mult(uint16_t conn_handle, +int ble_att_svr_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_write(uint16_t conn_handle, +int ble_att_svr_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom); -#ifdef ESP_PLATFORM -int ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom); -#endif -int ble_att_svr_rx_prep_write(uint16_t conn_handle, +int ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_signed_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_svr_rx_prep_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_exec_write(uint16_t conn_handle, +int ble_att_svr_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_notify(uint16_t conn_handle, +int ble_att_svr_rx_notify(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_svr_rx_indicate(uint16_t conn_handle, +int ble_att_svr_rx_notify_multi(uint16_t conn_handle, uint16_t cid, + struct os_mbuf **rxom); +int ble_att_svr_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); void ble_att_svr_prep_clear(struct ble_att_prep_entry_list *prep_list); int ble_att_svr_read_handle(uint16_t conn_handle, uint16_t attr_handle, @@ -233,9 +237,12 @@ int ble_att_svr_init(void); void ble_att_svr_hide_range(uint16_t start_handle, uint16_t end_handle); void ble_att_svr_restore_range(uint16_t start_handle, uint16_t end_handle); -int ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, +int ble_att_svr_tx_error_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom, uint8_t req_op, uint16_t handle, uint8_t error_code); +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) +uint8_t ble_att_svr_security_mode_1_level(void); +#endif /*** $clt */ /** An information-data entry in a find information response. */ @@ -266,52 +273,56 @@ struct ble_att_read_group_type_adata { uint8_t *value; }; -int ble_att_clt_rx_error(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_rx_error(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_clt_tx_mtu(uint16_t conn_handle, uint16_t mtu); -int ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t handle); -int ble_att_clt_rx_read(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t handle, +int ble_att_clt_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read(uint16_t conn_handle, uint16_t cid, uint16_t handle); +int ble_att_clt_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read_blob(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t offset); -int ble_att_clt_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_mult(uint16_t conn_handle, +int ble_att_clt_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read_mult(uint16_t conn_handle, uint16_t cid, const uint16_t *handles, int num_handles, bool variable); -int ble_att_clt_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t start_handle, +int ble_att_clt_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid); -int ble_att_clt_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_read_group_type(uint16_t conn_handle, +int ble_att_clt_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_read_group_type(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid128); -int ble_att_clt_rx_read_group_type(uint16_t conn_handle, +int ble_att_clt_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t start_handle, +int ble_att_clt_tx_find_info(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle); -int ble_att_clt_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t start_handle, +int ble_att_clt_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_find_type_value(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, uint16_t attribute_type, const void *attribute_value, int value_len); -int ble_att_clt_rx_find_type_value(uint16_t conn_handle, +int ble_att_clt_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); -int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t handle, - uint16_t offset, struct os_mbuf *txom); -int ble_att_clt_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint8_t flags); -int ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t handle, - uint8_t * csrk, uint32_t counter, - struct os_mbuf * txom); -int ble_att_clt_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom); -int ble_att_clt_rx_write(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_write_req(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom); +int ble_att_clt_tx_write_cmd(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom); +int ble_att_clt_tx_prep_write(uint16_t conn_handle, uint16_t cid, + uint16_t handle, uint16_t offset, + struct os_mbuf *txom); +int ble_att_clt_rx_prep_write(uint16_t conn_handle, uint16_t cid, + struct os_mbuf **rxom); +int ble_att_clt_tx_exec_write(uint16_t conn_handle, uint16_t cid, + uint8_t flags); +int ble_att_clt_tx_signed_write_cmd(uint16_t conn_handle, uint16_t cid, + uint16_t handle, uint8_t * csrk, + uint32_t counter, struct os_mbuf * txom); +int ble_att_clt_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); int ble_att_clt_tx_notify(uint16_t conn_handle, uint16_t handle, struct os_mbuf *txom); -int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t handle, - struct os_mbuf *txom); -int ble_att_clt_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom); +int ble_att_clt_tx_indicate(uint16_t conn_handle, uint16_t cid, + uint16_t handle, struct os_mbuf *txom); +int ble_att_clt_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom); +int ble_att_clt_tx_notify_mult(uint16_t conn_handle, struct os_mbuf *txom); #ifdef __cplusplus } diff --git a/src/nimble/nimble/host/src/ble_att_svr.c b/src/nimble/nimble/host/src/ble_att_svr.c index c35c966e..3d2ece37 100644 --- a/src/nimble/nimble/host/src/ble_att_svr.c +++ b/src/nimble/nimble/host/src/ble_att_svr.c @@ -25,7 +25,11 @@ #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/host/include/host/ble_uuid.h" #include "ble_hs_priv.h" +#ifdef ESP_PLATFORM #include "nimble/esp_port/port/include/esp_nimble_mem.h" +#else +#include "nimble/porting/nimble/include/mem/mem.h" +#endif #if NIMBLE_BLE_CONNECT /** @@ -325,13 +329,19 @@ ble_att_svr_check_perms(uint16_t conn_handle, int is_read, /* In SC Only mode all characteristics requiring security * require it on level 4 */ - if (MYNEWT_VAL(BLE_SM_SC_ONLY)) { - if (sec_state.key_size != 16 || - !sec_state.authenticated || + if (ble_hs_cfg.sm_sc_only) { + if (!sec_state.authenticated || !sec_state.encrypted) { - return BLE_ATT_ERR_INSUFFICIENT_KEY_SZ; + *out_att_err = BLE_ATT_ERR_INSUFFICIENT_AUTHEN; + return BLE_HS_ATT_ERR(*out_att_err); + } else if (sec_state.authenticated && + sec_state.encrypted && + sec_state.key_size != 16) { + *out_att_err = BLE_ATT_ERR_INSUFFICIENT_KEY_SZ; + return BLE_HS_ATT_ERR(*out_att_err); } } + if ((enc || authen) && !sec_state.encrypted) { ble_hs_lock(); conn = ble_hs_conn_find(conn_handle); @@ -365,7 +375,9 @@ ble_att_svr_check_perms(uint16_t conn_handle, int is_read, if (author) { /* XXX: Prompt user for authorization. */ + ble_hs_lock(); conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); if(!conn->bhc_sec_state.authorize){ rc = ble_gap_authorize_event(conn_handle, entry->ha_handle_id, is_read); if (rc == BLE_GAP_AUTHORIZE_REJECT) { @@ -617,7 +629,7 @@ ble_att_svr_write_handle(uint16_t conn_handle, uint16_t attr_handle, } int -ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, +ble_att_svr_tx_error_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom, uint8_t req_op, uint16_t handle, uint8_t error_code) { struct ble_att_error_rsp *rsp; @@ -634,7 +646,7 @@ ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, rsp->baep_handle = htole16(handle); rsp->baep_error_code = error_code; - return ble_att_tx(conn_handle, txom); + return ble_att_tx(conn_handle, cid, txom); } /** @@ -661,13 +673,10 @@ ble_att_svr_tx_error_rsp(uint16_t conn_handle, struct os_mbuf *txom, * field. */ static int -ble_att_svr_tx_rsp(uint16_t conn_handle, int hs_status, struct os_mbuf *om, +ble_att_svr_tx_rsp(uint16_t conn_handle, uint16_t cid, int hs_status, struct os_mbuf *om, uint8_t att_op, uint8_t err_status, uint16_t err_handle) { - struct ble_l2cap_chan *chan; - struct ble_hs_conn *conn; int do_tx; - int rc; if (hs_status != 0 && err_status == 0) { /* Processing failed, but err_status of 0 means don't send error. */ @@ -677,28 +686,14 @@ ble_att_svr_tx_rsp(uint16_t conn_handle, int hs_status, struct os_mbuf *om, } if (do_tx) { - ble_hs_lock(); - - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); - if (rc != 0) { - /* No longer connected. */ - hs_status = rc; - } else { - if (hs_status == 0) { - BLE_HS_DBG_ASSERT(om != NULL); - - ble_att_inc_tx_stat(om->om_data[0]); - ble_att_truncate_to_mtu(chan, om); - hs_status = ble_l2cap_tx(conn, chan, om); - om = NULL; - if (hs_status != 0) { - err_status = BLE_ATT_ERR_UNLIKELY; - } - } + if (hs_status == 0) { + hs_status = ble_att_tx(conn_handle, cid, om); + om = NULL; + if (hs_status) { + err_status = BLE_ATT_ERR_UNLIKELY; + } } - ble_hs_unlock(); - if (hs_status != 0) { STATS_INC(ble_att_stats, error_rsp_tx); @@ -709,7 +704,7 @@ ble_att_svr_tx_rsp(uint16_t conn_handle, int hs_status, struct os_mbuf *om, os_mbuf_adj(om, OS_MBUF_PKTLEN(om)); } if (om != NULL) { - ble_att_svr_tx_error_rsp(conn_handle, om, att_op, + ble_att_svr_tx_error_rsp(conn_handle, cid, om, att_op, err_handle, err_status); om = NULL; } @@ -736,7 +731,7 @@ ble_att_svr_build_mtu_rsp(uint16_t conn_handle, struct os_mbuf **rxom, txom = NULL; ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, NULL, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, NULL, &chan); if (rc == 0) { mtu = chan->my_mtu; } @@ -768,7 +763,7 @@ ble_att_svr_build_mtu_rsp(uint16_t conn_handle, struct os_mbuf **rxom, } int -ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_mtu(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { struct ble_att_mtu_cmd *cmd; struct ble_l2cap_chan *chan; @@ -781,6 +776,10 @@ ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) txom = NULL; mtu = 0; + if (cid != BLE_L2CAP_CID_ATT) { + return BLE_HS_ENOTSUP; + } + rc = ble_att_svr_pullup_req_base(rxom, sizeof(*cmd), &att_err); if (rc != 0) { goto done; @@ -798,12 +797,12 @@ ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_MTU_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, BLE_L2CAP_CID_ATT, rc, txom, BLE_ATT_OP_MTU_REQ, att_err, 0); if (rc == 0) { ble_hs_lock(); - rc = ble_att_conn_chan_find(conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT, &conn, &chan); if (rc == 0) { ble_att_set_peer_mtu(chan, mtu); chan->flags |= BLE_L2CAP_CHAN_F_TXED_MTU; @@ -902,7 +901,7 @@ ble_att_svr_fill_info(uint16_t start_handle, uint16_t end_handle, } static int -ble_att_svr_build_find_info_rsp(uint16_t conn_handle, +ble_att_svr_build_find_info_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, struct os_mbuf **rxom, struct os_mbuf **out_txom, @@ -931,7 +930,7 @@ ble_att_svr_build_find_info_rsp(uint16_t conn_handle, /* Write the variable length Information Data field, populating the format * field as appropriate. */ - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_fill_info(start_handle, end_handle, txom, mtu, &rsp->bafp_format); if (rc != 0) { @@ -948,7 +947,7 @@ ble_att_svr_build_find_info_rsp(uint16_t conn_handle, } int -ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_find_info(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_FIND_INFO) return BLE_HS_ENOTSUP; @@ -985,7 +984,7 @@ ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom) goto done; } - rc = ble_att_svr_build_find_info_rsp(conn_handle, + rc = ble_att_svr_build_find_info_rsp(conn_handle, cid, start_handle, end_handle, rxom, &txom, &att_err); if (rc != 0) { @@ -996,7 +995,7 @@ ble_att_svr_rx_find_info(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_FIND_INFO_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_FIND_INFO_REQ, att_err, err_handle); return rc; } @@ -1211,7 +1210,7 @@ ble_att_svr_fill_type_value(uint16_t conn_handle, } static int -ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, +ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, ble_uuid16_t attr_type, @@ -1238,7 +1237,7 @@ ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, } /* Write the variable length Information Data field. */ - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_fill_type_value(conn_handle, start_handle, end_handle, attr_type, *rxom, txom, mtu, @@ -1255,7 +1254,7 @@ ble_att_svr_build_find_type_value_rsp(uint16_t conn_handle, } int -ble_att_svr_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_find_type_value(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_FIND_TYPE) return BLE_HS_ENOTSUP; @@ -1293,7 +1292,7 @@ ble_att_svr_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) rc = BLE_HS_EBADDATA; goto done; } - rc = ble_att_svr_build_find_type_value_rsp(conn_handle, start_handle, + rc = ble_att_svr_build_find_type_value_rsp(conn_handle, cid, start_handle, end_handle, attr_type, rxom, &txom, &att_err); if (rc != 0) { @@ -1304,7 +1303,7 @@ ble_att_svr_rx_find_type_value(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_FIND_TYPE_VALUE_REQ, att_err, err_handle); return rc; @@ -1317,20 +1316,38 @@ static void ble_att_svr_make_conn_aware(uint16_t conn_handle) { int i = 0; conn = ble_hs_conn_find_assert(conn_handle); - conn->bhc_gatt_svr.aware_state = true; + conn->bhc_gatt_svr.aware_state = false; + conn->bhc_gatt_svr.half_aware = 1; ble_hs_conn_addrs(conn, &addrs); for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { if(memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { - ble_gatts_conn_aware_states[i].aware = true; + ble_gatts_conn_aware_states[i].aware = false; + ble_gatts_conn_aware_states[i].half_aware = 1; } } } static bool ble_att_svr_check_conn_aware(uint16_t conn_handle) { struct ble_hs_conn *conn; + struct ble_hs_conn_addrs addrs; + conn = ble_hs_conn_find_assert(conn_handle); + + if (conn->bhc_gatt_svr.half_aware == 1) { + conn->bhc_gatt_svr.half_aware = 0; + conn->bhc_gatt_svr.aware_state = true; + + ble_hs_conn_addrs(conn, &addrs); + for(int i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { + if(memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, + addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { + ble_gatts_conn_aware_states[i].half_aware = 0; + ble_gatts_conn_aware_states[i].aware = true; + } + } + } return conn->bhc_gatt_svr.aware_state; } @@ -1342,7 +1359,7 @@ static uint8_t * ble_att_svr_get_csfs(uint16_t conn_handle) { #endif static int -ble_att_svr_build_read_type_rsp(uint16_t conn_handle, +ble_att_svr_build_read_type_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *uuid, struct os_mbuf **rxom, @@ -1373,7 +1390,7 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, *rxom = NULL; os_mbuf_adj(txom, OS_MBUF_PKTLEN(txom)); - /* Allocate space for the respose base, but don't fill in the fields. They + /* Allocate space for the response base, but don't fill in the fields. They * get filled in at the end, when we know the value of the length field. */ @@ -1385,7 +1402,7 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, goto done; } - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); /* Find all matching attributes, writing a record for each. */ entry = NULL; @@ -1457,7 +1474,7 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, } int -ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_TYPE) return BLE_HS_ENOTSUP; @@ -1465,6 +1482,10 @@ ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) struct ble_att_read_type_req *req; uint16_t start_handle, end_handle; +#if MYNEWT_VAL(BLE_GATT_CACHING) + struct ble_hs_conn *conn; + struct ble_hs_conn_addrs addrs; +#endif struct os_mbuf *txom; uint16_t err_handle; uint16_t pktlen; @@ -1511,14 +1532,39 @@ ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) #if MYNEWT_VAL(BLE_GATT_CACHING) ble_hs_lock(); - ble_att_svr_make_conn_aware(conn_handle); - ble_hs_unlock(); + if (uuid.u.type == BLE_UUID_TYPE_16 && ( + uuid.u16.value == BLE_ATT_UUID_INCLUDE || + uuid.u16.value == BLE_ATT_UUID_CHARACTERISTIC || + uuid.u16.value == BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16)) { + int i = 0; - if(rc != 0) { - goto done; + conn = ble_hs_conn_find_assert(conn_handle); + conn->bhc_gatt_svr.aware_state = true; + conn->bhc_gatt_svr.half_aware = 0; + + ble_hs_conn_addrs(conn, &addrs); + for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { + if(memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, + addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { + ble_gatts_conn_aware_states[i].aware = true; + ble_gatts_conn_aware_states[i].half_aware = 0; + } + } + } else { + if((ble_att_svr_get_csfs(conn_handle)[0] & 1) + && ble_svc_gatt_csf_handle() != err_handle ) { + if (!ble_att_svr_check_conn_aware(conn_handle)) { + att_err = BLE_ATT_ERR_DB_OUT_OF_SYNC; + rc = BLE_HS_EREJECT; + ble_att_svr_make_conn_aware(conn_handle); + ble_hs_unlock(); + goto done; + } + } } + ble_hs_unlock(); #endif - rc = ble_att_svr_build_read_type_rsp(conn_handle, start_handle, end_handle, + rc = ble_att_svr_build_read_type_rsp(conn_handle, cid, start_handle, end_handle, &uuid.u, rxom, &txom, &att_err, &err_handle); if (rc != 0) { @@ -1528,13 +1574,13 @@ ble_att_svr_rx_read_type(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_TYPE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_TYPE_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ) return BLE_HS_ENOTSUP; @@ -1591,13 +1637,13 @@ ble_att_svr_rx_read(uint16_t conn_handle, struct os_mbuf **rxom) } done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_blob(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_BLOB) return BLE_HS_ENOTSUP; @@ -1659,13 +1705,13 @@ ble_att_svr_rx_read_blob(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_BLOB_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_BLOB_REQ, att_err, err_handle); return rc; } static int -ble_att_svr_build_read_mult_rsp(uint16_t conn_handle, +ble_att_svr_build_read_mult_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom, struct os_mbuf **out_txom, uint8_t *att_err, @@ -1676,7 +1722,7 @@ ble_att_svr_build_read_mult_rsp(uint16_t conn_handle, uint16_t mtu; int rc; - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_pkt(rxom, &txom, att_err); if (rc != 0) { @@ -1726,7 +1772,7 @@ ble_att_svr_build_read_mult_rsp(uint16_t conn_handle, } int -ble_att_svr_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_mult(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_MULT) return BLE_HS_ENOTSUP; @@ -1757,18 +1803,18 @@ ble_att_svr_rx_read_mult(uint16_t conn_handle, struct os_mbuf **rxom) ble_hs_unlock(); #endif - rc = ble_att_svr_build_read_mult_rsp(conn_handle, rxom, &txom, &att_err, + rc = ble_att_svr_build_read_mult_rsp(conn_handle, cid, rxom, &txom, &att_err, &err_handle); #if MYNEWT_VAL(BLE_GATT_CACHING) done : #endif - return ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_READ_MULT_REQ, + return ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_MULT_REQ, att_err, err_handle); } static int -ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, +ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom, struct os_mbuf **out_txom, uint8_t *att_err, @@ -1781,7 +1827,7 @@ ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, struct os_mbuf *tmp = NULL; int rc; - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); rc = ble_att_svr_pkt(rxom, &txom, att_err); if (rc != 0) { @@ -1850,7 +1896,7 @@ ble_att_svr_build_read_mult_rsp_var(uint16_t conn_handle, } int -ble_att_svr_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_mult_var(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_MULT) return BLE_HS_ENOTSUP; @@ -1881,13 +1927,13 @@ ble_att_svr_rx_read_mult_var(uint16_t conn_handle, struct os_mbuf **rxom) ble_hs_unlock(); #endif - rc = ble_att_svr_build_read_mult_rsp_var(conn_handle, rxom, &txom, &att_err, + rc = ble_att_svr_build_read_mult_rsp_var(conn_handle, cid, rxom, &txom, &att_err, &err_handle); #if MYNEWT_VAL(BLE_GATT_CACHING) done: #endif - return ble_att_svr_tx_rsp(conn_handle, rc, txom, + return ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_MULT_VAR_REQ, att_err, err_handle); } @@ -1956,7 +2002,7 @@ ble_att_svr_read_group_type_entry_write(struct os_mbuf *om, uint16_t mtu, * @return 0 on success; BLE_HS error code on failure. */ static int -ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, +ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, uint16_t cid, uint16_t start_handle, uint16_t end_handle, const ble_uuid_t *group_uuid, @@ -1976,6 +2022,9 @@ ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, /* Silence warnings. */ end_group_handle = 0; + start_group_handle = 0; + + entry = NULL; *att_err = 0; *err_handle = start_handle; @@ -1983,7 +2032,7 @@ ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, entry = NULL; - mtu = ble_att_mtu(conn_handle); + mtu = ble_att_mtu_by_cid(conn_handle, cid); /* Just reuse the request buffer for the response. */ txom = *rxom; @@ -2125,7 +2174,7 @@ ble_att_svr_build_read_group_type_rsp(uint16_t conn_handle, } int -ble_att_svr_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_read_group_type(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_READ_GROUP_TYPE) return BLE_HS_ENOTSUP; @@ -2194,9 +2243,10 @@ ble_att_svr_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) goto done; } - rc = ble_att_svr_build_read_group_type_rsp(conn_handle, start_handle, - end_handle, &uuid.u, - rxom, &txom, &att_err, + rc = ble_att_svr_build_read_group_type_rsp(conn_handle, cid, + start_handle, end_handle, + &uuid.u, rxom, + &txom, &att_err, &err_handle); if (rc != 0) { goto done; @@ -2205,7 +2255,7 @@ ble_att_svr_rx_read_group_type(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_READ_GROUP_TYPE_REQ, att_err, err_handle); return rc; @@ -2240,7 +2290,7 @@ ble_att_svr_build_write_rsp(struct os_mbuf **rxom, struct os_mbuf **out_txom, } int -ble_att_svr_rx_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_WRITE) return BLE_HS_ENOTSUP; @@ -2300,13 +2350,13 @@ ble_att_svr_rx_write(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_WRITE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_WRITE_REQ, att_err, handle); return rc; } int -ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_WRITE_NO_RSP) return BLE_HS_ENOTSUP; @@ -2342,14 +2392,17 @@ ble_att_svr_rx_write_no_rsp(uint16_t conn_handle, struct os_mbuf **rxom) return ble_att_svr_write_handle(conn_handle, handle, 0, rxom, &att_err); } -#ifdef ESP_PLATFORM int -ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_signed_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_SIGNED_WRITE) return BLE_HS_ENOTSUP; #endif + if (MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 && ble_hs_cfg.eatt) { + return BLE_HS_ENOTSUP; + } + struct ble_att_signed_write_cmd *req; struct ble_store_value_sec value_sec; struct ble_store_key_sec key_sec; @@ -2448,13 +2501,12 @@ ble_att_svr_rx_signed_write(uint16_t conn_handle, struct os_mbuf **rxom) goto err; } - if(message != NULL) nimble_platform_mem_free(message); + nimble_platform_mem_free(message); return 0; err: - if(message != NULL) nimble_platform_mem_free(message); + nimble_platform_mem_free(message); return rc; } -#endif int ble_att_svr_write_local(uint16_t attr_handle, struct os_mbuf *om) @@ -2720,7 +2772,7 @@ ble_att_svr_insert_prep_entry(uint16_t conn_handle, } int -ble_att_svr_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_prep_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_QUEUED_WRITE) return BLE_HS_ENOTSUP; @@ -2810,13 +2862,13 @@ ble_att_svr_rx_prep_write(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_PREP_WRITE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_PREP_WRITE_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_exec_write(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_QUEUED_WRITE) return BLE_HS_ENOTSUP; @@ -2900,13 +2952,13 @@ ble_att_svr_rx_exec_write(uint16_t conn_handle, struct os_mbuf **rxom) ble_att_svr_prep_clear(&prep_list); } - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_EXEC_WRITE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_EXEC_WRITE_REQ, att_err, err_handle); return rc; } int -ble_att_svr_rx_notify(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_notify(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_NOTIFY) return BLE_HS_ENOTSUP; @@ -2935,7 +2987,7 @@ ble_att_svr_rx_notify(uint16_t conn_handle, struct os_mbuf **rxom) /* All indications shall be confirmed, but only these with required * security established shall be pass to application */ - if (MYNEWT_VAL(BLE_SM_SC_LVL) >= 2 && !sec_state.encrypted) { + if (MYNEWT_VAL(BLE_SM_LVL) >= 2 && !sec_state.encrypted) { return 0; } @@ -2948,6 +3000,67 @@ ble_att_svr_rx_notify(uint16_t conn_handle, struct os_mbuf **rxom) return 0; } +int +ble_att_svr_rx_notify_multi(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) +{ +#if !MYNEWT_VAL(BLE_ATT_SVR_NOTIFY_MULTI) + return BLE_HS_ENOTSUP; +#endif + + struct ble_att_tuple_list *req; + uint16_t handle; + int rc = 0; + uint16_t pkt_len; + struct os_mbuf *tmp; + uint16_t attr_len; + + pkt_len = OS_MBUF_PKTLEN(*rxom); + while (pkt_len > 0) { + rc = ble_att_svr_pullup_req_base(rxom, sizeof(struct ble_att_tuple_list), NULL); + if (rc != 0) { + return BLE_HS_ENOMEM; + } + + req = (struct ble_att_tuple_list *)(*rxom)->om_data; + + handle = le16toh(req->handle); + attr_len = le16toh(req->value_len); + + os_mbuf_adj(*rxom, 4); + + if (attr_len > BLE_ATT_ATTR_MAX_LEN) { + BLE_HS_LOG_ERROR("attr length (%d) > max (%d)", + attr_len, BLE_ATT_ATTR_MAX_LEN); + rc = BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + goto done; + } + + tmp = os_msys_get_pkthdr(attr_len, 0); + if (!tmp) { + BLE_HS_LOG_ERROR("not enough resources, aborting"); + rc = BLE_ATT_ERR_INSUFFICIENT_RES; + goto done; + } + + rc = os_mbuf_appendfrom(tmp, *rxom, 0, attr_len); + if (rc) { + BLE_HS_LOG_ERROR("not enough resources, aborting"); + rc = BLE_ATT_ERR_INSUFFICIENT_RES; + goto done; + } + + ble_gap_notify_rx_event(conn_handle, handle, tmp, 0); + + os_mbuf_adj(*rxom, attr_len); + pkt_len = OS_MBUF_PKTLEN(*rxom); + } +done: + os_mbuf_free_chain(*rxom); + *rxom = NULL; + + return rc; +} + /** * @return 0 on success; nonzero on failure. */ @@ -2981,7 +3094,7 @@ ble_att_svr_build_indicate_rsp(struct os_mbuf **rxom, } int -ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) +ble_att_svr_rx_indicate(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rxom) { #if !MYNEWT_VAL(BLE_ATT_SVR_INDICATE) return BLE_HS_ENOTSUP; @@ -3026,7 +3139,7 @@ ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) /* All indications shall be confirmed, but only these with required * security established shall be pass to application */ - if (MYNEWT_VAL(BLE_SM_SC_LVL) >= 2 && !sec_state.encrypted) { + if (MYNEWT_VAL(BLE_SM_LVL) >= 2 && !sec_state.encrypted) { goto done; } @@ -3039,7 +3152,7 @@ ble_att_svr_rx_indicate(uint16_t conn_handle, struct os_mbuf **rxom) rc = 0; done: - rc = ble_att_svr_tx_rsp(conn_handle, rc, txom, BLE_ATT_OP_INDICATE_REQ, + rc = ble_att_svr_tx_rsp(conn_handle, cid, rc, txom, BLE_ATT_OP_INDICATE_REQ, att_err, handle); return rc; } @@ -3367,4 +3480,45 @@ int ble_att_fill_database_info(uint8_t *out_data) return 0; } #endif + +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) +/** + * Return the highest Security Mode 1 Level requirement. + * + * @return Maximum level requirement + */ +uint8_t +ble_att_svr_security_mode_1_level() +{ + struct ble_att_svr_entry *entry; + uint8_t highest_security_level = 0x01; //No Security + uint8_t sec_level; + uint8_t flags; + + for (entry = STAILQ_FIRST(&ble_att_svr_list); + entry != NULL; + entry = STAILQ_NEXT(entry, ha_next)) { + + flags = entry->ha_flags; + if ((flags & BLE_ATT_F_READ_AUTHEN) || (flags & BLE_ATT_F_WRITE_AUTHEN)) { + sec_level = 0x03; //Authenticated pairing with encryption + /* This is the highest currently supported value. + * Break here. + */ + highest_security_level = 0x03; + break; + } else if ((flags & BLE_ATT_F_READ_ENC) || (flags & BLE_ATT_F_WRITE_ENC)) { + sec_level = 0x02; //Unauthenticated pairing with encryption + } else { + sec_level = 0x01; //No security (No authentication and no encryption) + } + + if (sec_level > highest_security_level) { + highest_security_level = sec_level; + } + } + + return highest_security_level; +} +#endif #endif diff --git a/src/nimble/nimble/host/src/ble_dtm.c b/src/nimble/nimble/host/src/ble_dtm.c new file mode 100644 index 00000000..c8cff788 --- /dev/null +++ b/src/nimble/nimble/host/src/ble_dtm.c @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include "ble_hs_hci_priv.h" + +int +ble_dtm_rx_start(const struct ble_dtm_rx_params *params) +{ + struct ble_hci_le_rx_test_v2_cp cmd; + + cmd.rx_chan = params->channel; + cmd.phy = params->phy; + cmd.index = params->modulation_index; + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_RX_TEST_V2), + &cmd, sizeof(cmd), NULL, 0); +} + +int +ble_dtm_tx_start(const struct ble_dtm_tx_params *params) +{ + struct ble_hci_le_tx_test_v2_cp cmd; + + cmd.tx_chan = params->channel; + cmd.test_data_len = params->test_data_len; + cmd.payload = params->payload; + cmd.phy = params->phy; + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_TX_TEST_V2), + &cmd, sizeof(cmd), NULL, 0); +} + +int +ble_dtm_stop(uint16_t *num_packets) +{ + struct ble_hci_le_test_end_rp rsp; + int rc; + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_TEST_END), + NULL, 0, &rsp, sizeof(rsp)); + + if (rc) { + *num_packets = 0; + } else { + *num_packets = le16toh(rsp.num_packets); + } + + return rc; +} diff --git a/src/nimble/nimble/host/src/ble_ead.c b/src/nimble/nimble/host/src/ble_ead.c index c67d947b..f688dad1 100644 --- a/src/nimble/nimble/host/src/ble_ead.c +++ b/src/nimble/nimble/host/src/ble_ead.c @@ -5,8 +5,8 @@ */ #include "nimble/porting/nimble/include/os/queue.h" -#include "../include/host/ble_ead.h" -#include "../include/host/ble_aes_ccm.h" +#include "nimble/nimble/host/include/host/ble_ead.h" +#include "nimble/nimble/host/include/host/ble_aes_ccm.h" #if MYNEWT_VAL(ENC_ADV_DATA) @@ -68,15 +68,18 @@ static int ead_encrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], const uint8_ int err; uint8_t nonce[BLE_EAD_NONCE_SIZE]; + /** Nonce is concatenation of Randomizer and IV */ err = ble_ead_generate_nonce(iv, randomizer, nonce); if (err != 0) { return -1; } + /** Copying Randomizer to the start of encrypted advertisment data */ memcpy(encrypted_payload, nonce, BLE_EAD_RANDOMIZER_SIZE); err = ble_aes_ccm_encrypt(session_key, nonce, payload, payload_size, ble_ead_aad, BLE_EAD_AAD_SIZE, &encrypted_payload[BLE_EAD_RANDOMIZER_SIZE], BLE_EAD_MIC_SIZE); + if (err != 0) { BLE_HS_LOG(DEBUG, "Failed to encrypt the payload (ble_ccm_encrypt err %d)", err); return -1; @@ -178,30 +181,6 @@ int ble_ead_decrypt(const uint8_t session_key[BLE_EAD_KEY_SIZE], const uint8_t i return ead_decrypt(session_key, iv, encrypted_payload, encrypted_payload_size, payload); } -int ble_ead_serialize_data(const struct enc_adv_data *input, uint8_t *output) -{ - if ( input == NULL) { - BLE_HS_LOG(DEBUG, "input is NULL"); - return 0; - } - - if ( output == NULL) { - BLE_HS_LOG(DEBUG, "output is NULL"); - return 0; - } - - uint8_t adv_data_len = input->len; - uint8_t data_len = adv_data_len + 1; - - output[0] = data_len; - output[1] = input->type; - - memcpy(&output[2], input->data, adv_data_len); - - return data_len + 1; - -} - #endif /* ENC_ADV_DATA */ #ifdef __cplusplus diff --git a/src/nimble/nimble/host/src/ble_eatt.c b/src/nimble/nimble/host/src/ble_eatt.c new file mode 100644 index 00000000..f006aec5 --- /dev/null +++ b/src/nimble/nimble/host/src/ble_eatt.c @@ -0,0 +1,605 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "nimble/porting/nimble/include/syscfg/syscfg.h" + +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + +#include +#include +#include "nimble/nimble/host/include/host/ble_hs_log.h" +#include "ble_att_cmd_priv.h" +#include "ble_hs_priv.h" +#include "ble_l2cap_priv.h" +#include "ble_eatt_priv.h" +#include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" + +struct ble_eatt { + SLIST_ENTRY(ble_eatt) next; + uint16_t conn_handle; + struct ble_l2cap_chan *chan; + uint8_t client_op; + + /* Packet transmit queue */ + STAILQ_HEAD(, os_mbuf_pkthdr) eatt_tx_q; + + struct ble_npl_event setup_ev; + struct ble_npl_event wakeup_ev; +}; + +SLIST_HEAD(ble_eatt_list, ble_eatt); + +static struct ble_eatt_list g_ble_eatt_list; +static ble_eatt_att_rx_fn ble_eatt_att_rx_cb; + +#define BLE_EATT_DATABUF_SIZE ( \ + MYNEWT_VAL(BLE_EATT_MTU) + \ + 2 + \ + sizeof (struct os_mbuf_pkthdr) + \ + sizeof (struct os_mbuf)) + +#define BLE_EATT_MEMBLOCK_SIZE \ + (OS_ALIGN(BLE_EATT_DATABUF_SIZE, 4)) + +#define BLE_EATT_MEMPOOL_SIZE \ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_EATT_CHAN_NUM) + 1, BLE_EATT_MEMBLOCK_SIZE) +static os_membuf_t ble_eatt_conn_mem[ + OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_EATT_CHAN_NUM), + sizeof(struct ble_eatt)) +]; +static struct os_mempool ble_eatt_conn_pool; +static os_membuf_t ble_eatt_sdu_coc_mem[BLE_EATT_MEMPOOL_SIZE]; +struct os_mbuf_pool ble_eatt_sdu_os_mbuf_pool; +static struct os_mempool ble_eatt_sdu_mbuf_mempool; + +static struct ble_gap_event_listener ble_eatt_listener; + +static struct ble_npl_event g_read_sup_cl_feat_ev; +static struct ble_npl_event g_read_sup_srv_feat_ev; + +static void ble_eatt_setup_cb(struct ble_npl_event *ev); +static void ble_eatt_start(uint16_t conn_handle); + +static struct ble_eatt * +ble_eatt_find_not_busy(uint16_t conn_handle) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if ((eatt->conn_handle == conn_handle) && !eatt->client_op && eatt->chan) { + return eatt; + } + } + return NULL; +} + +static struct ble_eatt * +ble_eatt_find_by_conn_handle(uint16_t conn_handle) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if (eatt->conn_handle == conn_handle) { + return eatt; + } + } + return NULL; + +} + +static struct ble_eatt * +ble_eatt_find_by_conn_handle_and_busy_op(uint16_t conn_handle, uint8_t op) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if (eatt->conn_handle == conn_handle && eatt->client_op == op) { + return eatt; + } + } + return NULL; + +} + +static struct ble_eatt * +ble_eatt_find(uint16_t conn_handle, uint16_t cid) +{ + struct ble_eatt *eatt; + + SLIST_FOREACH(eatt, &g_ble_eatt_list, next) { + if ((eatt->conn_handle == conn_handle) && + (eatt->chan) && + (eatt->chan->scid == cid)) { + return eatt; + } + } + return NULL; + +} + +static int +ble_eatt_prepare_rx_sdu(struct ble_l2cap_chan *chan) +{ + int rc; + struct os_mbuf *om; + + om = os_mbuf_get_pkthdr(&ble_eatt_sdu_os_mbuf_pool, 0); + if (!om) { + BLE_EATT_LOG_ERROR("eatt: no memory for sdu\n"); + return BLE_HS_ENOMEM; + } + + rc = ble_l2cap_recv_ready(chan, om); + if (rc) { + BLE_EATT_LOG_ERROR("eatt: Failed to supply RX SDU conn_handle 0x%04x (status=%d)\n", + chan->conn_handle, rc); + os_mbuf_free_chain(om); + } + return rc; +} + +static void +ble_eatt_wakeup_cb(struct ble_npl_event *ev) +{ + struct ble_eatt *eatt; + struct os_mbuf *txom; + struct os_mbuf_pkthdr *omp; + struct ble_l2cap_chan_info info; + + eatt = ble_npl_event_get_arg(ev); + assert(eatt); + + omp = STAILQ_FIRST(&eatt->eatt_tx_q); + if (omp != NULL) { + STAILQ_REMOVE_HEAD(&eatt->eatt_tx_q, omp_next); + + txom = OS_MBUF_PKTHDR_TO_MBUF(omp); + ble_l2cap_get_chan_info(eatt->chan, &info); + ble_eatt_tx(eatt->conn_handle, info.dcid, txom); + } +} + +static struct ble_eatt * +ble_eatt_alloc(void) +{ + struct ble_eatt *eatt; + + eatt = os_memblock_get(&ble_eatt_conn_pool); + if (eatt) { + SLIST_INSERT_HEAD(&g_ble_eatt_list, eatt, next); + } else { + BLE_EATT_LOG_DEBUG("eatt: Failed to allocate new eatt context\n"); + return NULL; + } + + eatt->conn_handle = BLE_HS_CONN_HANDLE_NONE; + eatt->chan = NULL; + eatt->client_op = 0; + + STAILQ_INIT(&eatt->eatt_tx_q); + ble_npl_event_init(&eatt->setup_ev, ble_eatt_setup_cb, eatt); + ble_npl_event_init(&eatt->wakeup_ev, ble_eatt_wakeup_cb, eatt); + return eatt; +} + +static void +ble_eatt_free(struct ble_eatt *eatt) +{ + struct os_mbuf_pkthdr *omp; + + while ((omp = STAILQ_FIRST(&eatt->eatt_tx_q)) != NULL) { + STAILQ_REMOVE_HEAD(&eatt->eatt_tx_q, omp_next); + os_mbuf_free_chain(OS_MBUF_PKTHDR_TO_MBUF(omp)); + } + + SLIST_REMOVE(&g_ble_eatt_list, eatt, ble_eatt, next); + os_memblock_put(&ble_eatt_conn_pool, eatt); +} + +static int +ble_eatt_l2cap_event_fn(struct ble_l2cap_event *event, void *arg) +{ + struct ble_eatt *eatt = arg; + struct ble_gap_conn_desc desc; + uint8_t opcode; + int rc; + + switch (event->type) { + case BLE_L2CAP_EVENT_COC_CONNECTED: + BLE_EATT_LOG_DEBUG("eatt: Connected \n"); + if (event->connect.status) { + ble_eatt_free(eatt); + return 0; + } + eatt->chan = event->connect.chan; + ble_gap_eatt_event(event->connect.conn_handle, 0, event->connect.chan->scid); + break; + case BLE_L2CAP_EVENT_COC_DISCONNECTED: + BLE_EATT_LOG_DEBUG("eatt: Disconnected \n"); + ble_eatt_free(eatt); + ble_gap_eatt_event(event->disconnect.conn_handle, 1, event->disconnect.chan->scid); + break; + case BLE_L2CAP_EVENT_COC_ACCEPT: + BLE_EATT_LOG_DEBUG("eatt: Accept request\n"); + + eatt = ble_eatt_alloc(); + if (!eatt) { + return BLE_HS_ENOMEM; + } + eatt->conn_handle = event->accept.conn_handle; + event->accept.chan->cb_arg = eatt; + + rc = ble_eatt_prepare_rx_sdu(event->accept.chan); + if (rc) { + ble_eatt_free(eatt); + return rc; + } + break; + case BLE_L2CAP_EVENT_COC_TX_UNSTALLED: + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->wakeup_ev); + break; + case BLE_L2CAP_EVENT_COC_DATA_RECEIVED: + assert(eatt->chan == event->receive.chan); + opcode = event->receive.sdu_rx->om_data[0]; + if (ble_att_is_response_op(opcode)) { + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->wakeup_ev); + } else if (!ble_att_is_att_pdu_op(opcode)) { + /* As per BLE 5.4 Standard, Vol. 3, Part G, section 5.3.2 + * (ENHANCED ATT BEARER L2CAP INTEROPERABILITY REQUIREMENTS: + * Channel Requirements): + * All packets sent on this L2CAP channel shall be Attribute PDUs. + * + * Disconnect peer with invalid behavior. + */ + ble_l2cap_disconnect(eatt->chan); + return BLE_HS_EREJECT; + } + + assert (!ble_gap_conn_find(event->receive.conn_handle, &desc)); + /* As per BLE 5.4 Standard, Vol. 3, Part G, section 5.3.2 + * (ENHANCED ATT BEARER L2CAP INTEROPERABILITY REQUIREMENTS: + * Channel Requirements): + * The channel shall be encrypted. + * + * Disconnect peer with invalid behavior - ATT PDU received before + * encryption. + */ + if (!desc.sec_state.encrypted) { + ble_l2cap_disconnect(eatt->chan); + return BLE_HS_EREJECT; + } + + ble_eatt_att_rx_cb(event->receive.conn_handle, eatt->chan->scid, &event->receive.sdu_rx); + if (event->receive.sdu_rx) { + os_mbuf_free_chain(event->receive.sdu_rx); + event->receive.sdu_rx = NULL; + } + rc = ble_eatt_prepare_rx_sdu(event->receive.chan); + if (rc) { + /* Receiving L2CAP data is no longer possible, terminate connection */ + ble_l2cap_disconnect(eatt->chan); + return BLE_HS_ENOMEM; + } + break; + default: + break; + } + + return 0; +} + +static void +ble_eatt_setup_cb(struct ble_npl_event *ev) +{ + struct ble_eatt *eatt; + struct os_mbuf *om; + int rc; + + eatt = ble_npl_event_get_arg(ev); + assert(eatt); + + om = os_mbuf_get_pkthdr(&ble_eatt_sdu_os_mbuf_pool, 0); + if (!om) { + ble_eatt_free(eatt); + BLE_EATT_LOG_ERROR("eatt: no memory for sdu\n"); + return; + } + + BLE_EATT_LOG_DEBUG("eatt: connecting eatt on conn_handle 0x%04x\n", eatt->conn_handle); + rc = ble_l2cap_enhanced_connect(eatt->conn_handle, BLE_EATT_PSM, + MYNEWT_VAL(BLE_EATT_MTU), 1, &om, ble_eatt_l2cap_event_fn, eatt); + if (rc) { + BLE_EATT_LOG_ERROR("eatt: Failed to connect EATT on conn_handle 0x%04x (status=%d)\n", + eatt->conn_handle, rc); + os_mbuf_free_chain(om); + ble_eatt_free(eatt); + } +} + +static int +ble_gatt_eatt_write_cl_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg) +{ + if (error == NULL || (error->status != 0 && error->status != BLE_HS_EDONE)) { + BLE_EATT_LOG_DEBUG("eatt: Cannot write to Client Supported features on peer device\n"); + return 0; + } + + ble_eatt_start(conn_handle); + return 0; +} + +static int +ble_gatt_eatt_read_cl_uuid_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg) +{ + uint8_t client_supported_feat; + int rc; + + if (error == NULL || (error->status != 0 && error->status != BLE_HS_EDONE)) { + BLE_EATT_LOG_DEBUG("eatt: Cannot find Client Supported features on peer device\n"); + return BLE_HS_EDONE; + } + + if (attr == NULL) { + BLE_EATT_LOG_ERROR("eatt: Invalid attribute \n"); + return BLE_HS_EDONE; + } + + if (error->status == 0) { + client_supported_feat = MYNEWT_VAL(BLE_CLIENT_SUPPORTED_FEATURES); + rc = ble_gattc_write_flat(conn_handle, attr->handle, &client_supported_feat, 1, + ble_gatt_eatt_write_cl_cb, NULL); + BLE_EATT_LOG_DEBUG("eatt: %s , write rc = %d \n", __func__, rc); + assert(rc == 0); + return 0; + } + + return BLE_HS_EDONE; +} + +static int +ble_gatt_eatt_read_uuid_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, void *arg) +{ + uint8_t supported_features; + int rc; + + if (error == NULL || (error->status != 0 && error->status != BLE_HS_EDONE)) { + BLE_EATT_LOG_DEBUG("eatt: Cannot find Server Supported features on peer device\n"); + return BLE_HS_EDONE; + } + + if (attr == NULL) { + BLE_EATT_LOG_ERROR("eatt: Invalid attribute \n"); + return BLE_HS_EDONE; + } + + rc = os_mbuf_copydata(attr->om, 0, 1, &supported_features); + if (rc) { + BLE_EATT_LOG_ERROR("eatt: Cannot read srv supported features \n"); + return BLE_HS_EDONE; + } + + if (supported_features & 0x01) { + ble_npl_event_set_arg(&g_read_sup_cl_feat_ev, (void *)((uintptr_t) conn_handle)); + ble_npl_eventq_put(ble_hs_evq_get(), &g_read_sup_cl_feat_ev); + } + return BLE_HS_EDONE; +} + +static void +ble_gatt_eatt_read_svr_uuid(struct ble_npl_event *ev) +{ + uint16_t conn_handle; + + conn_handle = (uint16_t)((uintptr_t)(ble_npl_event_get_arg(ev))); + + ble_gattc_read_by_uuid(conn_handle, 1, 0xffff, + BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_SERVER_SUPPORTED_FEAT_UUID16), + ble_gatt_eatt_read_uuid_cb, NULL); +} + +static void +ble_gatt_eatt_read_cl_uuid(struct ble_npl_event *ev) +{ + uint16_t conn_handle; + + conn_handle = (uint16_t)((uintptr_t)(ble_npl_event_get_arg(ev))); + + ble_gattc_read_by_uuid(conn_handle, 1, 0xffff, + BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_CLIENT_SUPPORTED_FEAT_UUID16), + ble_gatt_eatt_read_cl_uuid_cb, NULL); +} + +static int +ble_eatt_gap_event(struct ble_gap_event *event, void *arg) +{ + struct ble_eatt *eatt; + + switch (event->type) { + case BLE_GAP_EVENT_ENC_CHANGE: + if (event->enc_change.status != 0) { + return 0; + } + + if (ble_hs_cfg.eatt == 0) { + return 0; + } + + /* Don't try to connect if already connected */ + if (ble_eatt_find_by_conn_handle(event->enc_change.conn_handle)) { + return 0; + } + + BLE_EATT_LOG_DEBUG("eatt: Encryption enabled, connecting EATT (conn_handle=0x%04x)\n", + event->enc_change.conn_handle); + + ble_npl_event_set_arg(&g_read_sup_srv_feat_ev, (void *)((uintptr_t)(event->enc_change.conn_handle))); + ble_npl_eventq_put(ble_hs_evq_get(), &g_read_sup_srv_feat_ev); + + break; + case BLE_GAP_EVENT_DISCONNECT: + eatt = ble_eatt_find_by_conn_handle(event->disconnect.conn.conn_handle); + assert(eatt == NULL); + break; + default: + break; + } + return 0; +} + +uint16_t +ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op) +{ + uint16_t default_cid; + struct ble_eatt * eatt; + + default_cid = ble_att_get_default_bearer_cid(conn_handle); + if (default_cid) { + eatt = ble_eatt_find(conn_handle, default_cid); + } else { + eatt = ble_eatt_find_not_busy(conn_handle); + } + if (!eatt) { + return BLE_L2CAP_CID_ATT; + } + + eatt->client_op = op; + return eatt->chan->scid; +} + + +void +ble_eatt_release_chan(uint16_t conn_handle, uint8_t op) +{ + struct ble_eatt * eatt; + + eatt = ble_eatt_find_by_conn_handle_and_busy_op(conn_handle, op); + if (!eatt) { + BLE_EATT_LOG_DEBUG("ble_eatt_release_chan:" + "EATT not found for conn_handle 0x%04x, operation 0x%02\n", conn_handle, op); + return; + } + + eatt->client_op = 0; +} + +int +ble_eatt_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom) +{ + struct ble_eatt *eatt; + int rc; + + BLE_EATT_LOG_DEBUG("eatt: %s, size %d ", __func__, OS_MBUF_PKTLEN(txom)); + eatt = ble_eatt_find(conn_handle, cid); + if (!eatt || !eatt->chan) { + BLE_EATT_LOG_ERROR("Eatt not available"); + rc = BLE_HS_ENOENT; + goto error; + } + + ble_att_truncate_to_mtu(eatt->chan, txom); + rc = ble_l2cap_send(eatt->chan, txom); + if (rc == 0) { + goto done; + } + + if (rc == BLE_HS_ESTALLED) { + BLE_EATT_LOG_DEBUG("ble_eatt_tx: Eatt stalled"); + } else if (rc == BLE_HS_EBUSY) { + BLE_EATT_LOG_DEBUG("ble_eatt_tx: Message queued"); + STAILQ_INSERT_HEAD(&eatt->eatt_tx_q, OS_MBUF_PKTHDR(txom), omp_next); + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->wakeup_ev); + } else { + BLE_EATT_LOG_ERROR("eatt: %s, ERROR %d ", __func__, rc); + assert(0); + } +done: + return 0; + +error: + os_mbuf_free_chain(txom); + return rc; +} + +static void +ble_eatt_start(uint16_t conn_handle) +{ + struct ble_gap_conn_desc desc; + struct ble_eatt *eatt; + int rc; + + rc = ble_gap_conn_find(conn_handle, &desc); + assert(rc == 0); + if (desc.role != BLE_GAP_ROLE_MASTER) { + /* Let master to create ecoc. + */ + return; + } + + for (int i = 0; i < ble_hs_cfg.eatt; i++) { + eatt = ble_eatt_alloc(); + if (!eatt) { + return; + } + + eatt->conn_handle = conn_handle; + + /* Setup EATT */ + ble_npl_eventq_put(ble_hs_evq_get(), &eatt->setup_ev); + eatt = NULL; + } +} + +void +ble_eatt_init(ble_eatt_att_rx_fn att_rx_cb) +{ + int rc; + + rc = os_mempool_init(&ble_eatt_sdu_mbuf_mempool, + MYNEWT_VAL(BLE_EATT_CHAN_NUM) + 1, + BLE_EATT_MEMBLOCK_SIZE, + ble_eatt_sdu_coc_mem, + "ble_eatt_sdu"); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + + rc = os_mbuf_pool_init(&ble_eatt_sdu_os_mbuf_pool, + &ble_eatt_sdu_mbuf_mempool, + BLE_EATT_MEMBLOCK_SIZE, + MYNEWT_VAL(BLE_EATT_CHAN_NUM) + 1); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + + rc = os_mempool_init(&ble_eatt_conn_pool, MYNEWT_VAL(BLE_EATT_CHAN_NUM), + sizeof (struct ble_eatt), + ble_eatt_conn_mem, "ble_eatt_conn_pool"); + BLE_HS_DBG_ASSERT_EVAL(rc == 0); + + rc = ble_gap_event_listener_register(&ble_eatt_listener, ble_eatt_gap_event, NULL); + ble_l2cap_create_server(BLE_EATT_PSM, MYNEWT_VAL(BLE_EATT_MTU), ble_eatt_l2cap_event_fn, NULL); + + ble_npl_event_init(&g_read_sup_srv_feat_ev, ble_gatt_eatt_read_svr_uuid, NULL); + ble_npl_event_init(&g_read_sup_cl_feat_ev, ble_gatt_eatt_read_cl_uuid, NULL); + + ble_eatt_att_rx_cb = att_rx_cb; +} +#endif diff --git a/src/nimble/nimble/host/src/ble_eatt_priv.h b/src/nimble/nimble/host/src/ble_eatt_priv.h new file mode 100644 index 00000000..fa7efe42 --- /dev/null +++ b/src/nimble/nimble/host/src/ble_eatt_priv.h @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "nimble/nimble/host/include/host/ble_l2cap.h" + +#ifndef BLE_EATT_H_ +#define BLE_EATT_H_ + +typedef int (* ble_eatt_att_rx_fn)(uint16_t conn_handle, uint16_t cid, struct os_mbuf **rx_buf); + +#define BLE_EATT_PSM (0x0027) + +#define BLE_GATT_OP_SERVER 0xF1 +#define BLE_GATT_OP_DUMMY 0xF2 + +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 +void ble_eatt_init(ble_eatt_att_rx_fn att_rx_fn); +uint16_t ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op); +void ble_eatt_release_chan(uint16_t conn_handle, uint8_t op); +int ble_eatt_tx(uint16_t conn_handle, uint16_t cid, struct os_mbuf *txom); +#else +static inline void +ble_eatt_init(ble_eatt_att_rx_fn att_rx_fn) +{ +} + +static inline void +ble_eatt_release_chan(uint16_t conn_handle, uint8_t op) +{ + +} + +static inline uint16_t +ble_eatt_get_available_chan_cid(uint16_t conn_handle, uint8_t op) +{ + return BLE_L2CAP_CID_ATT; +} + +#endif +#endif diff --git a/src/nimble/nimble/host/src/ble_eddystone.c b/src/nimble/nimble/host/src/ble_eddystone.c index ad0f449d..72800357 100644 --- a/src/nimble/nimble/host/src/ble_eddystone.c +++ b/src/nimble/nimble/host/src/ble_eddystone.c @@ -19,7 +19,7 @@ #include #include "nimble/porting/nimble/include/os/endian.h" -#include "../include/host/ble_eddystone.h" +#include "nimble/nimble/host/include/host/ble_eddystone.h" #include "nimble/nimble/host/include/host/ble_hs_adv.h" #include "ble_hs_priv.h" diff --git a/src/nimble/nimble/host/src/ble_gap.c b/src/nimble/nimble/host/src/ble_gap.c index f4fd5eb9..c524ce55 100644 --- a/src/nimble/nimble/host/src/ble_gap.c +++ b/src/nimble/nimble/host/src/ble_gap.c @@ -31,8 +31,8 @@ #include "ble_gattc_cache_priv.h" #endif -#include "../include/host/ble_hs_pvcy.h" -#include "../util/include/host/util/util.h" +#include "nimble/nimble/host/include/host/ble_hs_pvcy.h" +#include "nimble/nimble/host/util/include/host/util/util.h" #ifndef min #define min(a, b) ((a) < (b) ? (a) : (b)) @@ -46,7 +46,7 @@ #define BIT(n) (1UL << (n)) #endif -#if MYNEWT +#ifdef MYNEWT #include "bsp/bsp.h" #else #define bssnz_t @@ -112,7 +112,7 @@ #define BLE_GAP_UPDATE_TIMEOUT_MS 40000 /* ms */ -#if MYNEWT_VAL(BLE_ROLE_CENTRAL) +#if MYNEWT_VAL(BLE_ROLE_CENTRAL) || MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) static const struct ble_gap_conn_params ble_gap_conn_params_dflt = { .scan_itvl = 0x0010, .scan_window = 0x0010, @@ -131,9 +131,21 @@ struct ble_gap_connect_reattempt_ctxt { ble_addr_t peer_addr; uint8_t peer_addr_present:1; int32_t duration_ms; - struct ble_gap_conn_params conn_params; + struct ble_gap_conn_params conn_params_1m; ble_gap_event_fn *cb; void *cb_arg; +#if MYNEWT_VAL(BLE_EXT_ADV) + uint8_t phy_mask; + struct ble_gap_conn_params conn_params_2m; + struct ble_gap_conn_params conn_params_coded; +#endif // MYNEWT_VAL(BLE_EXT_ADV) +#if MYNEWT_VAL(BLE_PERIODIC_ADV) + ble_addr_t periodic_addr; + uint8_t adv_sid; + int sync_reattempt; + int count; + struct ble_gap_periodic_sync_params periodic_params; +#endif // MYNEWT_VAL(BLE_PERIODIC_ADV) }ble_conn_reattempt; struct ble_gap_adv_reattempt_ctxt { @@ -151,17 +163,18 @@ struct ble_gap_adv_reattempt_ctxt { struct ble_gap_ext_adv_params params; int8_t selected_tx_power; uint8_t selected_tx_power_present:1; - struct os_mbuf *data; + uint8_t data[1650]; + uint16_t data_len; int duration; int max_events; #endif + bool retry; ble_gap_event_fn *cb; void *cb_arg; }ble_adv_reattempt; #endif - /** * The state of the in-progress master connection. If no master connection is * currently in progress, then the op field is set to BLE_GAP_OP_NULL. @@ -278,6 +291,12 @@ struct ble_gap_multi_conn_state static struct ble_gap_multi_conn_state ble_gap_multi_conn; #endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +static uint8_t pawr_adv_handle; +static uint16_t pawr_sync_handle; +#endif + +int slave_conn[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; static void ble_gap_update_entry_free(struct ble_gap_update_entry *entry); #if NIMBLE_BLE_CONNECT @@ -304,6 +323,11 @@ static int ble_gap_conn_cancel_tx(void); static int ble_gap_disc_enable_tx(int enable, int filter_duplicates); #endif +uint16_t g_max_tx_time[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; +uint16_t g_max_rx_time[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1 ]; +uint16_t g_max_tx_octets[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; +uint16_t g_max_rx_octets[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; + STATS_SECT_DECL(ble_gap_stats) ble_gap_stats; STATS_NAME_START(ble_gap_stats) STATS_NAME(ble_gap_stats, wl_set) @@ -368,7 +392,7 @@ ble_gap_log_duration(int32_t duration_ms) if (duration_ms == BLE_HS_FOREVER) { BLE_HS_LOG(INFO, "duration=forever"); } else { - BLE_HS_LOG(INFO, "duration=%" PRId32"ms", duration_ms); + BLE_HS_LOG(INFO, "duration=%" PRId32 "ms", duration_ms); } } #endif @@ -561,6 +585,30 @@ ble_gap_conn_find(uint16_t handle, struct ble_gap_conn_desc *out_desc) #endif } +int +ble_gap_read_rem_ver_info(uint16_t conn_handle, uint8_t *version, uint16_t *manufacturer, uint16_t *subversion) +{ +#if NIMBLE_BLE_CONNECT + struct ble_hs_conn *conn; + + ble_hs_lock(); + + conn = ble_hs_conn_find(conn_handle); + + ble_hs_unlock(); + + if (conn == NULL ) { + return BLE_HS_ENOTCONN; + } + + *version = conn->bhc_rd_rem_ver_params.version; + *manufacturer = conn->bhc_rd_rem_ver_params.manufacturer; + *subversion = conn->bhc_rd_rem_ver_params.subversion; + + return 0; +#endif +} + int ble_gap_conn_find_by_addr(const ble_addr_t *addr, struct ble_gap_conn_desc *out_desc) @@ -569,7 +617,7 @@ ble_gap_conn_find_by_addr(const ble_addr_t *addr, struct ble_hs_conn *conn; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -591,6 +639,57 @@ ble_gap_conn_find_by_addr(const ble_addr_t *addr, #endif } +int +ble_gap_conn_find_handle_by_addr(const ble_addr_t *addr, uint16_t *out_conn_handle) +{ +#if NIMBLE_BLE_CONNECT + struct ble_hs_conn *conn; + + ble_hs_lock(); + + conn = ble_hs_conn_find_by_addr(addr); + if (conn != NULL) { + *out_conn_handle = conn->bhc_handle; + } else { + *out_conn_handle = BLE_HS_CONN_HANDLE_NONE; + } + + ble_hs_unlock(); + + if (conn == NULL) { + return BLE_HS_ENOTCONN; + } + + return 0; +#else + return BLE_HS_ENOTSUP; +#endif +} + +struct foreach_handle_cb_arg { + ble_gap_conn_foreach_handle_fn *cb; + void *arg; +}; + +static int +ble_gap_conn_foreach_handle_callback(struct ble_hs_conn *conn, void *arg) +{ + struct foreach_handle_cb_arg *cb_arg = (struct foreach_handle_cb_arg *)arg; + + return cb_arg->cb(conn->bhc_handle, cb_arg->arg); +} + +void +ble_gap_conn_foreach_handle(ble_gap_conn_foreach_handle_fn *cb, void *arg) +{ + struct foreach_handle_cb_arg cb_arg = { + .cb = cb, + .arg = arg, + }; + + ble_hs_conn_foreach(ble_gap_conn_foreach_handle_callback, &cb_arg); +} + #if NIMBLE_BLE_CONNECT static int ble_gap_extract_conn_cb(uint16_t conn_handle, @@ -626,7 +725,7 @@ ble_gap_set_priv_mode(const ble_addr_t *peer_addr, uint8_t priv_mode) { #if NIMBLE_BLE_CONNECT if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } return ble_hs_pvcy_set_mode(peer_addr, priv_mode); @@ -645,7 +744,7 @@ ble_gap_read_le_phy(uint16_t conn_handle, uint8_t *tx_phy, uint8_t *rx_phy) int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -697,7 +796,7 @@ ble_gap_set_prefered_default_le_phy(uint8_t tx_phys_mask, uint8_t rx_phys_mask) } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } memset(&cmd, 0, sizeof(cmd)); @@ -731,7 +830,7 @@ ble_gap_set_prefered_le_phy(uint16_t conn_handle, uint8_t tx_phys_mask, struct ble_hs_conn *conn; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -1003,7 +1102,22 @@ ble_gap_master_connect_failure(int status) event.type = BLE_GAP_EVENT_CONNECT; event.connect.status = status; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.connect.sync_handle = pawr_sync_handle; + event.connect.adv_handle = pawr_adv_handle; +#endif + rc = state.cb(&event, state.cb_arg); + +//TODO Remove duplication of event fields + event.type = BLE_GAP_EVENT_LINK_ESTAB; + event.link_estab.status = status; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.link_estab.sync_handle = pawr_sync_handle; + event.link_estab.adv_handle = pawr_adv_handle; +#endif rc = state.cb(&event, state.cb_arg); + } else { rc = 0; } @@ -1029,6 +1143,28 @@ ble_gap_master_connect_cancelled(void) /* Connect procedure timed out. */ event.connect.status = BLE_HS_ETIMEOUT; } + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.connect.sync_handle = pawr_sync_handle; + event.connect.adv_handle = pawr_adv_handle; +#endif + state.cb(&event, state.cb_arg); + +//TODO Remove duplication of event fields + event.type = BLE_GAP_EVENT_LINK_ESTAB; + event.link_estab.conn_handle = BLE_HS_CONN_HANDLE_NONE; + if (state.conn.cancel) { + /* Connect procedure successfully cancelled. */ + event.link_estab.status = BLE_HS_EAPP; + } else { + /* Connect procedure timed out. */ + event.link_estab.status = BLE_HS_ETIMEOUT; + } + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.link_estab.sync_handle = pawr_sync_handle; + event.link_estab.adv_handle = pawr_adv_handle; +#endif state.cb(&event, state.cb_arg); } } @@ -1075,12 +1211,33 @@ ble_gap_master_connect_reattempt(uint16_t conn_handle) return rc; } +#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN) + /* This reattempt will be done automatically. The `scheduling_len` maybe set in the ble_gap_multi_connect(). */ + ble_gap_multi_conn.scheduling_len_set = true; +#endif // MYNEWT_VAL(OPTIMIZE_MULTI_CONN) + +#if MYNEWT_VAL(BLE_EXT_ADV) + rc = ble_gap_ext_connect(ble_conn_reattempt.own_addr_type, + (ble_conn_reattempt.peer_addr_present == 1 ? &ble_conn_reattempt.peer_addr : NULL), + ble_conn_reattempt.duration_ms, ble_conn_reattempt.phy_mask, + ble_conn_reattempt.phy_mask & BLE_GAP_LE_PHY_1M_MASK ? &ble_conn_reattempt.conn_params_1m : NULL, + ble_conn_reattempt.phy_mask & BLE_GAP_LE_PHY_2M_MASK ? &ble_conn_reattempt.conn_params_2m : NULL, + ble_conn_reattempt.phy_mask & BLE_GAP_LE_PHY_CODED_MASK ? &ble_conn_reattempt.conn_params_coded : NULL, + ble_conn_reattempt.cb, + ble_conn_reattempt.cb_arg); +#else rc = ble_gap_connect(ble_conn_reattempt.own_addr_type, (ble_conn_reattempt.peer_addr_present == 1 ? &ble_conn_reattempt.peer_addr : NULL), ble_conn_reattempt.duration_ms, - &ble_conn_reattempt.conn_params, + &ble_conn_reattempt.conn_params_1m, ble_conn_reattempt.cb, - &conn); + ble_conn_reattempt.cb_arg); +#endif // #if MYNEWT_VAL(BLE_EXT_ADV) + +#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN) + ble_gap_multi_conn.scheduling_len_set = false; +#endif // MYNEWT_VAL(OPTIMIZE_MULTI_CONN) + if (rc != 0) { return rc; } @@ -1134,11 +1291,14 @@ int ble_gap_slave_adv_reattempt(void) rc = ble_gap_ext_adv_configure(ble_adv_reattempt.instance, &ble_adv_reattempt.params, (ble_adv_reattempt.selected_tx_power_present == 1 ? &ble_adv_reattempt.selected_tx_power : NULL), ble_adv_reattempt.cb, ble_adv_reattempt.cb_arg); + if (rc != 0) { return rc; } - rc = ble_gap_ext_adv_set_data(ble_adv_reattempt.instance, ble_adv_reattempt.data); + ble_adv_reattempt.retry = 1; + rc = ble_gap_ext_adv_set_data(ble_adv_reattempt.instance, + ble_hs_mbuf_from_flat(ble_adv_reattempt.data, ble_adv_reattempt.data_len)); if (rc != 0) { return rc; @@ -1189,21 +1349,17 @@ ble_gap_disc_report(void *desc) static void ble_gap_disc_complete(void) { -#if NIMBLE_BLE_CONNECT struct ble_gap_master_state state; -#endif struct ble_gap_event event; memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_DISC_COMPLETE; event.disc_complete.reason = 0; -#if NIMBLE_BLE_CONNECT ble_gap_master_extract_state(&state, 1); if (ble_gap_has_client(&state)) { ble_gap_call_event_cb(&event, state.cb, state.cb_arg); } -#endif ble_gap_event_listener_call(&event); } @@ -1318,7 +1474,10 @@ ble_gap_update_next_exp(int32_t *out_ticks_from_now) } -#if NIMBLE_BLE_SCAN + +#if (MYNEWT_VAL(BLE_ROLE_CENTRAL) || \ + (MYNEWT_VAL(BLE_ROLE_CENTRAL) && !MYNEWT_VAL(BLE_EXT_ADV)) || \ + (NIMBLE_BLE_SCAN && !MYNEWT_VAL(BLE_EXT_ADV))) static void ble_gap_master_set_timer(uint32_t ticks_from_now) { @@ -1396,6 +1555,8 @@ ble_gap_conn_broken(uint16_t conn_handle, int reason) struct ble_gap_update_entry *entry; struct ble_gap_snapshot snap; struct ble_gap_event event; + struct ble_hs_conn *conn; + bool send = 1; int rc; memset(&event, 0, sizeof event); @@ -1432,13 +1593,33 @@ ble_gap_conn_broken(uint16_t conn_handle, int reason) #endif ble_hs_flow_connection_broken(conn_handle);; + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); + + // Send disconnect event in slave role if connect was sent + if ((conn != NULL) && !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { + if (slave_conn[conn_handle]) { + slave_conn[conn_handle] = 0; + } else { + send = 0; + } + } + ble_hs_atomic_conn_delete(conn_handle); + g_max_tx_time[conn_handle] = 0; + g_max_rx_time[conn_handle] = 0; + g_max_tx_octets[conn_handle] = 0; + g_max_rx_octets[conn_handle] = 0; + event.type = BLE_GAP_EVENT_DISCONNECT; event.disconnect.reason = reason; - ble_gap_event_listener_call(&event); - ble_gap_call_event_cb(&event, snap.cb, snap.cb_arg); + if (send) { + ble_gap_event_listener_call(&event); + ble_gap_call_event_cb(&event, snap.cb, snap.cb_arg); + } STATS_INC(ble_gap_stats, disconnect); #endif @@ -1662,11 +1843,16 @@ ble_gap_accept_master_conn(void) static int ble_gap_accept_slave_conn(uint8_t instance) { - int rc; - + int rc = 0; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + if (instance >= BLE_ADV_INSTANCES) { + rc = BLE_HS_ENOENT; +} +#else if (instance >= BLE_ADV_INSTANCES) { - rc = BLE_HS_ENOENT; + rc = BLE_HS_ENOENT; } else if (!ble_gap_adv_active_instance(instance)) { + rc = BLE_HS_ENOENT; } else { if (ble_gap_slave[instance].connectable) { @@ -1680,6 +1866,7 @@ ble_gap_accept_slave_conn(uint8_t instance) STATS_INC(ble_gap_stats, connect_slv); } +#endif return rc; } #endif @@ -1813,7 +2000,6 @@ ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev) /* Periodic adv events */ #if MYNEWT_VAL(BLE_PERIODIC_ADV) - void ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv_sync_estab *ev) { @@ -1821,7 +2007,9 @@ ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv struct ble_gap_event event; ble_gap_event_fn *cb; void *cb_arg; - +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + int rc; +#endif memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_PERIODIC_SYNC; @@ -1834,6 +2022,11 @@ ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv if (!ev->status) { sync_handle = le16toh(ev->sync_handle); +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + if (ble_conn_reattempt.sync_reattempt) { + ble_conn_reattempt.sync_reattempt = 0; + } +#endif ble_gap_sync.psync->sync_handle = sync_handle; ble_gap_sync.psync->adv_sid = ev->sid; memcpy(ble_gap_sync.psync->advertiser_addr.val, ev->peer_addr, 6); @@ -1848,26 +2041,62 @@ ble_gap_rx_peroidic_adv_sync_estab(const struct ble_hci_ev_le_subev_periodic_adv event.periodic_sync.adv_phy = ev->phy; event.periodic_sync.per_adv_ival = ev->interval; event.periodic_sync.adv_clk_accuracy = ev->aca; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.periodic_sync.num_subevents = ev->num_subevents; + event.periodic_sync.subevent_interval = ev->subevent_interval; + event.periodic_sync.response_slot_delay = ev->response_slot_delay; + event.periodic_sync.response_slot_spacing = ev->response_slot_spacing; +#endif ble_hs_periodic_sync_insert(ble_gap_sync.psync); } else { ble_hs_periodic_sync_free(ble_gap_sync.psync); - } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + if (ev->status == BLE_ERR_CONN_ESTABLISHMENT) { + if (ble_conn_reattempt.count < MAX_REATTEMPT_ALLOWED) { + if (ble_gap_sync.op == BLE_GAP_OP_SYNC) { + memset(&ble_gap_sync, 0, sizeof(ble_gap_sync)); + } + ble_conn_reattempt.count += 1; + ble_conn_reattempt.sync_reattempt = 1; - cb = ble_gap_sync.cb; - cb_arg = ble_gap_sync.cb_arg; + ble_hs_unlock(); - ble_gap_sync.op = BLE_GAP_OP_NULL; - ble_gap_sync.cb_arg = NULL; - ble_gap_sync.cb_arg = NULL; - ble_gap_sync.psync = NULL; + rc = ble_gap_periodic_adv_sync_create(&ble_conn_reattempt.periodic_addr, ble_conn_reattempt.adv_sid, + &ble_conn_reattempt.periodic_params, + ble_conn_reattempt.cb, ble_conn_reattempt.cb_arg); + if (rc != 0) { + return; + } - ble_hs_unlock(); + ble_hs_lock(); + } + } +#endif + } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + if (!ble_conn_reattempt.sync_reattempt || ble_conn_reattempt.count >= MAX_REATTEMPT_ALLOWED) { + memset(&ble_conn_reattempt.periodic_addr, 0, sizeof(ble_addr_t)); + ble_conn_reattempt.adv_sid = 0; + ble_conn_reattempt.count = 0; + memset(&ble_conn_reattempt.periodic_params, 0x0, sizeof(struct ble_gap_periodic_sync_params)); +#endif + cb = ble_gap_sync.cb; + cb_arg = ble_gap_sync.cb_arg; - ble_gap_event_listener_call(&event); - if (cb) { - cb(&event, cb_arg); + ble_gap_sync.op = BLE_GAP_OP_NULL; + ble_gap_sync.cb_arg = NULL; + ble_gap_sync.cb_arg = NULL; + ble_gap_sync.psync = NULL; + + ble_gap_event_listener_call(&event); + if (cb) { + cb(&event, cb_arg); + } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) } +#endif + ble_hs_unlock(); } void @@ -1899,6 +2128,10 @@ ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_rpt *e event.periodic_report.data_status = ev->data_status; event.periodic_report.data_length = ev->data_len; event.periodic_report.data = ev->data; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.periodic_report.event_counter = ev->event_counter; + event.periodic_report.subevent = ev->subevent; +#endif /* TODO should we allow for listener too? this can be spammy and is more * like ACL data, not general event @@ -1985,6 +2218,92 @@ ble_gap_rx_transmit_power_report(const struct ble_hci_ev_le_subev_transmit_power } #endif + +#if MYNEWT_VAL(BLE_AOA_AOD) + +void +ble_gap_rx_connless_iq_report(const struct ble_hci_ev_le_subev_connless_iq_rpt *ev) +{ + struct ble_hs_periodic_sync *psync; + struct ble_gap_event event; + ble_gap_event_fn *cb = NULL; + void *cb_arg = NULL; + uint16_t sync_handle = le16toh(ev->sync_handle); + + /* The handle must be in the list */ + ble_hs_lock(); + psync = ble_hs_periodic_sync_find_by_handle(sync_handle); + cb = psync->cb; + cb_arg = psync->cb_arg; + ble_hs_unlock(); + + memset(&event, 0, sizeof event); + + event.type = BLE_GAP_EVENT_CONNLESS_IQ_REPORT; + event.connless_iq_report.sync_handle = sync_handle; + event.connless_iq_report.channel_index = ev->channel_index; + event.connless_iq_report.rssi = le16toh(ev->rssi); + event.connless_iq_report.rssi_antenna_id = ev->rssi_antenna_id; + event.connless_iq_report.cte_type = ev->cte_type; + event.connless_iq_report.slot_durations = ev->slot_durations; + event.connless_iq_report.packet_status = ev->packet_status; + event.connless_iq_report.periodic_event_counter = le16toh(ev->periodic_event_counter); + event.connless_iq_report.sample_count = ev->sample_count; + event.connless_iq_report.i_samples = (int8_t *)(ev->iq_samples); + event.connless_iq_report.q_samples = (int8_t *)(ev->iq_samples + ev->sample_count); + + ble_gap_event_listener_call(&event); + + if (cb) { + cb(&event, cb_arg); + } +} + + +void +ble_gap_rx_conn_iq_report(const struct ble_hci_ev_le_subev_conn_iq_rpt *ev) +{ + struct ble_gap_event event; + memset(&event, 0, sizeof event); + + event.type = BLE_GAP_EVENT_CONN_IQ_REPORT; + event.conn_iq_report.conn_handle = le16toh(ev->conn_handle); + event.conn_iq_report.data_channel_index = ev->data_channel_index; + event.conn_iq_report.rx_phy = ev->rx_phy; + event.conn_iq_report.rssi = le16toh(ev->rssi); + event.conn_iq_report.rssi_antenna_id = ev->rssi_antenna_id; + event.conn_iq_report.cte_type = ev->cte_type; + event.conn_iq_report.slot_durations = ev->slot_durations; + event.conn_iq_report.packet_status = ev->packet_status; + event.conn_iq_report.conn_event_counter = le16toh(ev->conn_event_counter); + event.conn_iq_report.sample_count = ev->sample_count; + event.conn_iq_report.i_samples = (int8_t *)(ev->iq_samples); + event.conn_iq_report.q_samples = (int8_t *)(ev->iq_samples + ev->sample_count); + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, event.conn_iq_report.conn_handle); + +} + +void +ble_gap_rx_cte_req_failed(const struct ble_hci_ev_le_subev_cte_req_failed *ev) +{ + struct ble_gap_event event; + uint16_t conn_handle; + conn_handle = le16toh(ev->conn_handle); + + memset(&event, 0x0, sizeof event); + + event.type = BLE_GAP_EVENT_CTE_REQ_FAILED; + event.cte_req_fail.status = ev->status; + event.cte_req_fail.conn_handle = conn_handle; + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, conn_handle); +} + +#endif + #if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) static int periodic_adv_transfer_disable(uint16_t conn_handle) @@ -2050,7 +2369,11 @@ ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_ memset(&event, 0, sizeof event); +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.type = BLE_GAP_EVENT_PERIODIC_TRANSFER_V2; +#else event.type = BLE_GAP_EVENT_PERIODIC_TRANSFER; +#endif // MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) event.periodic_transfer.status = ev->status; /* only sync handle is not valid on error */ @@ -2079,9 +2402,55 @@ ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_ event.periodic_transfer.adv_phy = ev->phy; event.periodic_transfer.per_adv_itvl = le16toh(ev->interval); event.periodic_transfer.adv_clk_accuracy = ev->aca; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.periodic_transfer.num_subevents = ev->num_subevents; + event.periodic_transfer.subevent_interval = ev->subevent_interval; + event.periodic_transfer.response_slot_delay = ev->response_slot_delay; + event.periodic_transfer.response_slot_spacing = ev->response_slot_spacing; +#endif + ble_hs_unlock(); + + cb(&event, cb_arg); +} +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) +void +ble_gap_rx_biginfo_adv_rpt(const struct ble_hci_ev_le_subev_biginfo_adv_report *ev) +{ + struct ble_hs_periodic_sync *psync; + struct ble_gap_event event; + ble_gap_event_fn *cb; + void *cb_arg; + cb = NULL; + cb_arg = NULL; + + ble_hs_lock(); + psync = ble_hs_periodic_sync_find_by_handle(le16toh(ev->sync_handle)); + if (psync) { + cb = psync->cb; + cb_arg = psync->cb_arg; + } ble_hs_unlock(); + memset(&event, 0, sizeof event); + + event.type = BLE_GAP_EVENT_BIGINFO_REPORT; + event.biginfo_report.sync_handle = ev->sync_handle; + event.biginfo_report.bis_cnt = ev->bis_cnt; + event.biginfo_report.nse = ev->nse; + event.biginfo_report.iso_interval = ev->iso_interval; + event.biginfo_report.bn = ev->bn; + event.biginfo_report.pto = ev->pto; + event.biginfo_report.irc = ev->irc; + event.biginfo_report.max_pdu = ev->max_pdu; + event.biginfo_report.sdu_interval = get_le24(&ev->sdu_interval[0]); + event.biginfo_report.max_sdu = ev->max_sdu; + event.biginfo_report.phy = ev->phy; + event.biginfo_report.framing = ev->framing; + event.biginfo_report.encryption = ev->encryption; + ble_gap_event_listener_call(&event); if (cb) { cb(&event, cb_arg); @@ -2094,6 +2463,9 @@ void ble_gap_rx_subrate_change(const struct ble_hci_ev_le_subev_subrate_change *ev) { struct ble_gap_event event; + uint16_t conn_handle; + + conn_handle = le16toh(ev->conn_handle); memset(&event, 0x0, sizeof event); @@ -2106,39 +2478,138 @@ ble_gap_rx_subrate_change(const struct ble_hci_ev_le_subev_subrate_change *ev) event.subrate_change.supervision_tmo = le16toh(ev->supervision_tmo); ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, conn_handle); } #endif -#if NIMBLE_BLE_CONNECT -static int -ble_gap_rd_rem_sup_feat_tx(uint16_t handle) +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +void +ble_gap_rx_periodic_adv_subev_data_req(const struct ble_hci_ev_le_subev_periodic_adv_subev_data_req *ev) { - struct ble_hci_le_rd_rem_feat_cp cmd; + struct ble_gap_event event; + ble_gap_event_fn *cb; + void *cb_arg; - cmd.conn_handle = htole16(handle); + memset(&event, 0x0, sizeof event); - return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_RD_REM_FEAT), - &cmd, sizeof(cmd), NULL, 0); + event.type = BLE_GAP_EVENT_PER_SUBEV_DATA_REQ; + event.periodic_adv_subev_data_req.adv_handle = ev->adv_handle; + event.periodic_adv_subev_data_req.subevent_start = ev->subevent_start; + event.periodic_adv_subev_data_req.subevent_data_count = ev->subevent_data_count; + + ble_gap_slave_extract_cb(ev->adv_handle, &cb, &cb_arg); + if (cb != NULL) { + cb(&event, cb_arg); + } + + ble_gap_event_listener_call(&event); } -#endif -/** - * Processes an incoming connection-complete HCI event. +void +ble_gap_rx_periodic_adv_response(const struct ble_gap_periodic_adv_response resp) +{ + struct ble_gap_event event; + ble_gap_event_fn *cb; + void *cb_arg; + + memset(&event, 0x0, sizeof event); + + event.type = BLE_GAP_EVENT_PER_SUBEV_RESP; + memcpy(&event.periodic_adv_response, &resp, + sizeof(struct ble_gap_periodic_adv_response)); + + ble_gap_slave_extract_cb(resp.adv_handle, &cb, &cb_arg); + if (cb != NULL) { + cb(&event, cb_arg); + } + + ble_gap_event_listener_call(&event); +} + +void +ble_gap_rx_conn_comp_failed(const struct ble_gap_conn_complete *evt) +{ + struct ble_gap_event event, event_link_estab; + ble_gap_event_fn *cb; + void *cb_arg; + + memset(&event, 0x0, sizeof event); + memset(&event_link_estab, 0x0, sizeof event); + + event.type = BLE_GAP_EVENT_CONNECT; + event.connect.conn_handle = evt->connection_handle; + event.connect.status = BLE_ERR_CONN_ESTABLISHMENT; + + event.connect.sync_handle = evt->sync_handle; + event.connect.adv_handle = evt->adv_handle; + +//TODO Remove duplication of event fields + event_link_estab.type = BLE_GAP_EVENT_LINK_ESTAB; + event_link_estab.link_estab.conn_handle = evt->connection_handle; + event_link_estab.link_estab.status = BLE_ERR_CONN_ESTABLISHMENT; + + event_link_estab.link_estab.sync_handle = evt->sync_handle; + event_link_estab.link_estab.adv_handle = evt->adv_handle; + + ble_gap_master_reset_state(); + ble_gap_slave_extract_cb(evt->adv_handle, &cb, &cb_arg); + if (cb != NULL) { + cb(&event, cb_arg); + cb(&event_link_estab, cb_arg); + } + + ble_gap_event_listener_call(&event); + ble_gap_event_listener_call(&event_link_estab); +} +#endif + +#if NIMBLE_BLE_CONNECT +static int +ble_gap_rd_rem_sup_feat_tx(uint16_t handle) +{ + struct ble_hci_le_rd_rem_feat_cp cmd; + + cmd.conn_handle = htole16(handle); + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_RD_REM_FEAT), + &cmd, sizeof(cmd), NULL, 0); +} +#endif +static int +ble_gap_rd_rem_ver_tx(uint16_t handle) +{ + struct ble_hci_rd_rem_ver_info_cp cmd; + + cmd.conn_handle = htole16(handle); + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LINK_CTRL, + BLE_HCI_OCF_RD_REM_VER_INFO), + &cmd, sizeof(cmd), NULL, 0); +} + + +/** + * Processes an incoming connection-complete HCI event. * instance parameter is valid only for slave connection. */ int ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) { #if NIMBLE_BLE_CONNECT - struct ble_gap_event event; struct ble_hs_conn *conn; int rc; #if MYNEWT_VAL(BLE_GATT_CACHING) - struct ble_hs_conn_addrs addrs + struct ble_hs_conn_addrs addrs; #endif STATS_INC(ble_gap_stats, rx_conn_complete); +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint8_t v1_evt = 0; + if (evt->adv_handle == 0xFF && evt->sync_handle == 0xFFFF) { + v1_evt = 1; + } +#endif // MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) /* in that case *only* status field is valid so we determine role * based on error code @@ -2167,6 +2638,13 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) } } break; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + case BLE_ERR_CONN_ESTABLISHMENT: + if (!v1_evt) { + ble_gap_rx_conn_comp_failed(evt); + } + break; +#endif // MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) default: /* this should never happen, unless controller is broken */ BLE_HS_LOG(INFO, "controller reported invalid error code in conn" @@ -2220,6 +2698,17 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) conn->bhc_our_addr_type = ble_gap_master.conn.our_addr_type; ble_gap_master_reset_state(); } else { +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + if (!v1_evt) { + conn->bhc_cb = ble_gap_master.cb; + conn->bhc_cb_arg = ble_gap_master.cb_arg; + conn->bhc_our_addr_type = ble_gap_master.conn.our_addr_type; + } else { + conn->bhc_cb = ble_gap_slave[instance].cb; + conn->bhc_cb_arg = ble_gap_slave[instance].cb_arg; + conn->bhc_our_addr_type = ble_gap_slave[instance].our_addr_type; + } +#else conn->bhc_cb = ble_gap_slave[instance].cb; conn->bhc_cb_arg = ble_gap_slave[instance].cb_arg; conn->bhc_our_addr_type = ble_gap_slave[instance].our_addr_type; @@ -2227,7 +2716,8 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) memcpy(conn->bhc_our_rnd_addr, ble_gap_slave[instance].rnd_addr, 6); #endif ble_gap_slave_reset_state(instance); - } +#endif +} conn->bhc_peer_addr.type = evt->peer_addr_type; memcpy(conn->bhc_peer_addr.val, evt->peer_addr, 6); @@ -2250,26 +2740,39 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) ble_hs_lock(); - memset(&event, 0, sizeof event); ble_hs_conn_insert(conn); ble_hs_unlock(); - event.type = BLE_GAP_EVENT_CONNECT; - event.connect.conn_handle = evt->connection_handle; - event.connect.status = 0; - /* add gatt connection */ #if MYNEWT_VAL(BLE_GATT_CACHING) if (evt->role == BLE_HCI_LE_CONN_COMPLETE_ROLE_MASTER) { ble_hs_conn_addrs(conn, &addrs); rc = ble_gattc_cache_conn_create(conn->bhc_handle, addrs.peer_id_addr); + } else { + conn->bhc_gatt_svr.aware_state = true; + conn->bhc_gatt_svr.half_aware = 0; + /* This is also done when bonding is restored, so `conn` and `ble_gatts_conn_aware_states` need to be kept in sync */ + ble_hs_conn_addrs(conn, &addrs); + for (int i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { + if (memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, + addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { + conn->bhc_gatt_svr.half_aware = ble_gatts_conn_aware_states[i].half_aware; + conn->bhc_gatt_svr.aware_state = ble_gatts_conn_aware_states[i].aware; + } + } } #endif - ble_gap_event_listener_call(&event); - ble_gap_call_conn_event_cb(&event, evt->connection_handle); +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + pawr_sync_handle = evt->sync_handle; + pawr_adv_handle = evt->adv_handle; +#endif - ble_gap_rd_rem_sup_feat_tx(evt->connection_handle); + if (evt->role == BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE) { + ble_gap_rd_rem_ver_tx(evt->connection_handle); + } else { + ble_gap_rd_rem_sup_feat_tx(evt->connection_handle); + } return 0; #else @@ -2277,6 +2780,42 @@ ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance) #endif } +void +ble_gap_event_connect_call(uint16_t conn_handle, int status) +{ + struct ble_gap_event event; + uint16_t handle = le16toh(conn_handle); + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_CONNECT; + event.connect.status = status; + event.connect.conn_handle = handle; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.connect.sync_handle = pawr_sync_handle; + event.connect.adv_handle = pawr_adv_handle; +#endif + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, handle); + +//TODO : Remove duplication of event + event.type = BLE_GAP_EVENT_LINK_ESTAB; + event.link_estab.status = status; + event.link_estab.conn_handle = handle; + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + event.link_estab.sync_handle = pawr_sync_handle; + event.link_estab.adv_handle = pawr_adv_handle; +#endif + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, handle); + + ble_hs_hci_util_set_data_len(le16toh(conn_handle), BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX, + BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX); +} + void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev) { @@ -2286,11 +2825,48 @@ ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used ble_hs_lock(); conn = ble_hs_conn_find(le16toh(ev->conn_handle)); - if ((conn != NULL) && (ev->status == 0)) { + + ble_hs_unlock(); + + if ((conn != NULL) && (conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { conn->supported_feat = get_le32(ev->features); + ble_gap_rd_rem_ver_tx(ev->conn_handle); + } else { + if ((conn != NULL) && (ev->status == 0)) { + conn->supported_feat = get_le32(ev->features); + } + + if (conn != NULL) { + ble_gap_event_connect_call(ev->conn_handle, ev->status); + slave_conn[ev->conn_handle] = 1; + } } +#endif +} + +void +ble_gap_rx_rd_rem_ver_info_complete(const struct ble_hci_ev_rd_rem_ver_info_cmp *ev) +{ +#if NIMBLE_BLE_CONNECT + struct ble_hs_conn *conn; + + ble_hs_lock(); + + conn = ble_hs_conn_find(le16toh(ev->conn_handle)); ble_hs_unlock(); + + conn->bhc_rd_rem_ver_params.version = ev->version; + conn->bhc_rd_rem_ver_params.manufacturer = ev->manufacturer; + conn->bhc_rd_rem_ver_params.subversion = ev->subversion; + + if ((conn != NULL) && !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { + ble_gap_rd_rem_sup_feat_tx(ev->conn_handle); + } else { + if ((conn != NULL) && (ev->status == 0)) { + ble_gap_event_connect_call(ev->conn_handle, ev->status); + } + } #endif } @@ -2347,6 +2923,11 @@ ble_gap_rx_data_len_change(const struct ble_hci_ev_le_subev_data_len_chg *ev) event.data_len_chg.max_tx_time = le16toh(ev->max_tx_time); event.data_len_chg.max_rx_time = le16toh(ev->max_rx_time); + g_max_tx_octets[conn_handle] = event.data_len_chg.max_tx_octets; + g_max_rx_octets[conn_handle] = event.data_len_chg.max_rx_octets; + g_max_tx_time[conn_handle] = event.data_len_chg.max_tx_time; + g_max_rx_time[conn_handle] = event.data_len_chg.max_rx_time; + ble_gap_event_listener_call(&event); ble_gap_call_conn_event_cb(&event, conn_handle); #endif @@ -2543,7 +3124,7 @@ ble_gap_wl_busy(void) ble_gap_master.conn.using_wl; } -static int +int ble_gap_wl_tx_add(const ble_addr_t *addr) { struct ble_hci_le_add_whte_list_cp cmd; @@ -2594,7 +3175,7 @@ ble_gap_wl_tx_rmv(const ble_addr_t *addr) } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } memcpy(cmd.addr, addr->val, BLE_DEV_ADDR_LEN); @@ -2621,7 +3202,7 @@ ble_gap_wl_set(const ble_addr_t *addrs, uint8_t white_list_count) STATS_INC(ble_gap_stats, wl_set); if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -2729,7 +3310,7 @@ ble_gap_adv_stop(void) int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -2947,6 +3528,13 @@ ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr, return BLE_HS_EDISABLED; } + ble_hs_lock(); + + rc = ble_gap_adv_validate(own_addr_type, direct_addr, adv_params); + if (rc != 0) { + goto done; + } + #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) ble_adv_reattempt.type = 0; ble_adv_reattempt.own_addr_type = own_addr_type; @@ -2964,13 +3552,6 @@ ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr, ble_adv_reattempt.cb_arg = cb_arg; #endif - ble_hs_lock(); - - rc = ble_gap_adv_validate(own_addr_type, direct_addr, adv_params); - if (rc != 0) { - goto done; - } - if (duration_ms != BLE_HS_FOREVER) { rc = ble_npl_time_ms_to_ticks(duration_ms, &duration_ticks); if (rc != 0) { @@ -3045,7 +3626,7 @@ ble_gap_adv_set_data(const uint8_t *data, int data_len) STATS_INC(ble_gap_stats, adv_set_data); if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } /* Check for valid parameters */ @@ -3073,7 +3654,7 @@ ble_gap_adv_rsp_set_data(const uint8_t *data, int data_len) uint16_t opcode; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } /* Check for valid parameters */ @@ -3102,7 +3683,7 @@ ble_gap_adv_set_fields(const struct ble_hs_adv_fields *adv_fields) int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) memcpy(&ble_adv_reattempt.fields, adv_fields, sizeof( struct ble_hs_adv_fields)); @@ -3160,45 +3741,38 @@ ble_gap_adv_active(void) #if MYNEWT_VAL(BLE_EXT_ADV) static int -ble_gap_ext_adv_params_tx(uint8_t instance, - const struct ble_gap_ext_adv_params *params, - int8_t *selected_tx_power) - +ble_gap_set_ext_adv_params(struct ble_hci_le_set_ext_adv_params_cp *cmd, + uint8_t instance, const struct ble_gap_ext_adv_params *params, + int8_t *selected_tx_power) { - struct ble_hci_le_set_ext_adv_params_cp cmd; - struct ble_hci_le_set_ext_adv_params_rp rsp; - int rc; - - memset(&cmd, 0, sizeof(cmd)); - - cmd.adv_handle = instance; + cmd->adv_handle = instance; if (params->connectable) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_CONNECTABLE; } if (params->scannable) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_SCANNABLE; } if (params->directed) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED; - cmd.peer_addr_type = params->peer.type; - memcpy(cmd.peer_addr, params->peer.val, BLE_DEV_ADDR_LEN); + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_DIRECTED; + cmd->peer_addr_type = params->peer.type; + memcpy(cmd->peer_addr, params->peer.val, BLE_DEV_ADDR_LEN); } if (params->high_duty_directed) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_HD_DIRECTED; } if (params->anonymous) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_ANON_ADV; } if (params->include_tx_power) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR; } if (params->legacy_pdu) { - cmd.props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; + cmd->props |= BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY; /* check right away if the applied configuration is valid before handing * the command to the controller to improve error reporting */ - switch (cmd.props) { + switch (cmd->props) { case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_IND: case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_LD_DIR: case BLE_HCI_LE_SET_EXT_ADV_PROP_LEGACY_HD_DIR: @@ -3213,38 +3787,95 @@ ble_gap_ext_adv_params_tx(uint8_t instance, /* Fill optional fields if application did not specify them. */ if (params->itvl_min == 0 && params->itvl_max == 0) { /* TODO for now limited to legacy values*/ - put_le24(cmd.pri_itvl_min, BLE_GAP_ADV_FAST_INTERVAL1_MIN); - put_le24(cmd.pri_itvl_max, BLE_GAP_ADV_FAST_INTERVAL2_MAX); + put_le24(cmd->pri_itvl_min, BLE_GAP_ADV_FAST_INTERVAL1_MIN); + put_le24(cmd->pri_itvl_max, BLE_GAP_ADV_FAST_INTERVAL2_MAX); } else { - put_le24(cmd.pri_itvl_min, params->itvl_min); - put_le24(cmd.pri_itvl_max, params->itvl_max); + put_le24(cmd->pri_itvl_min, params->itvl_min); + put_le24(cmd->pri_itvl_max, params->itvl_max); } if (params->channel_map == 0) { - cmd.pri_chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP; + cmd->pri_chan_map = BLE_GAP_ADV_DFLT_CHANNEL_MAP; } else { - cmd.pri_chan_map = params->channel_map; + cmd->pri_chan_map = params->channel_map; } /* Zero is the default value for filter policy and high duty cycle */ - cmd.filter_policy = params->filter_policy; - cmd.tx_power = params->tx_power; + cmd->filter_policy = params->filter_policy; + cmd->tx_power = params->tx_power; if (params->legacy_pdu) { - cmd.pri_phy = BLE_HCI_LE_PHY_1M; - cmd.sec_phy = BLE_HCI_LE_PHY_1M; + cmd->pri_phy = BLE_HCI_LE_PHY_1M; + cmd->sec_phy = BLE_HCI_LE_PHY_1M; } else { - cmd.pri_phy = params->primary_phy; - cmd.sec_phy = params->secondary_phy; + cmd->pri_phy = params->primary_phy; + cmd->sec_phy = params->secondary_phy; + } + + cmd->own_addr_type = params->own_addr_type; + cmd->sec_max_skip = 0; + cmd->sid = params->sid; + cmd->scan_req_notif = params->scan_req_notif; + + return 0; +} + +static int +ble_gap_ext_adv_params_tx_v1(uint8_t instance, + const struct ble_gap_ext_adv_params *params, + int8_t *selected_tx_power) +{ + struct ble_hci_le_set_ext_adv_params_cp cmd; + struct ble_hci_le_set_ext_adv_params_rp rsp; + int rc; + + memset(&cmd, 0, sizeof(cmd)); + + rc = ble_gap_set_ext_adv_params(&cmd, instance, params, selected_tx_power); + + if (rc != 0) { + return rc; + } + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM), + &cmd, sizeof(cmd), &rsp, sizeof(rsp)); + + if (rc != 0) { + return rc; + } + + if (selected_tx_power) { + *selected_tx_power = rsp.tx_power; + } + + return 0; + +} + +static int +ble_gap_ext_adv_params_tx_v2(uint8_t instance, + const struct ble_gap_ext_adv_params *params, + int8_t *selected_tx_power) +{ + + struct ble_hci_le_set_ext_adv_params_v2_cp cmd; + struct ble_hci_le_set_ext_adv_params_rp rsp; + int rc; + + memset(&cmd, 0, sizeof(cmd)); + + rc = ble_gap_set_ext_adv_params(&(cmd.cmd), instance, params, selected_tx_power); + + if (rc != 0) { + return rc; } - cmd.own_addr_type = params->own_addr_type; - cmd.sec_max_skip = 0; - cmd.sid = params->sid; - cmd.scan_req_notif = params->scan_req_notif; + cmd.pri_phy_opt = params->primary_phy_opt; + cmd.sec_phy_opt = params->secondary_phy_opt; rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, - BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM), + BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM_V2), &cmd, sizeof(cmd), &rsp, sizeof(rsp)); if (rc != 0) { @@ -3258,6 +3889,32 @@ ble_gap_ext_adv_params_tx(uint8_t instance, return 0; } +static int +ble_gap_ext_adv_params_tx(uint8_t instance, + const struct ble_gap_ext_adv_params *params, + int8_t *selected_tx_power) +{ + struct ble_hs_hci_sup_cmd sup_cmd; + int rc = 0; + + sup_cmd = ble_hs_hci_get_hci_supported_cmd(); + + /* Return Error if phy is non-zero and controller doesn't support V2 */ + if (!((sup_cmd.commands[46] & 0x04) != 0) && + (params->primary_phy_opt || params->secondary_phy_opt)) { + return BLE_HS_EINVAL; + } + + if ((sup_cmd.commands[46] & 0x04) != 0) { + rc = ble_gap_ext_adv_params_tx_v2(instance, params, selected_tx_power); + return rc; + } + + rc = ble_gap_ext_adv_params_tx_v1(instance, params, selected_tx_power); + + return rc; +} + static int ble_gap_ext_adv_params_validate(const struct ble_gap_ext_adv_params *params) { @@ -3331,7 +3988,7 @@ ble_gap_ext_adv_configure(uint8_t instance, } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } rc = ble_gap_ext_adv_params_validate(params); @@ -3470,7 +4127,7 @@ ble_gap_ext_adv_start(uint8_t instance, int duration, int max_events) } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) @@ -3762,24 +4419,21 @@ ble_gap_ext_adv_set_data(uint8_t instance, struct os_mbuf *data) } if (!ble_hs_is_enabled()) { - rc = BLE_HS_EDISABLED; - goto done; + rc = BLE_HS_EDISABLED; + goto done; } #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) uint16_t len = OS_MBUF_PKTLEN(data); + ble_adv_reattempt.type = 1; ble_adv_reattempt.instance = instance; - // Allocate if NULL - if (ble_adv_reattempt.data == NULL) { - ble_adv_reattempt.data = os_msys_get_pkthdr(len , 0); - } - if (ble_adv_reattempt.data && (ble_adv_reattempt.data != data)) { - os_mbuf_adj(ble_adv_reattempt.data, len); - rc = os_mbuf_appendfrom(ble_adv_reattempt.data, data, 0, len); - assert (rc == 0); + if (!ble_adv_reattempt.retry) { + ble_hs_mbuf_to_flat(data, ble_adv_reattempt.data, len, &ble_adv_reattempt.data_len); + } else { + ble_adv_reattempt.retry = 0; } #endif @@ -3795,15 +4449,9 @@ ble_gap_ext_adv_set_data(uint8_t instance, struct os_mbuf *data) ble_hs_unlock(); done: -#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) - if (ble_adv_reattempt.data != data) { - os_mbuf_free_chain(data); - data = NULL; - } -#else os_mbuf_free_chain(data); data = NULL; -#endif + return rc; } @@ -3859,8 +4507,8 @@ ble_gap_ext_adv_rsp_set_data(uint8_t instance, struct os_mbuf *data) } if (!ble_hs_is_enabled()) { - rc = BLE_HS_EDISABLED; - goto done; + rc = BLE_HS_EDISABLED; + goto done; } ble_hs_lock(); @@ -3892,7 +4540,7 @@ ble_gap_ext_adv_remove(uint8_t instance) } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -3929,7 +4577,7 @@ ble_gap_ext_adv_clear(void) uint16_t opcode; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -3971,7 +4619,11 @@ ble_gap_periodic_adv_params_tx(uint8_t instance, const struct ble_gap_periodic_adv_params *params) { +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + struct ble_hci_le_set_periodic_adv_params_v2 cmd; +#else struct ble_hci_le_set_periodic_adv_params_cp cmd; +#endif uint16_t opcode; cmd.adv_handle = instance; @@ -3992,8 +4644,19 @@ ble_gap_periodic_adv_params_tx(uint8_t instance, cmd.props = 0; } - opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS); +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + cmd.num_subevents = params->num_subevents; + cmd.subevent_interval = params->subevent_interval; + cmd.response_slot_delay = params->response_slot_delay; + cmd.response_slot_spacing = params->response_slot_spacing; + cmd.num_response_slots = params->num_response_slots; +#endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS_V2); +#else + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS); +#endif return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); } @@ -4025,12 +4688,12 @@ ble_gap_periodic_adv_configure(uint8_t instance, } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } rc = ble_gap_periodic_adv_params_validate(params); if (rc) { - return rc; + return rc; } ble_hs_lock(); @@ -4080,7 +4743,7 @@ ble_gap_periodic_adv_start(uint8_t instance) } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -4275,8 +4938,8 @@ int ble_gap_periodic_adv_set_data(uint8_t instance, struct os_mbuf *data) } if (!ble_hs_is_enabled()) { - rc = BLE_HS_EDISABLED; - goto done; + rc = BLE_HS_EDISABLED; + goto done; } #if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) @@ -4345,7 +5008,7 @@ ble_gap_periodic_adv_stop(uint8_t instance) } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -4405,7 +5068,7 @@ ble_gap_periodic_adv_sync_create(const ble_addr_t *addr, uint8_t adv_sid, } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -4429,6 +5092,18 @@ ble_gap_periodic_adv_sync_create(const ble_addr_t *addr, uint8_t adv_sid, return BLE_HS_ENOMEM; } +#if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) + ble_conn_reattempt.adv_sid = adv_sid; + + if (addr != NULL ) { + memcpy(&ble_conn_reattempt.periodic_addr, addr, sizeof(ble_addr_t)); + } + if (params != NULL ) { + memcpy(&ble_conn_reattempt.periodic_params, params, sizeof(struct ble_gap_periodic_sync_params)); + } + ble_conn_reattempt.cb = cb; + ble_conn_reattempt.cb_arg = cb_arg; +#endif ble_npl_event_init(&psync->lost_ev, ble_gap_npl_sync_lost, psync); if (addr) { @@ -4453,7 +5128,11 @@ ble_gap_periodic_adv_sync_create(const ble_addr_t *addr, uint8_t adv_sid, cmd.sid = adv_sid; cmd.skip = params->skip; cmd.sync_timeout = htole16(params->sync_timeout); +#if MYNEWT_VAL(BLE_AOA_AOD) + cmd.sync_cte_type = params->sync_cte_type; +#else cmd.sync_cte_type = 0x00; +#endif opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC); rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); @@ -4506,7 +5185,7 @@ ble_gap_periodic_adv_sync_terminate(uint16_t sync_handle) int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -4564,7 +5243,7 @@ ble_gap_periodic_adv_sync_reporting(uint16_t sync_handle, bool enable) int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -4609,7 +5288,7 @@ ble_gap_periodic_adv_sync_transfer(uint16_t sync_handle, uint16_t conn_handle, int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -4657,7 +5336,7 @@ ble_gap_periodic_adv_sync_set_info(uint8_t instance, uint16_t conn_handle, } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -4701,17 +5380,26 @@ periodic_adv_transfer_enable(uint16_t conn_handle, opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_PERIODIC_ADV_SYNC_TRANSFER_PARAMS); + memset(&cmd, 0, sizeof(cmd)); cmd.conn_handle = htole16(conn_handle); - cmd.sync_cte_type = 0x00; - cmd.mode = params->reports_disabled ? 0x01 : 0x02; + + if (params != NULL) { +#if MYNEWT_VAL(BLE_AOA_AOD) + cmd.sync_cte_type = params->sync_cte_type; +#else + cmd.sync_cte_type = 0x00; +#endif + cmd.mode = params->reports_disabled ? 0x01 : 0x02; #if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) - if (params->filter_duplicates) - cmd.mode = 0x03; + if (!params->reports_disabled && params->filter_duplicates) { + cmd.mode = 0x03; + } #endif - cmd.skip = htole16(params->skip); - cmd.sync_timeout = htole16(params->sync_timeout); + cmd.skip = htole16(params->skip); + cmd.sync_timeout = htole16(params->sync_timeout); + } rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp)); if (!rc) { @@ -4736,7 +5424,11 @@ periodic_adv_set_default_sync_params(const struct ble_gap_periodic_sync_params * memset(&cmd, 0, sizeof(cmd)); if (params != NULL) { +#if MYNEWT_VAL(BLE_AOA_AOD) + cmd.sync_cte_type = params->sync_cte_type; +#else cmd.sync_cte_type = 0x00; +#endif cmd.mode = params->reports_disabled ? 0x01 : 0x02; #if MYNEWT_VAL(BLE_PERIODIC_ADV_ENH) @@ -4761,7 +5453,7 @@ ble_gap_periodic_adv_sync_receive(uint16_t conn_handle, int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -4825,7 +5517,7 @@ ble_gap_add_dev_to_periodic_adv_list(const ble_addr_t *peer_addr, } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } cmd.peer_addr_type = peer_addr->type; @@ -4849,7 +5541,7 @@ ble_gap_rem_dev_from_periodic_adv_list(const ble_addr_t *peer_addr, uint8_t adv_ } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } cmd.peer_addr_type = peer_addr->type; @@ -4893,6 +5585,157 @@ ble_gap_read_periodic_adv_list_size(uint8_t *per_adv_list_size) return 0; } +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +static int +ble_gap_calc_periodic_adv_data_size(uint8_t num_subevents, + const struct ble_gap_set_periodic_adv_subev_data_params *params) { + int len = 0; + const struct ble_gap_set_periodic_adv_subev_data_params *param; + int raw_subev_size = sizeof(*param) - sizeof(struct os_mbuf*); + + for(int i = 0; i < num_subevents; i++) { + param = params + i; + len += raw_subev_size; + len += OS_MBUF_PKTLEN(param->data); + } + return len; +} +int +ble_gap_set_periodic_adv_subev_data(uint8_t instance, uint8_t num_subevents, + const struct ble_gap_set_periodic_adv_subev_data_params *params) +{ + struct ble_hci_le_set_periodic_adv_subev_data_cp *cmd; + struct periodic_adv_subevents *subevents; + uint8_t len = ble_gap_calc_periodic_adv_data_size(num_subevents, params); + uint8_t buf[len + 2]; + uint16_t opcode; + uint16_t subev_data_len; + int rc; + + if (instance >= BLE_ADV_INSTANCES) { + rc = BLE_HS_EINVAL; + goto done; + } + + if (!ble_hs_is_enabled()) { + rc = BLE_HS_EDISABLED; + goto done; + } + + /* Check if we can set all of data in one hci command. */ + if ((len + 2) >= 0xff) { + rc = BLE_HS_EINVAL; + goto done; + } + + ble_hs_lock(); + + /* Periodic advertising cannot start unless it is configured before */ + if (!ble_gap_slave[instance].periodic_configured) { + ble_hs_unlock(); + rc = BLE_HS_EINVAL; + goto done; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SUBEV_DATA); + + cmd = (void *) buf; + subevents = cmd->subevents; + + cmd->adv_handle = instance; + cmd->num_subevents = num_subevents; + + for (int i = 0; i < num_subevents; i++) { + subevents->subevent = params[i].subevent; + subevents->response_slot_start = params[i].response_slot_start; + subevents->response_slot_count = params[i].response_slot_count; + ble_hs_mbuf_to_flat(params[i].data, subevents->subevent_data, OS_MBUF_PKTLEN(params[i].data), + (void*)&subev_data_len); + subevents->subevent_data_length = OS_MBUF_PKTLEN(params[i].data); + subevents = (struct periodic_adv_subevents *)( + (uint32_t)subevents + sizeof(struct periodic_adv_subevents) + subev_data_len); + } + + rc = ble_hs_hci_cmd_tx(opcode, cmd, len + 2, NULL, 0); + if (rc != 0) { + ble_hs_unlock(); + goto done; + } + + ble_gap_slave[instance].periodic_op = BLE_GAP_OP_S_PERIODIC_ADV; + + ble_hs_unlock(); + +done: + for (int i = 0; i < num_subevents; i++) { + os_mbuf_free_chain(params[i].data); + } + return rc; +} + +int ble_gap_periodic_adv_set_response_data(uint16_t sync_handle, + struct ble_gap_periodic_adv_response_params *param, + struct os_mbuf *data) +{ + struct ble_hci_le_set_periodic_adv_response_data *cmd; + uint16_t opcode; + int len = sizeof(*cmd); + int data_len = 0; + if (data) { + data_len = OS_MBUF_PKTLEN(data); + } + uint8_t buf[len + data_len]; + + //!TODO: Check if we can set all of data in one hci command. + + cmd = (void *) buf; + + (void)memset(cmd, 0, sizeof(*cmd)); + put_le16(&cmd->sync_handle, sync_handle); + put_le16(&cmd->request_event, param->request_event); + cmd->request_subevent = param->request_subevent; + cmd->response_subevent = param->response_subevent; + cmd->response_slot = param->response_slot; + cmd->response_data_length = data_len; + if (data_len) { + ble_hs_mbuf_to_flat(data, cmd->response_data, data_len, NULL); + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_RESPONSE_DATA); + + return ble_hs_hci_cmd_tx(opcode, cmd, len + data_len, NULL, 0); +} + +int ble_gap_periodic_adv_sync_subev(uint16_t sync_handle, uint8_t include_tx_power, + uint8_t num_subevents, uint8_t *subevents) +{ + struct ble_hci_le_set_periodic_adv_sync_subevent *cmd; + struct ble_hci_le_set_periodic_adv_sync_subevent_rp rsp; + struct ble_hs_periodic_sync *psync; + uint8_t cmd_buf[sizeof(*cmd) + num_subevents]; + uint16_t opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SYNC_SUBEVENT); + int rc; + + psync = ble_hs_periodic_sync_find_by_handle(sync_handle); + if (!psync) { + ble_hs_unlock(); + return BLE_HS_ENOTCONN; + } + + cmd = (void *)cmd_buf; + + put_le16(&cmd->sync_handle, sync_handle); + put_le16(&cmd->periodic_adv_properties, (uint16_t)(include_tx_power << 6)); + cmd->num_subevents = num_subevents; + memcpy(cmd->subevents, subevents, num_subevents); + + rc = ble_hs_hci_cmd_tx(opcode, cmd, sizeof(*cmd) + num_subevents, &rsp, sizeof(rsp)); + if (!rc) { + BLE_HS_DBG_ASSERT(le16toh(rsp.sync_handle) == sync_handle); + } + return rc; +} +#endif #endif /***************************************************************************** @@ -4974,7 +5817,201 @@ ble_gap_ext_disc_enable_tx(uint8_t enable, uint8_t filter_duplicates, &cmd, sizeof(cmd), NULL, 0); } #endif + +#if MYNEWT_VAL(BLE_AOA_AOD) +int +ble_gap_set_connless_cte_transmit_params(uint8_t instance, const struct ble_gap_periodic_adv_cte_params *params) +{ + uint8_t buf[sizeof(struct ble_hci_le_set_connless_cte_tx_params_cp) + + params->switching_pattern_length]; + struct ble_hci_le_set_connless_cte_tx_params_cp *cmd = (void *)buf; + uint8_t len = sizeof(buf); + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONNLESS_CTE_TX_PARAMS); + + cmd->adv_handle = instance; + cmd->cte_length = params->cte_length; + cmd->cte_type = params->cte_type; + cmd->cte_count = params->cte_count; + cmd->switching_pattern_len = params->switching_pattern_length; + memcpy(cmd->switching_pattern, params->antenna_ids, params->switching_pattern_length); + + return ble_hs_hci_cmd_tx(opcode, cmd, len, NULL, 0); +} + +int +ble_gap_set_connless_cte_transmit_enable(uint8_t instance, uint8_t cte_enable) +{ + struct ble_hci_le_set_connless_cte_tx_enable_cp cmd; + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONNLESS_CTE_TX_ENABLE); + + cmd.adv_handle = instance; + cmd.cte_enable = cte_enable; + + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); +} + +int +ble_gap_set_connless_iq_sampling_enable(uint16_t sync_handle, uint8_t sampling_enable, uint8_t max_sampled_ctes, + const struct ble_gap_cte_sampling_params *cte_sampling_params) +{ + uint8_t buf[sizeof(struct ble_hci_le_set_connless_iq_sampling_enable_cp) + + cte_sampling_params->switching_pattern_length]; + struct ble_hci_le_set_connless_iq_sampling_enable_cp *cmd = (struct ble_hci_le_set_connless_iq_sampling_enable_cp*)buf; + struct ble_hci_le_set_connless_iq_sampling_enable_rp rsp; + uint8_t len = sizeof(buf); + uint16_t opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONNLESS_IQ_SAMPLING_ENABLE); + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + cmd->sync_handle = htole16(sync_handle); + cmd->sampling_enable = sampling_enable; + cmd->max_sampled_ctes = max_sampled_ctes; + cmd->slot_durations = cte_sampling_params->slot_durations; + cmd->switching_pattern_len = cte_sampling_params->switching_pattern_length; + memcpy(cmd->antenna_ids, cte_sampling_params->antenna_ids, cte_sampling_params->switching_pattern_length); + + return ble_hs_hci_cmd_tx(opcode, cmd, len, &rsp, sizeof(rsp)); +} + +int +ble_gap_set_conn_cte_recv_param(uint16_t conn_handle, uint8_t sampling_enable, const struct ble_gap_cte_sampling_params *cte_sampling_params) +{ + uint8_t buf[sizeof(struct ble_hci_le_set_conn_cte_rx_params_cp) + cte_sampling_params->switching_pattern_length]; + struct ble_hci_le_set_conn_cte_rx_params_cp *cmd = (void *)buf; + struct ble_hci_le_set_conn_cte_rx_params_rp rsp; + uint8_t len = sizeof(buf); + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONN_CTE_RX_PARAMS); + + cmd->conn_handle = conn_handle; + cmd->sampling_enable = sampling_enable; + cmd->slot_durations = cte_sampling_params->slot_durations; + cmd->switching_pattern_len = cte_sampling_params->switching_pattern_length; + memcpy(cmd->antenna_ids, cte_sampling_params->antenna_ids, cte_sampling_params->switching_pattern_length); + + return ble_hs_hci_cmd_tx(opcode, cmd, len, &rsp, sizeof(rsp)); +} + +int +ble_gap_set_conn_cte_transmit_param(uint16_t conn_handle, uint8_t cte_types, uint8_t switching_pattern_len, const uint8_t *antenna_ids) +{ + uint8_t buf[sizeof(struct ble_hci_le_set_conn_cte_tx_params_cp) + switching_pattern_len]; + struct ble_hci_le_set_conn_cte_tx_params_cp *cmd = (void *)buf; + struct ble_hci_le_set_conn_cte_tx_params_rp rsp; + uint8_t len = sizeof(buf); + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONN_CTE_TX_PARAMS); + + cmd->conn_handle = htole16(conn_handle); + cmd->cte_types = cte_types; + if (cmd->cte_types != BIT(0) && (switching_pattern_len == 0 || antenna_ids == NULL)) { + BLE_HS_LOG(ERROR, "Invalid antenna_ids!\n"); + return BLE_HS_EINVAL; + } + cmd->switching_pattern_len = switching_pattern_len; + memcpy(cmd->antenna_ids, antenna_ids, switching_pattern_len); + + + return ble_hs_hci_cmd_tx(opcode, cmd, len, &rsp, sizeof(rsp)); +} + +int +ble_gap_conn_cte_req_enable(uint16_t conn_handle, uint8_t enable, uint16_t cte_request_interval, + uint8_t requested_cte_length, uint8_t requested_cte_type) +{ + uint8_t buf[sizeof(struct ble_gap_conn_cte_req_enable_cp)]; + struct ble_gap_conn_cte_req_enable_cp *cmd = (void *)buf; + struct ble_gap_conn_cte_req_enable_rp rsp; + uint8_t len = sizeof(buf); + uint16_t opcode; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONN_CTE_REQ_ENABLE); + + cmd->conn_handle = htole16(conn_handle); + cmd->enable = enable; + cmd->cte_request_interval = htole16(cte_request_interval); + cmd->requested_cte_length = requested_cte_length; + cmd->requested_cte_type = requested_cte_type; + + return ble_hs_hci_cmd_tx(opcode, cmd, len, &rsp, sizeof(rsp)); +} + +int +ble_gap_conn_cte_rsp_enable(uint16_t conn_handle, uint8_t enable) +{ + struct ble_hci_le_set_conn_cte_rsp_enable_cp cmd; + struct ble_hci_le_set_conn_cte_rsp_enable_rp rsp; + uint16_t opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SET_CONN_CTE_RESP_ENABLE); + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + cmd.conn_handle = htole16(conn_handle); + cmd.enable = enable; + + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp)); +} + +int +ble_gap_read_antenna_information(uint8_t *switch_sampling_rates, uint8_t *num_antennae, uint8_t *max_switch_pattern_len, uint8_t *max_cte_len) +{ + struct ble_hci_le_rd_antenna_info_rp rsp; + uint16_t opcode; + int rc = 0; + + if (!ble_hs_is_enabled()) { + return BLE_HS_EDISABLED; + } + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_ANTENNA_INFO); + + rc = ble_hs_hci_cmd_tx(opcode, NULL, 0, &rsp, sizeof(rsp)); + + if (rc != 0) { + return rc; + } + + *switch_sampling_rates = rsp.switch_sampling_rates; + *num_antennae = rsp.num_antennae; + *max_switch_pattern_len = rsp.max_switch_pattern_len; + *max_cte_len = rsp.max_cte_len; + + return 0; +} + +#endif // MYNEWT_VAL(BLE_AOA_AOD) + #endif + #if NIMBLE_BLE_SCAN #if !MYNEWT_VAL(BLE_EXT_ADV) static int @@ -5060,7 +6097,7 @@ ble_gap_disc_cancel(void) int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } #if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) @@ -5161,7 +6198,7 @@ ble_gap_ext_disc(uint8_t own_addr_type, uint16_t duration, uint16_t period, STATS_INC(ble_gap_stats, discover); if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -5298,7 +6335,7 @@ ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms, struct ble_gap_ext_disc_params p = {0}; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } p.itvl = disc_params->itvl; @@ -5323,7 +6360,7 @@ ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms, STATS_INC(ble_gap_stats, discover); if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -5488,55 +6525,291 @@ ble_gap_subrate_req(uint16_t conn_handle, uint16_t subrate_min, uint16_t subrate opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_SUBRATE_REQ); - return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); -} -#endif + return ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), NULL, 0); +} +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) || (MYNEWT_VAL(BLE_EXT_ADV) && MYNEWT_VAL(BLE_ROLE_CENTRAL)) +static int +ble_gap_check_conn_params(uint8_t phy, const struct ble_gap_conn_params *params) +{ + if (phy != BLE_HCI_LE_PHY_2M) { + /* Check scan interval and window */ + if ((params->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || + (params->scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || + (params->scan_window < BLE_HCI_SCAN_WINDOW_MIN) || + (params->scan_window > BLE_HCI_SCAN_WINDOW_MAX) || + (params->scan_itvl < params->scan_window)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + } + /* Check connection interval min */ + if ((params->itvl_min < BLE_HCI_CONN_ITVL_MIN) || + (params->itvl_min > BLE_HCI_CONN_ITVL_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + /* Check connection interval max */ + if ((params->itvl_max < BLE_HCI_CONN_ITVL_MIN) || + (params->itvl_max > BLE_HCI_CONN_ITVL_MAX) || + (params->itvl_max < params->itvl_min)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check connection latency */ + if (params->latency > BLE_HCI_CONN_LATENCY_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check supervision timeout */ + if ((params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || + (params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + /* Check connection event length */ + if (params->min_ce_len > params->max_ce_len) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return 0; +} +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +static int +ble_gap_ext_conn_create_conn_synced_tx(uint8_t own_addr_type, + uint8_t advertising_handle, uint8_t subevent, + const ble_addr_t *peer_addr, uint8_t phy_mask, + const struct ble_gap_conn_params *phy_1m_conn_params, + const struct ble_gap_conn_params *phy_2m_conn_params, + const struct ble_gap_conn_params *phy_coded_conn_params) +{ + struct ble_hci_le_ext_create_conn_v2_cp *cmd; + struct conn_params *params; + uint8_t buf[sizeof(*cmd) + 3 * sizeof(*params)]; + uint8_t len = sizeof(*cmd); + int rc; + + /* Check own addr type */ + if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (phy_mask > (BLE_HCI_LE_PHY_1M_PREF_MASK | + BLE_HCI_LE_PHY_2M_PREF_MASK | + BLE_HCI_LE_PHY_CODED_PREF_MASK)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + cmd = (void *) buf; + params = cmd->conn_params; + if (peer_addr == NULL) { + /* Application wants to connect to any device in the white list. The + * peer address type and peer address fields are ignored by the + * controller; fill them with dummy values. + */ + cmd->filter_policy = BLE_HCI_CONN_FILT_USE_WL; + cmd->peer_addr_type = 0; + memset(cmd->peer_addr, 0, sizeof(cmd->peer_addr)); + } else { + /* Check peer addr type */ + if (peer_addr->type > BLE_HCI_CONN_PEER_ADDR_MAX) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + cmd->filter_policy = BLE_HCI_CONN_FILT_NO_WL; + cmd->peer_addr_type = peer_addr->type; + memcpy(cmd->peer_addr, peer_addr->val, sizeof(cmd->peer_addr)); + } + + cmd->own_addr_type = own_addr_type; + cmd->init_phy_mask = phy_mask; + + cmd->adv_handle = advertising_handle; + cmd->subevent = subevent; + + if (phy_mask & BLE_GAP_LE_PHY_1M_MASK) { + rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_1M, phy_1m_conn_params); + if (rc) { + return rc; + } + + params->scan_itvl = htole16(phy_1m_conn_params->scan_itvl); + params->scan_window = htole16(phy_1m_conn_params->scan_window); + params->conn_min_itvl = htole16(phy_1m_conn_params->itvl_min); + params->conn_max_itvl = htole16(phy_1m_conn_params->itvl_max); + params->conn_latency = htole16(phy_1m_conn_params->latency); + params->supervision_timeout = htole16(phy_1m_conn_params->supervision_timeout); + params->min_ce = htole16(phy_1m_conn_params->min_ce_len); + params->max_ce = htole16(phy_1m_conn_params->max_ce_len); + + params++; + len += sizeof(*params); + } + + if (phy_mask & BLE_GAP_LE_PHY_2M_MASK) { + rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_2M, phy_2m_conn_params); + if (rc) { + return rc; + } + + params->scan_itvl = htole16(phy_2m_conn_params->scan_itvl); + params->scan_window = htole16(phy_2m_conn_params->scan_window); + params->conn_min_itvl = htole16(phy_2m_conn_params->itvl_min); + params->conn_max_itvl = htole16(phy_2m_conn_params->itvl_max); + params->conn_latency = htole16(phy_2m_conn_params->latency); + params->supervision_timeout = htole16(phy_2m_conn_params->supervision_timeout); + params->min_ce = htole16(phy_2m_conn_params->min_ce_len); + params->max_ce = htole16(phy_2m_conn_params->max_ce_len); + + params++; + len += sizeof(*params); + } + + if (phy_mask & BLE_GAP_LE_PHY_CODED_MASK) { + rc = ble_gap_check_conn_params(BLE_HCI_LE_PHY_CODED, phy_coded_conn_params); + if (rc) { + return rc; + } + + params->scan_itvl = htole16(phy_coded_conn_params->scan_itvl); + params->scan_window = htole16(phy_coded_conn_params->scan_window); + params->conn_min_itvl = htole16(phy_coded_conn_params->itvl_min); + params->conn_max_itvl = htole16(phy_coded_conn_params->itvl_max); + params->conn_latency = htole16(phy_coded_conn_params->latency); + params->supervision_timeout = htole16(phy_coded_conn_params->supervision_timeout); + params->min_ce = htole16(phy_coded_conn_params->min_ce_len); + params->max_ce = htole16(phy_coded_conn_params->max_ce_len); + + params++; + len += sizeof(*params); + } + + return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, + BLE_HCI_LE_EXT_CREATE_CONN_V2), + cmd, len, NULL, 0); +} + + +int +ble_gap_connect_with_synced(uint8_t own_addr_type, uint8_t advertising_handle, + uint8_t subevent, const ble_addr_t *peer_addr, + int32_t duration_ms, uint8_t phy_mask, + const struct ble_gap_conn_params *phy_1m_conn_params, + const struct ble_gap_conn_params *phy_2m_conn_params, + const struct ble_gap_conn_params *phy_coded_conn_params, + ble_gap_event_fn *cb, void *cb_arg) +{ + int rc; + + STATS_INC(ble_gap_stats, initiate); + + ble_hs_lock(); + + if (ble_gap_conn_active()) { + rc = BLE_HS_EALREADY; + goto done; + } + + if (ble_gap_disc_active()) { + rc = BLE_HS_EBUSY; + goto done; + } + + if (!ble_hs_is_enabled()) { + rc = BLE_HS_EDISABLED; + goto done; + } + + if (ble_gap_is_preempted()) { + rc = BLE_HS_EPREEMPTED; + goto done; + } + + if (!ble_hs_conn_can_alloc()) { + rc = BLE_HS_ENOMEM; + goto done; + } + + if (peer_addr && + peer_addr->type != BLE_ADDR_PUBLIC && + peer_addr->type != BLE_ADDR_RANDOM && + peer_addr->type != BLE_ADDR_PUBLIC_ID && + peer_addr->type != BLE_ADDR_RANDOM_ID) { + + rc = BLE_HS_EINVAL; + goto done; + } + + if ((phy_mask & BLE_GAP_LE_PHY_1M_MASK) && phy_1m_conn_params == NULL) { + phy_1m_conn_params = &ble_gap_conn_params_dflt; + } + + if ((phy_mask & BLE_GAP_LE_PHY_2M_MASK) && phy_2m_conn_params == NULL) { + phy_2m_conn_params = &ble_gap_conn_params_dflt; + } + + if ((phy_mask & BLE_GAP_LE_PHY_CODED_MASK) && + phy_coded_conn_params == NULL) { -#if MYNEWT_VAL(BLE_EXT_ADV) -#if MYNEWT_VAL(BLE_ROLE_CENTRAL) -static int -ble_gap_check_conn_params(uint8_t phy, const struct ble_gap_conn_params *params) -{ - if (phy != BLE_HCI_LE_PHY_2M) { - /* Check scan interval and window */ - if ((params->scan_itvl < BLE_HCI_SCAN_ITVL_MIN) || - (params->scan_itvl > BLE_HCI_SCAN_ITVL_MAX) || - (params->scan_window < BLE_HCI_SCAN_WINDOW_MIN) || - (params->scan_window > BLE_HCI_SCAN_WINDOW_MAX) || - (params->scan_itvl < params->scan_window)) { - return BLE_ERR_INV_HCI_CMD_PARMS; - } + phy_coded_conn_params = &ble_gap_conn_params_dflt; } - /* Check connection interval min */ - if ((params->itvl_min < BLE_HCI_CONN_ITVL_MIN) || - (params->itvl_min > BLE_HCI_CONN_ITVL_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; + + if (duration_ms == 0) { + duration_ms = BLE_GAP_CONN_DUR_DFLT; } - /* Check connection interval max */ - if ((params->itvl_max < BLE_HCI_CONN_ITVL_MIN) || - (params->itvl_max > BLE_HCI_CONN_ITVL_MAX) || - (params->itvl_max < params->itvl_min)) { - return BLE_ERR_INV_HCI_CMD_PARMS; + + /* The connection creation timeout is not really useful for PAwR. + * The controller will give a result for the connection attempt + * within a periodic interval. We do not know the periodic interval + * used, so disable the timeout. + */ + + /* Verify peer not already connected. */ + if (ble_hs_conn_find_by_addr(peer_addr) != NULL) { + rc = BLE_HS_EDONE; + goto done; } - /* Check connection latency */ - if (params->latency > BLE_HCI_CONN_LATENCY_MAX) { - return BLE_ERR_INV_HCI_CMD_PARMS; + /* XXX: Verify conn_params. */ + + rc = ble_hs_id_use_addr(own_addr_type); + if (rc != 0) { + goto done; } - /* Check supervision timeout */ - if ((params->supervision_timeout < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) || - (params->supervision_timeout > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) { - return BLE_ERR_INV_HCI_CMD_PARMS; + BLE_HS_LOG(INFO, "GAP procedure initiated: extended connect; \n"); + + ble_gap_master.cb = cb; + ble_gap_master.cb_arg = cb_arg; + ble_gap_master.conn.using_wl = peer_addr == NULL; + ble_gap_master.conn.our_addr_type = own_addr_type; + + ble_gap_master.op = BLE_GAP_OP_M_CONN; + + rc = ble_gap_ext_conn_create_conn_synced_tx(own_addr_type,advertising_handle,subevent, peer_addr, phy_mask, + phy_1m_conn_params, phy_2m_conn_params, + phy_coded_conn_params); + if (rc != 0) { + ble_gap_master_reset_state(); + goto done; } - /* Check connection event length */ - if (params->min_ce_len > params->max_ce_len) { - return BLE_ERR_INV_HCI_CMD_PARMS; + rc = 0; + +done: + ble_hs_unlock(); + + if (rc != 0) { + STATS_INC(ble_gap_stats, initiate_fail); } + return rc; - return 0; } +#endif + +#if MYNEWT_VAL(BLE_EXT_ADV) +#if MYNEWT_VAL(BLE_ROLE_CENTRAL) static int ble_gap_ext_conn_create_tx( @@ -5648,7 +6921,60 @@ ble_gap_ext_conn_create_tx( BLE_HCI_OCF_LE_EXT_CREATE_CONN), cmd, len, NULL, 0); } -#endif + +/** + * Initiates a connect procedure. + * + * @param own_addr_type The type of address the stack should use for + * itself during connection establishment. + * o BLE_OWN_ADDR_PUBLIC + * o BLE_OWN_ADDR_RANDOM + * o BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT + * o BLE_OWN_ADDR_RPA_RANDOM_DEFAULT + * @param peer_addr The address of the peer to connect to. + * If this parameter is NULL, the white list + * is used. + * @param duration_ms The duration of the discovery procedure. + * On expiration, the procedure ends and a + * BLE_GAP_EVENT_DISC_COMPLETE event is + * reported. Units are milliseconds. + * @param phy_mask Define on which PHYs connection attempt should + * be done + * @param phy_1m_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_1M_MASK is set in phy_mask + * this parameter can be specify to null for + * default values. + * @param phy_2m_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_2M_MASK is set in phy_mask + * this parameter can be specify to null for + * default values. + * @param phy_coded_conn_params Additional arguments specifying the + * particulars of the connect procedure. When + * BLE_GAP_LE_PHY_CODED_MASK is set in + * phy_mask this parameter can be specify to + * null for default values. + * @param cb The callback to associate with this connect + * procedure. When the connect procedure + * completes, the result is reported through + * this callback. If the connect procedure + * succeeds, the connection inherits this + * callback as its event-reporting mechanism. + * @param cb_arg The optional argument to pass to the callback + * function. + * + * @return 0 on success; + * BLE_HS_EALREADY if a connection attempt is + * already in progress; + * BLE_HS_EBUSY if initiating a connection is not + * possible because scanning is in progress; + * BLE_HS_EDONE if the specified peer is already + * connected; + * Other nonzero on error. + */ + +#endif // MYNEWT_VAL(BLE_ROLE_CENTRAL) /** * Initiates a connect procedure. @@ -5731,14 +7057,16 @@ ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, goto done; } +#if !MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN) if (ble_gap_disc_active()) { rc = BLE_HS_EBUSY; goto done; } +#endif if (!ble_hs_is_enabled()) { rc = BLE_HS_EDISABLED; - goto done; + goto done; } if (ble_gap_is_preempted()) { @@ -5822,21 +7150,22 @@ ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, } ble_conn_reattempt.duration_ms = duration_ms; + ble_conn_reattempt.phy_mask = phy_mask; if (phy_mask & BLE_GAP_LE_PHY_1M_MASK) { - memcpy(&ble_conn_reattempt.conn_params, + memcpy(&ble_conn_reattempt.conn_params_1m, phy_1m_conn_params, sizeof(struct ble_gap_conn_params)); } if (phy_mask & BLE_GAP_LE_PHY_2M_MASK) { - memcpy(&ble_conn_reattempt.conn_params, + memcpy(&ble_conn_reattempt.conn_params_2m, phy_2m_conn_params, sizeof(struct ble_gap_conn_params)); } if (phy_mask & BLE_GAP_LE_PHY_CODED_MASK) { - memcpy(&ble_conn_reattempt.conn_params, + memcpy(&ble_conn_reattempt.conn_params_coded, phy_coded_conn_params, sizeof(struct ble_gap_conn_params)); } @@ -5908,10 +7237,12 @@ ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, goto done; } +#if !MYNEWT_VAL(BLE_HOST_ALLOW_CONNECT_WITH_SCAN) if (ble_gap_disc_active()) { rc = BLE_HS_EBUSY; goto done; } +#endif if (!ble_hs_is_enabled()) { rc = BLE_HS_EDISABLED; @@ -6012,7 +7343,7 @@ ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr, } ble_conn_reattempt.duration_ms = duration_ms; - memcpy(&ble_conn_reattempt.conn_params, + memcpy(&ble_conn_reattempt.conn_params_1m, conn_params, sizeof(struct ble_gap_conn_params)); ble_conn_reattempt.cb = cb; @@ -6128,6 +7459,7 @@ ble_gap_multi_connect(struct ble_gap_multi_conn_params *multi_conn_params, #endif // MYNEWT_VAL(BLE_EXT_ADV) scheduling_len_us = multi_conn_params->scheduling_len_us; + /* `scheduling_len_us == 0` is allowed. It indicates that the optimization for this connection * is disabled. The connection interval must be an integer multiple of `common factor`. Note * that the unit of the connection interval is 1.25ms, while the common factor's unit is 0.625ms. @@ -6186,7 +7518,7 @@ ble_gap_multi_connect(struct ble_gap_multi_conn_params *multi_conn_params, multi_conn_params->phy_2m_conn_params, multi_conn_params->phy_coded_conn_params, cb, cb_arg); #else - rc = ble_gap_ext_connect(multi_conn_params->own_addr_type, multi_conn_params->peer_addr, + rc = ble_gap_connect(multi_conn_params->own_addr_type, multi_conn_params->peer_addr, multi_conn_params->duration_ms, multi_conn_params->phy_1m_conn_params, cb, cb_arg); #endif // MYNEWT_VAL(BLE_EXT_ADV) @@ -6254,7 +7586,7 @@ ble_gap_terminate(uint16_t conn_handle, uint8_t hci_reason) STATS_INC(ble_gap_stats, terminate); if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -6337,7 +7669,7 @@ ble_gap_conn_cancel(void) int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -6603,7 +7935,7 @@ ble_gap_update_params(uint16_t conn_handle, } if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } STATS_INC(ble_gap_stats, update); @@ -6680,24 +8012,55 @@ ble_gap_update_params(uint16_t conn_handle, #endif } -int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time) +int +ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, + uint16_t tx_time) { + /* Check if host has triggered Set data len for same parameters + * which are currently set in controller. + * If yes, then just return event to host indicating success + * since controller will not send any event in this scenario + */ + if (g_max_tx_time[conn_handle] == tx_time && g_max_tx_octets[conn_handle] == tx_octets) { + + struct ble_gap_event event; + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_DATA_LEN_CHG; + event.data_len_chg.max_tx_octets = g_max_tx_octets[conn_handle]; + event.data_len_chg.max_rx_octets = g_max_rx_octets[conn_handle]; + event.data_len_chg.max_tx_time = g_max_tx_time[conn_handle]; + event.data_len_chg.max_rx_time = g_max_rx_time[conn_handle]; + event.data_len_chg.conn_handle = conn_handle; + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, conn_handle); + + return 0; + } + return ble_hs_hci_util_set_data_len(conn_handle, tx_octets, tx_time); } -int ble_gap_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets, uint16_t *out_sugg_max_tx_time) +int +ble_gap_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets, + uint16_t *out_sugg_max_tx_time) { - return ble_hs_hci_util_read_sugg_def_data_len(out_sugg_max_tx_octets, out_sugg_max_tx_time); + return ble_hs_hci_util_read_sugg_def_data_len(out_sugg_max_tx_octets, + out_sugg_max_tx_time); } -int ble_gap_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, uint16_t sugg_max_tx_time) +int +ble_gap_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, + uint16_t sugg_max_tx_time) { - return ble_hs_hci_util_write_sugg_def_data_len(sugg_max_tx_octets, sugg_max_tx_time); + return ble_hs_hci_util_write_sugg_def_data_len(sugg_max_tx_octets, + sugg_max_tx_time); } /***************************************************************************** - * $security * - *****************************************************************************/ +* $security * +*****************************************************************************/ int ble_gap_security_initiate(uint16_t conn_handle) { @@ -6712,7 +8075,7 @@ ble_gap_security_initiate(uint16_t conn_handle) STATS_INC(ble_gap_stats, security_initiate); if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } ble_hs_lock(); @@ -6775,7 +8138,9 @@ ble_gap_security_initiate(uint16_t conn_handle) int ble_gap_dev_authorization(uint16_t conn_handle, bool authorized) { + ble_hs_lock(); struct ble_hs_conn *conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); if (conn != NULL) { if (!(conn->bhc_sec_state.authenticated)) { @@ -6806,7 +8171,7 @@ ble_gap_pair_initiate(uint16_t conn_handle) int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } rc = ble_sm_pair_initiate(conn_handle); @@ -6827,7 +8192,7 @@ ble_gap_encryption_initiate(uint16_t conn_handle, int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } rc = ble_hs_atomic_conn_flags(conn_handle, &conn_flags); @@ -6847,20 +8212,65 @@ ble_gap_encryption_initiate(uint16_t conn_handle, #endif } +#if NIMBLE_BLE_SM && MYNEWT_VAL(BLE_SMP_ID_RESET) +static void +ble_gap_reset_irk(void) +{ + ble_addr_t oldest_peer_id_addr[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; + struct ble_store_value_local_irk value_local_irk; + struct ble_store_key_local_irk key_local_irk; + uint8_t *local_id = NULL; + int rc, num_peers; + uint8_t tmp_addr[6]; + + ble_store_util_bonded_peers(&oldest_peer_id_addr[0], &num_peers, + MYNEWT_VAL(BLE_STORE_MAX_BONDS)); + + if (num_peers != 0) { + return ; + } + + memset(&key_local_irk, 0, sizeof key_local_irk); + memset(&value_local_irk, 0x0, sizeof value_local_irk); + + ble_hs_id_addr(BLE_ADDR_PUBLIC, (const uint8_t **) &local_id, NULL); + + if (local_id) { + memcpy (key_local_irk.addr.val , local_id, BLE_DEV_ADDR_LEN); + } + + key_local_irk.addr.type = BLE_ADDR_PUBLIC; + + ble_store_delete_local_irk(&key_local_irk); + + ble_hs_pvcy_set_default_irk(); + + //Remove the previous entry pertaining to 00:00:00:00:00:00 address + memset(tmp_addr, 0, 6); + rc = ble_hs_pvcy_remove_entry(0, tmp_addr); + if (rc != 0) { + BLE_HS_LOG(INFO, "Failed to remove old all zero IRK"); + return; + } + + ble_hs_pvcy_set_our_irk(NULL); + + BLE_HS_LOG(INFO,"Local IRK Reset"); +} +#endif + int ble_gap_unpair(const ble_addr_t *peer_addr) { #if NIMBLE_BLE_SM - int rc; - int ltk_rc = 0; - int irk_rc = 0; + int rc, err = 0; struct ble_hs_conn *conn; union ble_store_value value; union ble_store_key key; ble_addr_t *new_addr = (ble_addr_t *) peer_addr; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } if (ble_addr_cmp(peer_addr, BLE_ADDR_ANY) == 0) { @@ -6897,32 +8307,46 @@ ble_gap_unpair(const ble_addr_t *peer_addr) // Checking if the device is in ble_store if (!rc) { if (value.sec.irk_present) { + /* We cannot delete entry from resolving list if there is ongoing + * discovery or advertising in progress */ + + if (ble_gap_adv_active() || + ble_gap_disc_active()) { + return BLE_HS_EBUSY; + } + // Delete the IRK as it is Distributed - irk_rc = ble_hs_pvcy_remove_entry(key.sec.peer_addr.type, - key.sec.peer_addr.val); - if (irk_rc != 0) { - BLE_HS_LOG(ERROR, "Error while removing IRK , rc = %x\n",irk_rc); + rc = ble_hs_pvcy_remove_entry(key.sec.peer_addr.type,key.sec.peer_addr.val); + if (rc != 0) { + BLE_HS_LOG(ERROR, "Error while removing IRK , rc = %x\n",rc); } } - if (value.sec.ltk_present || value.sec.irk_present || value.sec.csrk_present) { - // Delete the Peer record from store as LTK is present - ltk_rc = ble_store_util_delete_peer(&key.sec.peer_addr); - if (ltk_rc != 0) { - BLE_HS_LOG(ERROR, "Error while removing LTK , rc = %x\n",ltk_rc); - } + // Delete the Peer record from store as LTK is present + rc = ble_store_util_delete_peer(&key.sec.peer_addr); + if (rc != 0) { + BLE_HS_LOG(ERROR, "Error while removing LTK , rc = %x\n",rc); } - } - else { - rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_SEC, &key, &value); - if(!rc) { + } else { + rc = ble_store_read(BLE_STORE_OBJ_TYPE_OUR_SEC, &key, &value); + if (!rc) { ble_store_util_delete_peer(&key.sec.peer_addr); - } - else { - BLE_HS_LOG(ERROR,"No record found for the given address in ble store , rc = %x\n",rc); - return rc; - } + } else { + BLE_HS_LOG(ERROR,"No record found for the given address in ble store , rc = %x\n",rc); + err = rc ; + } + } + +#if MYNEWT_VAL(BLE_SMP_ID_RESET) + /* There are tracking risks associated with using a fixed or static IRK. + * A best-practices approach, when all pairing and bonding records are deleted, + * assign a new randomly-generated IRK. + */ + ble_gap_reset_irk(); +#endif + if (err) { + return err; } return 0; @@ -6940,7 +8364,7 @@ ble_gap_unpair_oldest_peer(void) int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } rc = ble_store_util_bonded_peers( @@ -6974,7 +8398,7 @@ ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr) int rc, i; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } rc = ble_store_util_bonded_peers( @@ -7068,7 +8492,7 @@ ble_gap_enc_event(uint16_t conn_handle, int status, } void -ble_gap_identity_event(uint16_t conn_handle) +ble_gap_identity_event(uint16_t conn_handle, const ble_addr_t *peer_id_addr) { #if NIMBLE_BLE_SM && NIMBLE_BLE_CONNECT struct ble_gap_event event; @@ -7078,6 +8502,7 @@ ble_gap_identity_event(uint16_t conn_handle) memset(&event, 0, sizeof event); event.type = BLE_GAP_EVENT_IDENTITY_RESOLVED; event.identity_resolved.conn_handle = conn_handle; + event.identity_resolved.peer_id_addr = *peer_id_addr; ble_gap_call_conn_event_cb(&event, conn_handle); #endif } @@ -7099,6 +8524,20 @@ ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing *rp) #endif } +void +ble_gap_pairing_complete_event(uint16_t conn_handle, int status) +{ +#if NIMBLE_BLE_SM && NIMBLE_BLE_CONNECT + struct ble_gap_event event; + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_PARING_COMPLETE; + event.pairing_complete.conn_handle = conn_handle; + event.pairing_complete.status = status; + ble_gap_call_conn_event_cb(&event, conn_handle); +#endif +} + /***************************************************************************** * $rssi * *****************************************************************************/ @@ -7109,7 +8548,7 @@ ble_gap_conn_rssi(uint16_t conn_handle, int8_t *out_rssi) int rc; if (!ble_hs_is_enabled()) { - return BLE_HS_EDISABLED; + return BLE_HS_EDISABLED; } rc = ble_hs_hci_util_read_rssi(conn_handle, out_rssi); @@ -7236,6 +8675,19 @@ ble_gap_vs_hci_event(const void *buf, uint8_t len) ble_gap_event_listener_call(&event); } + +int +ble_hs_send_vs_event_mask(uint32_t event_mask) +{ + struct ble_hci_vs_set_event_mask_cp cmd; + + /* Populate command */ + cmd.event_mask = htole32(event_mask); + + /* Send command via HCI */ + return ble_hs_hci_send_vs_cmd(BLE_HCI_OCF_VS_SET_EVT_MASK, + &cmd, sizeof(cmd), NULL, 0); +} #endif int @@ -7323,6 +8775,27 @@ ble_gap_end_test_evt(const void *buf, uint8_t len) ble_gap_event_listener_call(&event); } +/***************************************************************************** + * EATT * + *****************************************************************************/ +void +ble_gap_eatt_event(uint16_t conn_handle, uint8_t status, uint16_t cid) +{ +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + struct ble_gap_event event; + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_EATT; + + event.eatt.conn_handle = conn_handle; + event.eatt.status = status; + event.eatt.cid = cid; + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, conn_handle); +#endif +} + /***************************************************************************** * $preempt * *****************************************************************************/ @@ -7708,6 +9181,30 @@ ble_gap_set_transmit_power_reporting_enable(uint16_t conn_handle, return BLE_HS_ENOTSUP; #endif } +int +ble_gap_rd_local_resolv_addr(uint8_t peer_addr_type, const ble_addr_t *peer_addr, + uint8_t *out_addr) +{ + struct ble_hci_le_rd_local_resolv_addr_cp cmd; + struct ble_hci_le_rd_local_resolv_addr_rp rsp; + uint16_t opcode; + int rc; + + opcode = BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR); + + cmd.peer_addr_type = peer_addr_type; + memcpy(&cmd.peer_id_addr, peer_addr->val, sizeof(cmd.peer_id_addr)); + + rc = ble_hs_hci_cmd_tx(opcode, &cmd, sizeof(cmd), &rsp, sizeof(rsp)); + + if (rc!=0) { + return rc; + } + + memcpy(out_addr, &rsp.rpa, sizeof(rsp.rpa)); + + return 0; +} #if MYNEWT_VAL(BLE_HCI_VS) #if MYNEWT_VAL(BLE_POWER_CONTROL) @@ -7883,7 +9380,7 @@ ble_gap_host_check_status(void) #endif struct ble_hs_conn *conn; ble_addr_t oldest_peer_id_addr[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; - int num_peers; + int num_peers = 0; /* Stop Advertising */ #if MYNEWT_VAL(BLE_EXT_ADV) diff --git a/src/nimble/nimble/host/src/ble_gap_priv.h b/src/nimble/nimble/host/src/ble_gap_priv.h index 31964aee..7a86bfb2 100644 --- a/src/nimble/nimble/host/src/ble_gap_priv.h +++ b/src/nimble/nimble/host/src/ble_gap_priv.h @@ -88,10 +88,15 @@ void ble_gap_rx_periodic_adv_rpt(const struct ble_hci_ev_le_subev_periodic_adv_r void ble_gap_rx_periodic_adv_sync_lost(const struct ble_hci_ev_le_subev_periodic_adv_sync_lost *ev); void ble_gap_rx_periodic_adv_sync_transfer(const struct ble_hci_ev_le_subev_periodic_adv_sync_transfer *ev); #endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) +void ble_gap_rx_biginfo_adv_rpt(const struct ble_hci_ev_le_subev_biginfo_adv_report *ev); +#endif void ble_gap_rx_scan_req_rcvd(const struct ble_hci_ev_le_subev_scan_req_rcvd *ev); #endif void ble_gap_rx_adv_report(struct ble_gap_disc_desc *desc); void ble_gap_rx_rd_rem_sup_feat_complete(const struct ble_hci_ev_le_subev_rd_rem_used_feat *ev); +void ble_gap_rx_rd_rem_ver_info_complete(const struct ble_hci_ev_rd_rem_ver_info_cmp *ev); +void ble_gap_event_connect_call(uint16_t conn_handle, int status); #if MYNEWT_VAL(BLE_CONN_SUBRATING) void ble_gap_rx_subrate_change(const struct ble_hci_ev_le_subev_subrate_change *ev); #endif @@ -99,6 +104,11 @@ void ble_gap_rx_subrate_change(const struct ble_hci_ev_le_subev_subrate_change * void ble_gap_rx_transmit_power_report(const struct ble_hci_ev_le_subev_transmit_power_report *ev); void ble_gap_rx_le_pathloss_threshold(const struct ble_hci_ev_le_subev_path_loss_threshold *ev); #endif +#if MYNEWT_VAL(BLE_AOA_AOD) +void ble_gap_rx_connless_iq_report(const struct ble_hci_ev_le_subev_connless_iq_rpt *ev); +void ble_gap_rx_conn_iq_report(const struct ble_hci_ev_le_subev_conn_iq_rpt *ev); +void ble_gap_rx_cte_req_failed(const struct ble_hci_ev_le_subev_cte_req_failed *ev); +#endif struct ble_gap_conn_complete { @@ -113,8 +123,17 @@ struct ble_gap_conn_complete uint8_t master_clk_acc; uint8_t local_rpa[BLE_DEV_ADDR_LEN]; uint8_t peer_rpa[BLE_DEV_ADDR_LEN]; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint8_t adv_handle; + uint16_t sync_handle; +#endif }; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +void ble_gap_rx_periodic_adv_subev_data_req(const struct ble_hci_ev_le_subev_periodic_adv_subev_data_req *ev); +void ble_gap_rx_periodic_adv_response(const struct ble_gap_periodic_adv_response resp); +void ble_gap_rx_conn_comp_failed(const struct ble_gap_conn_complete *evt); +#endif int ble_gap_rx_conn_complete(struct ble_gap_conn_complete *evt, uint8_t instance); void ble_gap_rx_disconn_complete(const struct ble_hci_ev_disconn_cmp *ev); void ble_gap_rx_update_complete(const struct ble_hci_ev_le_subev_conn_upd_complete *ev); @@ -135,10 +154,12 @@ void ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle, uint8_t prev_notify, uint8_t cur_notify, uint8_t prev_indicate, uint8_t cur_indicate); void ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu); -void ble_gap_identity_event(uint16_t conn_handle); +void ble_gap_identity_event(uint16_t conn_handle, const ble_addr_t *peer_id_addr); int ble_gap_repeat_pairing_event(const struct ble_gap_repeat_pairing *rp); +void ble_gap_pairing_complete_event(uint16_t conn_handle, int status); void ble_gap_vs_hci_event(const void *buf, uint8_t len); int ble_gap_authorize_event(uint16_t conn_handle, uint16_t attr_handle, int is_read); +void ble_gap_eatt_event(uint16_t conn_handle, uint8_t status, uint16_t cid); int ble_gap_master_in_progress(void); void ble_gap_preempt(void); @@ -147,7 +168,6 @@ void ble_gap_preempt_done(void); int ble_gap_terminate_with_conn(struct ble_hs_conn *conn, uint8_t hci_reason); void ble_gap_reset_state(int reason); void ble_gap_conn_broken(uint16_t conn_handle, int reason); -void ble_gap_reset_state(int reason); int32_t ble_gap_timer(void); int ble_gap_init(void); diff --git a/src/nimble/nimble/host/src/ble_gatt_priv.h b/src/nimble/nimble/host/src/ble_gatt_priv.h index f21f26b6..0488d8aa 100644 --- a/src/nimble/nimble/host/src/ble_gatt_priv.h +++ b/src/nimble/nimble/host/src/ble_gatt_priv.h @@ -68,6 +68,8 @@ STATS_SECT_START(ble_gattc_stats) STATS_SECT_ENTRY(write_reliable_fail) STATS_SECT_ENTRY(notify) STATS_SECT_ENTRY(notify_fail) + STATS_SECT_ENTRY(multi_notify) + STATS_SECT_ENTRY(multi_notify_fail) STATS_SECT_ENTRY(indicate) STATS_SECT_ENTRY(indicate_fail) STATS_SECT_ENTRY(proc_timeout) @@ -90,7 +92,6 @@ extern STATS_SECT_DECL(ble_gatts_stats) ble_gatts_stats; #define BLE_GATT_CHR_DECL_SZ_16 5 #define BLE_GATT_CHR_DECL_SZ_128 19 -#define BLE_GATT_CHR_CLI_SUP_FEAT_SZ 1 /** * For now only 3 bits in first octet are defined * @@ -108,6 +109,7 @@ struct ble_gatts_conn { int num_clt_cfgs; #if MYNEWT_VAL(BLE_GATT_CACHING) bool aware_state; + uint8_t half_aware:1; bool sent_err; #endif @@ -119,7 +121,7 @@ struct ble_gatts_conn { * future proof if more octets might be used. * (Vol. 3, Part G, 7.2) */ - uint8_t peer_cl_sup_feat[BLE_GATT_CHR_CLI_SUP_FEAT_SZ]; + uint8_t peer_cl_sup_feat[MYNEWT_VAL(BLE_GATT_CSFC_SIZE)]; }; /*** @client. */ @@ -127,32 +129,32 @@ struct ble_gatts_conn { int ble_gattc_locked_by_cur_task(void); void ble_gatts_indicate_fail_notconn(uint16_t conn_handle); -void ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status); -void ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu); -void ble_gattc_rx_read_type_adata(uint16_t conn_handle, +void ble_gattc_rx_err(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t status); +void ble_gattc_rx_mtu(uint16_t conn_handle, uint16_t cid, int status, uint16_t chan_mtu); +void ble_gattc_rx_read_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_type_adata *adata); -void ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status); -void ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, +void ble_gattc_rx_read_type_complete(uint16_t conn_handle, uint16_t cid, int status); +void ble_gattc_rx_read_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **rxom); -void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, +void ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **rxom); -void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, +void ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **rxom, bool variable); -void ble_gattc_rx_read_group_type_adata( - uint16_t conn_handle, struct ble_att_read_group_type_adata *adata); -void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int rc); -void ble_gattc_rx_find_type_value_hinfo( - uint16_t conn_handle, struct ble_att_find_type_value_hinfo *hinfo); -void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status); -void ble_gattc_rx_write_rsp(uint16_t conn_handle); -void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, +void ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, uint16_t cid, + struct ble_att_read_group_type_adata *adata); +void ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, uint16_t cid, int rc); +void ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, uint16_t cid, + struct ble_att_find_type_value_hinfo *hinfo); +void ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, uint16_t cid, int status); +void ble_gattc_rx_write_rsp(uint16_t conn_handle, uint16_t cid); +void ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, uint16_t cid, int status, uint16_t handle, uint16_t offset, struct os_mbuf **rxom); -void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status); -void ble_gatts_rx_indicate_rsp(uint16_t conn_handle); -void ble_gattc_rx_find_info_idata(uint16_t conn_handle, +void ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, uint16_t cid, int status); +void ble_gatts_rx_indicate_rsp(uint16_t conn_handle, uint16_t cid); +void ble_gattc_rx_find_info_idata(uint16_t conn_handle, uint16_t cid, struct ble_att_find_info_idata *idata); -void ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status); +void ble_gattc_rx_find_info_complete(uint16_t conn_handle, uint16_t cid, int status); void ble_gattc_connection_txable(uint16_t conn_handle); void ble_gattc_connection_broken(uint16_t conn_handle); int32_t ble_gattc_timer(void); @@ -222,11 +224,13 @@ int ble_gatts_register_svcs(const struct ble_gatt_svc_def *svcs, int ble_gatts_clt_cfg_access(uint16_t conn_handle, uint16_t attr_handle, uint8_t op, uint16_t offset, struct os_mbuf **om, void *arg); +void ble_gatts_set_clt_cfg_perm_flags(uint8_t flags); #if MYNEWT_VAL(BLE_GATT_CACHING) struct ble_gatts_aware_state { uint8_t peer_id_addr[6]; bool aware; + uint8_t half_aware:1; }; extern struct ble_gatts_aware_state ble_gatts_conn_aware_states[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; #endif diff --git a/src/nimble/nimble/host/src/ble_gattc.c b/src/nimble/nimble/host/src/ble_gattc.c index d29c2f2b..b808ce91 100644 --- a/src/nimble/nimble/host/src/ble_gattc.c +++ b/src/nimble/nimble/host/src/ble_gattc.c @@ -110,6 +110,7 @@ struct ble_gattc_proc { uint32_t exp_os_ticks; uint16_t conn_handle; + uint16_t cid; uint8_t op; uint8_t flags; @@ -224,6 +225,9 @@ struct ble_gattc_proc { }; }; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) +static struct ble_gattc_proc_list temp_proc_list; +#endif STAILQ_HEAD(ble_gattc_proc_list, ble_gattc_proc); /** @@ -243,6 +247,7 @@ static ble_gattc_err_fn ble_gattc_read_err; static ble_gattc_err_fn ble_gattc_read_uuid_err; static ble_gattc_err_fn ble_gattc_read_long_err; static ble_gattc_err_fn ble_gattc_read_mult_err; +static ble_gattc_err_fn ble_gattc_read_mult_var_err; static ble_gattc_err_fn ble_gattc_write_err; static ble_gattc_err_fn ble_gattc_write_long_err; static ble_gattc_err_fn ble_gattc_write_reliable_err; @@ -260,6 +265,7 @@ static ble_gattc_err_fn * const ble_gattc_err_dispatch[BLE_GATT_OP_CNT] = { [BLE_GATT_OP_READ_UUID] = ble_gattc_read_uuid_err, [BLE_GATT_OP_READ_LONG] = ble_gattc_read_long_err, [BLE_GATT_OP_READ_MULT] = ble_gattc_read_mult_err, + [BLE_GATT_OP_READ_MULT_VAR] = ble_gattc_read_mult_var_err, [BLE_GATT_OP_WRITE] = ble_gattc_write_err, [BLE_GATT_OP_WRITE_LONG] = ble_gattc_write_long_err, [BLE_GATT_OP_WRITE_RELIABLE] = ble_gattc_write_reliable_err, @@ -295,6 +301,7 @@ ble_gattc_resume_dispatch[BLE_GATT_OP_CNT] = { [BLE_GATT_OP_READ_UUID] = NULL, [BLE_GATT_OP_READ_LONG] = ble_gattc_read_long_resume, [BLE_GATT_OP_READ_MULT] = NULL, + [BLE_GATT_OP_READ_MULT_VAR] = NULL, [BLE_GATT_OP_WRITE] = NULL, [BLE_GATT_OP_WRITE_LONG] = ble_gattc_write_long_resume, [BLE_GATT_OP_WRITE_RELIABLE] = ble_gattc_write_reliable_resume, @@ -318,6 +325,7 @@ static ble_gattc_tmo_fn ble_gattc_read_tmo; static ble_gattc_tmo_fn ble_gattc_read_uuid_tmo; static ble_gattc_tmo_fn ble_gattc_read_long_tmo; static ble_gattc_tmo_fn ble_gattc_read_mult_tmo; +static ble_gattc_tmo_fn ble_gattc_read_mult_var_tmo; static ble_gattc_tmo_fn ble_gattc_write_tmo; static ble_gattc_tmo_fn ble_gattc_write_long_tmo; static ble_gattc_tmo_fn ble_gattc_write_reliable_tmo; @@ -336,6 +344,7 @@ ble_gattc_tmo_dispatch[BLE_GATT_OP_CNT] = { [BLE_GATT_OP_READ_UUID] = ble_gattc_read_uuid_tmo, [BLE_GATT_OP_READ_LONG] = ble_gattc_read_long_tmo, [BLE_GATT_OP_READ_MULT] = ble_gattc_read_mult_tmo, + [BLE_GATT_OP_READ_MULT_VAR] = ble_gattc_read_mult_var_tmo, [BLE_GATT_OP_WRITE] = ble_gattc_write_tmo, [BLE_GATT_OP_WRITE_LONG] = ble_gattc_write_long_tmo, [BLE_GATT_OP_WRITE_RELIABLE] = ble_gattc_write_reliable_tmo, @@ -472,6 +481,8 @@ STATS_NAME_START(ble_gattc_stats) STATS_NAME(ble_gattc_stats, write_reliable_fail) STATS_NAME(ble_gattc_stats, notify) STATS_NAME(ble_gattc_stats, notify_fail) + STATS_NAME(ble_gattc_stats, multi_notify) + STATS_NAME(ble_gattc_stats, multi_notify_fail) STATS_NAME(ble_gattc_stats, indicate) STATS_NAME(ble_gattc_stats, indicate_fail) STATS_NAME(ble_gattc_stats, proc_timeout) @@ -653,6 +664,15 @@ ble_gattc_log_notify(uint16_t att_handle) BLE_HS_LOG(INFO, "att_handle=%d\n", att_handle); } +static void +ble_gattc_log_multi_notify(struct ble_gatt_notif * tuples, uint16_t num) +{ + ble_gattc_log_proc_init("multi handle notify; "); + for (int i = 0; i < num; i++) { + BLE_HS_LOG(INFO, "att_handle=%d", tuples[i].handle); + } +} + static void ble_gattc_log_indicate(uint16_t att_handle) { @@ -707,6 +727,14 @@ ble_gattc_proc_alloc(void) return proc; } +static void +ble_gattc_proc_prepare(struct ble_gattc_proc *proc, uint16_t conn_handle, uint8_t op) +{ + proc->conn_handle = conn_handle; + proc->op = op; + proc->cid = ble_eatt_get_available_chan_cid(conn_handle, op); +} + /** * Frees the specified proc entry. No-op if passed a null pointer. */ @@ -738,6 +766,12 @@ ble_gattc_proc_free(struct ble_gattc_proc *proc) break; } +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + if (ble_hs_cfg.eatt && proc->cid != BLE_L2CAP_CID_ATT) { + ble_eatt_release_chan(proc->conn_handle, proc->op); + } +#endif + #if MYNEWT_VAL(BLE_HS_DEBUG) memset(proc, 0xff, sizeof *proc); #endif @@ -858,6 +892,7 @@ typedef int ble_gattc_match_fn(struct ble_gattc_proc *proc, void *arg); struct ble_gattc_criteria_conn_op { uint16_t conn_handle; + uint16_t psm; uint8_t op; }; @@ -889,6 +924,28 @@ ble_gattc_proc_matches_conn_op(struct ble_gattc_proc *proc, void *arg) return 1; } +static int +ble_gattc_proc_matches_conn_cid_op(struct ble_gattc_proc *proc, void *arg) +{ + const struct ble_gattc_criteria_conn_op *criteria; + + criteria = arg; + + if (criteria->conn_handle != proc->conn_handle) { + return 0; + } + + if (criteria->psm != proc->cid) { + return 0; + } + + if (criteria->op != proc->op && criteria->op != BLE_GATT_OP_NONE) { + return 0; + } + + return 1; +} + struct ble_gattc_criteria_exp { ble_npl_time_t now; int32_t next_exp_in; @@ -918,6 +975,7 @@ ble_gattc_proc_matches_expired(struct ble_gattc_proc *proc, void *arg) struct ble_gattc_criteria_conn_rx_entry { uint16_t conn_handle; + uint16_t cid; const void *rx_entries; int num_rx_entries; const void *matching_rx_entry; @@ -931,7 +989,8 @@ ble_gattc_proc_matches_conn_rx_entry(struct ble_gattc_proc *proc, void *arg) criteria = arg; if (criteria->conn_handle != BLE_HS_CONN_HANDLE_NONE && - criteria->conn_handle != proc->conn_handle) { + criteria->conn_handle != proc->conn_handle && + criteria->cid != proc->cid) { return 0; } @@ -950,6 +1009,10 @@ ble_gattc_extract(ble_gattc_match_fn *cb, void *arg, int max_procs, struct ble_gattc_proc *proc; struct ble_gattc_proc *prev; struct ble_gattc_proc *next; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + struct ble_gattc_proc *cur; + uint8_t flag = 0; +#endif int num_extracted; /* Only the parent task is allowed to remove entries from the list. */ @@ -961,6 +1024,28 @@ ble_gattc_extract(ble_gattc_match_fn *cb, void *arg, int max_procs, ble_hs_lock(); prev = NULL; + +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + proc = STAILQ_FIRST(&temp_proc_list); + while (proc != NULL) { + next = STAILQ_NEXT(proc, next); + STAILQ_FOREACH(cur, &ble_gattc_procs, next) { + if (proc == cur) { + flag = 1; + break; + } + } + if (!flag) { + /* Detected a preemption case */ + STAILQ_INSERT_TAIL(&ble_gattc_procs, proc, next); + } + flag = 0; + proc = next; + } + /* Clear the temp proc list */ + STAILQ_INIT(&temp_proc_list); +#endif + proc = STAILQ_FIRST(&ble_gattc_procs); while (proc != NULL) { next = STAILQ_NEXT(proc, next); @@ -1010,12 +1095,26 @@ ble_gattc_extract_by_conn_op(uint16_t conn_handle, uint8_t op, int max_procs, ble_gattc_extract(ble_gattc_proc_matches_conn_op, &criteria, max_procs, dst_list); } +static void +ble_gattc_extract_by_conn_cid_op(uint16_t conn_handle, uint16_t psm, uint8_t op, + int max_procs, + struct ble_gattc_proc_list *dst_list) +{ + struct ble_gattc_criteria_conn_op criteria; + + criteria.conn_handle = conn_handle; + criteria.op = op; + criteria.psm = psm; + + ble_gattc_extract(ble_gattc_proc_matches_conn_cid_op, &criteria, max_procs, dst_list); +} + static struct ble_gattc_proc * -ble_gattc_extract_first_by_conn_op(uint16_t conn_handle, uint8_t op) +ble_gattc_extract_first_by_conn_cid_op(uint16_t conn_handle, uint16_t cid, uint8_t op) { struct ble_gattc_proc_list dst_list; - ble_gattc_extract_by_conn_op(conn_handle, op, 1, &dst_list); + ble_gattc_extract_by_conn_cid_op(conn_handle, cid, op, 1, &dst_list); return STAILQ_FIRST(&dst_list); } @@ -1050,7 +1149,7 @@ ble_gattc_extract_expired(struct ble_gattc_proc_list *dst_list) } static struct ble_gattc_proc * -ble_gattc_extract_with_rx_entry(uint16_t conn_handle, +ble_gattc_extract_with_rx_entry(uint16_t conn_handle, uint16_t cid, const void *rx_entries, int num_rx_entries, const void **out_rx_entry) { @@ -1058,6 +1157,7 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle, struct ble_gattc_proc *proc; criteria.conn_handle = conn_handle; + criteria.cid = cid; criteria.rx_entries = rx_entries; criteria.num_rx_entries = num_rx_entries; criteria.matching_rx_entry = NULL; @@ -1075,6 +1175,7 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle, * list and returned. * * @param conn_handle The connection handle to match against. + * @param cid Source CID of L2CAP channel used * @param rx_entries The array of rx entries corresponding to the * op code of the incoming response. * @param out_rx_entry On success, the address of the matching rx @@ -1083,9 +1184,9 @@ ble_gattc_extract_with_rx_entry(uint16_t conn_handle, * @return The matching proc entry on success; * null on failure. */ -#define BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, rx_entries, out_rx_entry) \ +#define BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, rx_entries, out_rx_entry) \ ble_gattc_extract_with_rx_entry( \ - (conn_handle), (rx_entries), \ + (conn_handle), (cid), (rx_entries), \ sizeof (rx_entries) / sizeof (rx_entries)[0], \ (const void **)(out_rx_entry)) @@ -1303,7 +1404,7 @@ ble_gattc_mtu_tx(struct ble_gattc_proc *proc) int rc; ble_hs_lock(); - rc = ble_att_conn_chan_find(proc->conn_handle, &conn, &chan); + rc = ble_att_conn_chan_find(proc->conn_handle, proc->cid, &conn, &chan); if (rc == 0) { mtu = chan->my_mtu; } @@ -1332,6 +1433,7 @@ ble_gattc_exchange_mtu(uint16_t conn_handle, ble_gatt_mtu_fn *cb, void *cb_arg) proc->op = BLE_GATT_OP_MTU; proc->conn_handle = conn_handle; + proc->cid = BLE_L2CAP_CID_ATT; proc->mtu.cb = cb; proc->mtu.cb_arg = cb_arg; @@ -1408,7 +1510,7 @@ ble_gattc_disc_all_svcs_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_read_group_type(proc->conn_handle, + rc = ble_att_clt_tx_read_group_type(proc->conn_handle, proc->cid, proc->disc_all_svcs.prev_handle + 1, 0xffff, &uuid.u); if (rc != 0) { @@ -1561,12 +1663,17 @@ ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb, goto done; } - proc->op = BLE_GATT_OP_DISC_ALL_SVCS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_SVCS); + proc->disc_all_svcs.prev_handle = 0x0000; proc->disc_all_svcs.cb = cb; proc->disc_all_svcs.cb_arg = cb_arg; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_INSERT_TAIL(&temp_proc_list, proc, next); + ble_hs_unlock(); +#endif ble_gattc_log_proc_init("discover all services\n"); rc = ble_gattc_disc_all_svcs_tx(proc); @@ -1577,6 +1684,11 @@ ble_gattc_disc_all_svcs(uint16_t conn_handle, ble_gatt_disc_svc_fn *cb, done: if (rc != 0) { STATS_INC(ble_gattc_stats, disc_all_svcs_fail); +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_REMOVE(&temp_proc_list,proc,ble_gattc_proc, next); + ble_hs_unlock(); +#endif } ble_gattc_process_status(proc, rc); @@ -1641,7 +1753,7 @@ ble_gattc_disc_svc_uuid_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); ble_uuid_flat(&proc->disc_svc_uuid.service_uuid.u, val); - rc = ble_att_clt_tx_find_type_value(proc->conn_handle, + rc = ble_att_clt_tx_find_type_value(proc->conn_handle, proc->cid, proc->disc_svc_uuid.prev_handle + 1, 0xffff, BLE_ATT_UUID_PRIMARY_SERVICE, val, @@ -1780,8 +1892,8 @@ ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid, goto done; } - proc->op = BLE_GATT_OP_DISC_SVC_UUID; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_SVC_UUID); + ble_uuid_to_any(uuid, &proc->disc_svc_uuid.service_uuid); proc->disc_svc_uuid.prev_handle = 0x0000; proc->disc_svc_uuid.cb = cb; @@ -1862,7 +1974,7 @@ ble_gattc_find_inc_svcs_tx(struct ble_gattc_proc *proc) if (proc->find_inc_svcs.cur_start == 0) { /* Find the next included service. */ - rc = ble_att_clt_tx_read_type(proc->conn_handle, + rc = ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->find_inc_svcs.prev_handle + 1, proc->find_inc_svcs.end_handle, &uuid.u); if (rc != 0) { @@ -1870,7 +1982,7 @@ ble_gattc_find_inc_svcs_tx(struct ble_gattc_proc *proc) } } else { /* Read the UUID of the previously found service. */ - rc = ble_att_clt_tx_read(proc->conn_handle, + rc = ble_att_clt_tx_read(proc->conn_handle, proc->cid, proc->find_inc_svcs.cur_start); if (rc != 0) { return rc; @@ -2096,8 +2208,8 @@ ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_FIND_INC_SVCS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_FIND_INC_SVCS); + proc->find_inc_svcs.prev_handle = start_handle - 1; proc->find_inc_svcs.end_handle = end_handle; proc->find_inc_svcs.cb = cb; @@ -2176,7 +2288,7 @@ ble_gattc_disc_all_chrs_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_read_type(proc->conn_handle, + rc = ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->disc_all_chrs.prev_handle + 1, proc->disc_all_chrs.end_handle, &uuid.u); if (rc != 0) { @@ -2330,13 +2442,18 @@ ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_DISC_ALL_CHRS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_CHRS); + proc->disc_all_chrs.prev_handle = start_handle - 1; proc->disc_all_chrs.end_handle = end_handle; proc->disc_all_chrs.cb = cb; proc->disc_all_chrs.cb_arg = cb_arg; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_INSERT_TAIL(&temp_proc_list, proc, next); + ble_hs_unlock(); +#endif ble_gattc_log_disc_all_chrs(proc); rc = ble_gattc_disc_all_chrs_tx(proc); @@ -2347,6 +2464,11 @@ ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle, done: if (rc != 0) { STATS_INC(ble_gattc_stats, disc_all_chrs_fail); +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_REMOVE(&temp_proc_list,proc,ble_gattc_proc, next); + ble_hs_unlock(); +#endif } ble_gattc_process_status(proc, rc); @@ -2410,7 +2532,7 @@ ble_gattc_disc_chr_uuid_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_read_type(proc->conn_handle, + rc = ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->disc_chr_uuid.prev_handle + 1, proc->disc_chr_uuid.end_handle, &uuid.u); if (rc != 0) { @@ -2575,8 +2697,8 @@ ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_DISC_CHR_UUID; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_CHR_UUID); + ble_uuid_to_any(uuid, &proc->disc_chr_uuid.chr_uuid); proc->disc_chr_uuid.prev_handle = start_handle - 1; proc->disc_chr_uuid.end_handle = end_handle; @@ -2655,7 +2777,7 @@ ble_gattc_disc_all_dscs_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); - rc = ble_att_clt_tx_find_info(proc->conn_handle, + rc = ble_att_clt_tx_find_info(proc->conn_handle, proc->cid, proc->disc_all_dscs.prev_handle + 1, proc->disc_all_dscs.end_handle); if (rc != 0) { @@ -2791,14 +2913,19 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_DISC_ALL_DSCS; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_DISC_ALL_DSCS); + proc->disc_all_dscs.chr_val_handle = start_handle; proc->disc_all_dscs.prev_handle = start_handle; proc->disc_all_dscs.end_handle = end_handle; proc->disc_all_dscs.cb = cb; proc->disc_all_dscs.cb_arg = cb_arg; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_INSERT_TAIL(&temp_proc_list, proc, next); + ble_hs_unlock(); +#endif ble_gattc_log_disc_all_dscs(proc); rc = ble_gattc_disc_all_dscs_tx(proc); @@ -2809,6 +2936,11 @@ ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t start_handle, done: if (rc != 0) { STATS_INC(ble_gattc_stats, disc_all_dscs_fail); +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + ble_hs_lock(); + STAILQ_REMOVE(&temp_proc_list,proc,ble_gattc_proc, next); + ble_hs_unlock(); +#endif } ble_gattc_process_status(proc, rc); @@ -2907,7 +3039,7 @@ ble_gattc_read_tx(struct ble_gattc_proc *proc) { int rc; - rc = ble_att_clt_tx_read(proc->conn_handle, proc->read.handle); + rc = ble_att_clt_tx_read(proc->conn_handle, proc->cid, proc->read.handle); if (rc != 0) { return rc; } @@ -2934,8 +3066,8 @@ ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle, goto done; } - proc->op = BLE_GATT_OP_READ; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ); + proc->read.handle = attr_handle; proc->read.cb = cb; proc->read.cb_arg = cb_arg; @@ -3070,7 +3202,7 @@ ble_gattc_read_uuid_rx_complete(struct ble_gattc_proc *proc, int status) static int ble_gattc_read_uuid_tx(struct ble_gattc_proc *proc) { - return ble_att_clt_tx_read_type(proc->conn_handle, + return ble_att_clt_tx_read_type(proc->conn_handle, proc->cid, proc->read_uuid.start_handle, proc->read_uuid.end_handle, &proc->read_uuid.chr_uuid.u); @@ -3096,8 +3228,8 @@ ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle, goto done; } - proc->op = BLE_GATT_OP_READ_UUID; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_UUID); + ble_uuid_to_any(uuid, &proc->read_uuid.chr_uuid); proc->read_uuid.start_handle = start_handle; proc->read_uuid.end_handle = end_handle; @@ -3180,12 +3312,12 @@ ble_gattc_read_long_tx(struct ble_gattc_proc *proc) ble_gattc_dbg_assert_proc_not_inserted(proc); if (proc->read_long.offset == 0) { - rc = ble_att_clt_tx_read(proc->conn_handle, proc->read_long.handle); + rc = ble_att_clt_tx_read(proc->conn_handle, proc->cid, proc->read_long.handle); if (rc != 0) { return rc; } } else { - rc = ble_att_clt_tx_read_blob(proc->conn_handle, + rc = ble_att_clt_tx_read_blob(proc->conn_handle, proc->cid, proc->read_long.handle, proc->read_long.offset); if (rc != 0) { @@ -3256,7 +3388,7 @@ ble_gattc_read_long_rx_read_rsp(struct ble_gattc_proc *proc, int status, } /* Determine if this is the end of the attribute value. */ - mtu = ble_att_mtu(proc->conn_handle); + mtu = ble_att_mtu_by_cid(proc->conn_handle, proc->cid); if (mtu == 0) { /* No longer connected. */ return BLE_HS_EDONE; @@ -3297,8 +3429,8 @@ ble_gattc_read_long(uint16_t conn_handle, uint16_t handle, uint16_t offset, goto done; } - proc->op = BLE_GATT_OP_READ_LONG; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_READ_LONG); + proc->read_long.handle = handle; proc->read_long.offset = offset; proc->read_long.cb = cb; @@ -3337,7 +3469,7 @@ ble_gattc_read_mult_cb_var(struct ble_gattc_proc *proc, int status, return 0; } - memset(attr, 0, sizeof(*attr)); + memset(attr, 0, sizeof(attr)); for (i = 0; i < proc->read_mult.num_handles; i++) { attr[i].handle = proc->read_mult.handles[i]; @@ -3455,6 +3587,15 @@ ble_gattc_read_mult_tmo(struct ble_gattc_proc *proc) ble_gattc_read_mult_cb(proc, BLE_HS_ETIMEOUT, 0, 0); } +static void +ble_gattc_read_mult_var_tmo(struct ble_gattc_proc *proc) +{ + BLE_HS_DBG_ASSERT(!ble_hs_locked_by_cur_task()); + ble_gattc_dbg_assert_proc_not_inserted(proc); + + ble_gattc_read_mult_cb_var(proc, BLE_HS_ETIMEOUT, 0, 0); +} + /** * Handles an incoming ATT error response for the specified * read-multiple-characteristics proc. @@ -3467,12 +3608,24 @@ ble_gattc_read_mult_err(struct ble_gattc_proc *proc, int status, ble_gattc_read_mult_cb(proc, status, att_handle, NULL); } +/** + * Handles an incoming ATT error response for the specified + * read-multiple-variable-lengthcharacteristics proc. + */ +static void +ble_gattc_read_mult_var_err(struct ble_gattc_proc *proc, int status, + uint16_t att_handle) +{ + ble_gattc_dbg_assert_proc_not_inserted(proc); + ble_gattc_read_mult_cb_var(proc, status, att_handle, NULL); +} + static int ble_gattc_read_mult_tx(struct ble_gattc_proc *proc) { int rc; - rc = ble_att_clt_tx_read_mult(proc->conn_handle, proc->read_mult.handles, + rc = ble_att_clt_tx_read_mult(proc->conn_handle, proc->cid, proc->read_mult.handles, proc->read_mult.num_handles, proc->read_mult.variable); if (rc != 0) { return rc; @@ -3510,12 +3663,9 @@ ble_gattc_read_mult_internal(uint16_t conn_handle, const uint16_t *handles, goto done; } - if (variable) { - proc->op = BLE_GATT_OP_READ_MULT_VAR; - } else { - proc->op = BLE_GATT_OP_READ_MULT; - } - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, + variable ? BLE_GATT_OP_READ_MULT_VAR : BLE_GATT_OP_READ_MULT); + memcpy(proc->read_mult.handles, handles, num_handles * sizeof *handles); proc->read_mult.num_handles = num_handles; proc->read_mult.variable = variable; @@ -3573,15 +3723,18 @@ ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle, #endif int rc; + uint16_t cid; STATS_INC(ble_gattc_stats, write_no_rsp); ble_gattc_log_write(attr_handle, OS_MBUF_PKTLEN(txom), 0); - rc = ble_att_clt_tx_write_cmd(conn_handle, attr_handle, txom); + cid = ble_eatt_get_available_chan_cid(conn_handle, BLE_GATT_OP_DUMMY); + rc = ble_att_clt_tx_write_cmd(conn_handle, cid, attr_handle, txom); if (rc != 0) { STATS_INC(ble_gattc_stats, write); } + ble_eatt_release_chan(conn_handle, BLE_GATT_OP_DUMMY); return rc; } @@ -3653,7 +3806,7 @@ ble_gattc_signed_write(uint16_t conn_handle, uint16_t attr_handle, /* Converting the csrk to little endian */ swap_buf(csrk, value_sec.csrk, 16); - rc = ble_att_clt_tx_signed_write_cmd(conn_handle, attr_handle, + rc = ble_att_clt_tx_signed_write_cmd(conn_handle, BLE_L2CAP_CID_ATT, attr_handle, csrk, value_sec.sign_counter, txom); if (rc != 0) { goto err; @@ -3749,15 +3902,15 @@ ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle, goto done; } - proc->op = BLE_GATT_OP_WRITE; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE); + proc->write.att_handle = attr_handle; proc->write.cb = cb; proc->write.cb_arg = cb_arg; ble_gattc_log_write(attr_handle, OS_MBUF_PKTLEN(txom), 1); - rc = ble_att_clt_tx_write_req(conn_handle, attr_handle, txom); + rc = ble_att_clt_tx_write_req(conn_handle, proc->cid, attr_handle, txom); txom = NULL; if (rc != 0) { goto done; @@ -3862,7 +4015,7 @@ ble_gattc_write_long_tx(struct ble_gattc_proc *proc) om = NULL; - max_sz = ble_att_mtu(proc->conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; + max_sz = ble_att_mtu_by_cid(proc->conn_handle, proc->cid) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; if (max_sz <= 0) { /* Not connected. */ rc = BLE_HS_ENOTCONN; @@ -3874,7 +4027,7 @@ ble_gattc_write_long_tx(struct ble_gattc_proc *proc) proc->write_long.attr.offset); if (write_len <= 0) { - rc = ble_att_clt_tx_exec_write(proc->conn_handle, + rc = ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_EXECUTE); goto done; } @@ -3894,7 +4047,7 @@ ble_gattc_write_long_tx(struct ble_gattc_proc *proc) goto done; } - rc = ble_att_clt_tx_prep_write(proc->conn_handle, + rc = ble_att_clt_tx_prep_write(proc->conn_handle, proc->cid, proc->write_long.attr.handle, proc->write_long.attr.offset, om); om = NULL; @@ -3938,9 +4091,9 @@ ble_gattc_write_long_err(struct ble_gattc_proc *proc, int status, */ if (proc->write_long.attr.offset > 0 && proc->write_long.attr.offset < - OS_MBUF_PKTLEN(proc->write_long.attr.om)) { + OS_MBUF_PKTLEN(proc->write_long.attr.om)) { - ble_att_clt_tx_exec_write(proc->conn_handle, + ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_CANCEL); } @@ -4006,7 +4159,8 @@ ble_gattc_write_long_rx_prep(struct ble_gattc_proc *proc, rc = BLE_HS_EBADDATA; /* if data doesn't match up send cancel write */ - ble_att_clt_tx_exec_write(proc->conn_handle, BLE_ATT_EXEC_WRITE_F_CANCEL); + ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, + BLE_ATT_EXEC_WRITE_F_CANCEL); goto err; } else { /* Send follow-up request. */ @@ -4067,8 +4221,8 @@ ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, goto done; } - proc->op = BLE_GATT_OP_WRITE_LONG; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE_LONG); + proc->write_long.attr.handle = attr_handle; proc->write_long.attr.offset = offset; proc->write_long.attr.om = txom; @@ -4078,6 +4232,11 @@ ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle, /* The mbuf is consumed by the procedure. */ txom = NULL; + if (proc->write_long.attr.offset > OS_MBUF_PKTLEN(proc->write_long.attr.om)) { + rc = BLE_ATT_ERR_INVALID_OFFSET; + goto done; + } + ble_gattc_log_write_long(proc); rc = ble_gattc_write_long_tx(proc); @@ -4168,14 +4327,14 @@ ble_gattc_write_reliable_tx(struct ble_gattc_proc *proc) attr_idx = proc->write_reliable.cur_attr; if (attr_idx >= proc->write_reliable.num_attrs) { - rc = ble_att_clt_tx_exec_write(proc->conn_handle, + rc = ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_EXECUTE); goto done; } attr = proc->write_reliable.attrs + attr_idx; - max_sz = ble_att_mtu(proc->conn_handle) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; + max_sz = ble_att_mtu_by_cid(proc->conn_handle, proc->cid) - BLE_ATT_PREP_WRITE_CMD_BASE_SZ; if (max_sz <= 0) { /* Not connected. */ rc = BLE_HS_ENOTCONN; @@ -4198,8 +4357,8 @@ ble_gattc_write_reliable_tx(struct ble_gattc_proc *proc) goto done; } - rc = ble_att_clt_tx_prep_write(proc->conn_handle, attr->handle, - attr->offset, om); + rc = ble_att_clt_tx_prep_write(proc->conn_handle, proc->cid, + attr->handle, attr->offset, om); om = NULL; if (rc != 0) { goto done; @@ -4242,7 +4401,7 @@ ble_gattc_write_reliable_err(struct ble_gattc_proc *proc, int status, */ if (proc->write_reliable.cur_attr < proc->write_reliable.num_attrs) { - ble_att_clt_tx_exec_write(proc->conn_handle, + ble_att_clt_tx_exec_write(proc->conn_handle, proc->cid, BLE_ATT_EXEC_WRITE_F_CANCEL); } } @@ -4355,8 +4514,8 @@ ble_gattc_write_reliable(uint16_t conn_handle, goto done; } - proc->op = BLE_GATT_OP_WRITE_RELIABLE; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_WRITE_RELIABLE); + proc->write_reliable.num_attrs = num_attrs; proc->write_reliable.cur_attr = 0; proc->write_reliable.cb = cb; @@ -4473,6 +4632,118 @@ ble_gatts_notify_custom(uint16_t conn_handle, uint16_t chr_val_handle, return rc; } +int +ble_gatts_notify_multiple_custom(uint16_t conn_handle, + size_t chr_count, + struct ble_gatt_notif *tuples) +{ +#if !MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE) + return BLE_HS_ENOTSUP; +#endif + + int rc = 0; + int i = 0; + uint16_t cur_chr_cnt = 0; + /* mtu = MTU - 1 octet (OP code) */ + uint16_t mtu = ble_att_mtu(conn_handle) - 1; + struct os_mbuf *txom; + struct ble_hs_conn *conn; + + txom = ble_hs_mbuf_att_pkt(); + if (txom == NULL) { + return BLE_HS_ENOMEM; + } + + conn = ble_hs_conn_find(conn_handle); + if (conn == NULL) { + return ENOTCONN; + } + + STATS_INC(ble_gattc_stats, multi_notify); + ble_gattc_log_multi_notify(tuples, chr_count); + + /* Read missing values */ + for (i = 0; i < chr_count; i++) { + if (tuples->handle == 0) { + rc = BLE_HS_EINVAL; + goto done; + } + if (tuples[i].value == NULL) { + /* No custom attribute data; read the value from the specified + * attribute + */ + rc = ble_att_svr_read_local(tuples[i].handle, &tuples[i].value); + if (rc != 0) { + BLE_HS_LOG(ERROR, "Attribute read failed (err=0x%02x)", rc); + goto done; + } + } + } + + /* If peer does not support fall back to multiple single value + * Notifications */ + if ((conn->bhc_gatt_svr.peer_cl_sup_feat[0] & 0x04) == 0) { + for (i = 0; i < chr_count; i++) { + rc = ble_att_clt_tx_notify(conn_handle, tuples[i].handle, tuples[i].value); + if (rc != 0) { + goto done; + } + } + goto done; + } + + for (i = 0; i < chr_count; i++) { + if (OS_MBUF_PKTLEN(txom) + OS_MBUF_PKTLEN(tuples[i].value) > mtu && cur_chr_cnt < 2) { + rc = ble_att_clt_tx_notify(conn_handle, tuples[i].handle, + tuples[i].value); + if (rc != 0) { + goto done; + } + continue; + } else if (OS_MBUF_PKTLEN(txom) + OS_MBUF_PKTLEN(tuples[i].value) > mtu) { + rc = ble_att_clt_tx_notify_mult(conn_handle, txom); + if (rc != 0) { + goto done; + } + cur_chr_cnt = 0; + /* buffer was consumed, allocate new one */ + txom = ble_hs_mbuf_att_pkt(); + if (txom == NULL) { + return BLE_HS_ENOMEM; + } + } + + /* Handle */ + os_mbuf_append(txom, &tuples[i].handle, sizeof(uint16_t)); + + /* Length */ + os_mbuf_append(txom, &OS_MBUF_PKTLEN(tuples[i].value), + sizeof(uint16_t)); + + /* Value */ + os_mbuf_concat(txom, tuples[i].value); + cur_chr_cnt++; + } + + if (cur_chr_cnt == 1) { + rc = ble_att_clt_tx_notify(conn_handle, tuples[chr_count].handle, + tuples[chr_count].value); + } else { + rc = ble_att_clt_tx_notify_mult(conn_handle, txom); + } + +done: + if (rc != 0) { + STATS_INC(ble_gattc_stats, multi_notify_fail); + } + + /* Tell the application that multiple notification transmissions were attempted. */ + for (i = 0; i < chr_count; i++) { + ble_gap_notify_tx_event(rc, conn_handle, tuples[i].handle, 0); + } + return rc; +} + /** * Deprecated. Should not be used. Use ble_gatts_notify_custom instead. */ @@ -4608,8 +4879,8 @@ ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, goto done; } - proc->op = BLE_GATT_OP_INDICATE; - proc->conn_handle = conn_handle; + ble_gattc_proc_prepare(proc, conn_handle, BLE_GATT_OP_INDICATE); + proc->indicate.chr_val_handle = chr_val_handle; ble_gattc_log_indicate(chr_val_handle); @@ -4648,7 +4919,7 @@ ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle, } } - rc = ble_att_clt_tx_indicate(conn_handle, chr_val_handle, txom); + rc = ble_att_clt_tx_indicate(conn_handle, proc->cid, chr_val_handle, txom); txom = NULL; if (rc != 0) { goto done; @@ -4709,12 +4980,12 @@ ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle) * procedure. */ void -ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status) +ble_gattc_rx_err(uint16_t conn_handle, uint16_t cid, uint16_t handle, uint16_t status) { struct ble_gattc_proc *proc; ble_gattc_err_fn *err_cb; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, BLE_GATT_OP_NONE); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_NONE); if (proc != NULL) { err_cb = ble_gattc_err_dispatch_get(proc->op); if (err_cb != NULL) { @@ -4729,11 +5000,13 @@ ble_gattc_rx_err(uint16_t conn_handle, uint16_t handle, uint16_t status) * GATT procedure. */ void -ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu) +ble_gattc_rx_mtu(uint16_t conn_handle, uint16_t cid, int status, uint16_t chan_mtu) { struct ble_gattc_proc *proc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, BLE_GATT_OP_MTU); + assert(cid == BLE_L2CAP_CID_ATT); + + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, BLE_L2CAP_CID_ATT, BLE_GATT_OP_MTU); if (proc != NULL) { ble_gattc_mtu_cb(proc, status, 0, chan_mtu); ble_gattc_process_status(proc, BLE_HS_EDONE); @@ -4745,7 +5018,7 @@ ble_gattc_rx_mtu(uint16_t conn_handle, int status, uint16_t chan_mtu) * find-information-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_info_idata(uint16_t conn_handle, +ble_gattc_rx_find_info_idata(uint16_t conn_handle, uint16_t cid, struct ble_att_find_info_idata *idata) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO @@ -4755,7 +5028,7 @@ ble_gattc_rx_find_info_idata(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_DISC_ALL_DSCS); if (proc != NULL) { rc = ble_gattc_disc_all_dscs_rx_idata(proc, idata); @@ -4768,7 +5041,7 @@ ble_gattc_rx_find_info_idata(uint16_t conn_handle, * find-information-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status) +ble_gattc_rx_find_info_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_FIND_INFO return; @@ -4777,8 +5050,8 @@ ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, - BLE_GATT_OP_DISC_ALL_DSCS); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, + BLE_GATT_OP_DISC_ALL_DSCS); if (proc != NULL) { rc = ble_gattc_disc_all_dscs_rx_complete(proc, status); ble_gattc_process_status(proc, rc); @@ -4790,7 +5063,7 @@ ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status) * find-by-type-value-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, +ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, uint16_t cid, struct ble_att_find_type_value_hinfo *hinfo) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE @@ -4800,7 +5073,7 @@ ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_DISC_SVC_UUID); if (proc != NULL) { rc = ble_gattc_disc_svc_uuid_rx_hinfo(proc, hinfo); @@ -4813,7 +5086,7 @@ ble_gattc_rx_find_type_value_hinfo(uint16_t conn_handle, * find-by-type-value-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status) +ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_FIND_TYPE return; @@ -4822,8 +5095,8 @@ ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, - BLE_GATT_OP_DISC_SVC_UUID); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, + BLE_GATT_OP_DISC_SVC_UUID); if (proc != NULL) { rc = ble_gattc_disc_svc_uuid_rx_complete(proc, status); ble_gattc_process_status(proc, rc); @@ -4835,7 +5108,7 @@ ble_gattc_rx_find_type_value_complete(uint16_t conn_handle, int status) * to the appropriate active GATT procedure. */ void -ble_gattc_rx_read_type_adata(uint16_t conn_handle, +ble_gattc_rx_read_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_type_adata *adata) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE @@ -4846,7 +5119,7 @@ ble_gattc_rx_read_type_adata(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_read_type_elem_entries, &rx_entry); if (proc != NULL) { @@ -4860,7 +5133,7 @@ ble_gattc_rx_read_type_adata(uint16_t conn_handle, * the appropriate active GATT procedure. */ void -ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status) +ble_gattc_rx_read_type_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_READ_TYPE return; @@ -4871,7 +5144,7 @@ ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status) int rc; proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY( - conn_handle, ble_gattc_rx_read_type_complete_entries, + conn_handle, cid, ble_gattc_rx_read_type_complete_entries, &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, status); @@ -4884,7 +5157,7 @@ ble_gattc_rx_read_type_complete(uint16_t conn_handle, int status) * read-by-group-type-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, +ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, uint16_t cid, struct ble_att_read_group_type_adata *adata) { #if !NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE @@ -4894,7 +5167,7 @@ ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_DISC_ALL_SVCS); if (proc != NULL) { rc = ble_gattc_disc_all_svcs_rx_adata(proc, adata); @@ -4907,7 +5180,7 @@ ble_gattc_rx_read_group_type_adata(uint16_t conn_handle, * read-by-group-type-response to the appropriate active GATT procedure. */ void -ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int status) +ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_READ_GROUP_TYPE return; @@ -4916,8 +5189,8 @@ ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, - BLE_GATT_OP_DISC_ALL_SVCS); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, + BLE_GATT_OP_DISC_ALL_SVCS); if (proc != NULL) { rc = ble_gattc_disc_all_svcs_rx_complete(proc, status); ble_gattc_process_status(proc, rc); @@ -4929,7 +5202,7 @@ ble_gattc_rx_read_group_type_complete(uint16_t conn_handle, int status) * procedure. */ void -ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, struct os_mbuf **om) +ble_gattc_rx_read_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **om) { #if !NIMBLE_BLE_ATT_CLT_READ return; @@ -4939,7 +5212,7 @@ ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, struct os_mbuf **om) struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_read_rsp_entries, &rx_entry); if (proc != NULL) { @@ -4953,7 +5226,7 @@ ble_gattc_rx_read_rsp(uint16_t conn_handle, int status, struct os_mbuf **om) * procedure. */ void -ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, +ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **om) { #if !NIMBLE_BLE_ATT_CLT_READ_BLOB @@ -4963,7 +5236,7 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, struct ble_gattc_proc *proc; int rc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_READ_LONG); if (proc != NULL) { rc = ble_gattc_read_long_rx_read_rsp(proc, status, om); @@ -4976,7 +5249,7 @@ ble_gattc_rx_read_blob_rsp(uint16_t conn_handle, int status, * GATT procedure. */ void -ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, +ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, uint16_t cid, int status, struct os_mbuf **om, bool variable) { #if !NIMBLE_BLE_ATT_CLT_READ_MULT @@ -4988,7 +5261,7 @@ ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, op = variable ? BLE_GATT_OP_READ_MULT_VAR : BLE_GATT_OP_READ_MULT; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, op); + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, op); if (proc != NULL) { ble_gattc_read_mult_cb(proc, status, 0, om); ble_gattc_process_status(proc, BLE_HS_EDONE); @@ -5000,7 +5273,7 @@ ble_gattc_rx_read_mult_rsp(uint16_t conn_handle, int status, * procedure. */ void -ble_gattc_rx_write_rsp(uint16_t conn_handle) +ble_gattc_rx_write_rsp(uint16_t conn_handle, uint16_t cid) { #if !NIMBLE_BLE_ATT_CLT_WRITE return; @@ -5008,7 +5281,7 @@ ble_gattc_rx_write_rsp(uint16_t conn_handle) struct ble_gattc_proc *proc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_WRITE); if (proc != NULL) { ble_gattc_write_cb(proc, 0, 0); @@ -5021,7 +5294,7 @@ ble_gattc_rx_write_rsp(uint16_t conn_handle) * GATT procedure. */ void -ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, +ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, uint16_t cid, int status, uint16_t handle, uint16_t offset, struct os_mbuf **om) { @@ -5033,7 +5306,7 @@ ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_prep_entries, &rx_entry); if (proc != NULL) { @@ -5047,7 +5320,7 @@ ble_gattc_rx_prep_write_rsp(uint16_t conn_handle, int status, * GATT procedure. */ void -ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status) +ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, uint16_t cid, int status) { #if !NIMBLE_BLE_ATT_CLT_EXEC_WRITE return; @@ -5057,7 +5330,7 @@ ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status) struct ble_gattc_proc *proc; int rc; - proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, + proc = BLE_GATTC_RX_EXTRACT_RX_ENTRY(conn_handle, cid, ble_gattc_rx_exec_entries, &rx_entry); if (proc != NULL) { rc = rx_entry->cb(proc, status); @@ -5070,7 +5343,7 @@ ble_gattc_rx_exec_write_rsp(uint16_t conn_handle, int status) * active GATT procedure. */ void -ble_gatts_rx_indicate_rsp(uint16_t conn_handle) +ble_gatts_rx_indicate_rsp(uint16_t conn_handle, uint16_t cid) { #if !NIMBLE_BLE_ATT_CLT_INDICATE return; @@ -5078,7 +5351,7 @@ ble_gatts_rx_indicate_rsp(uint16_t conn_handle) struct ble_gattc_proc *proc; - proc = ble_gattc_extract_first_by_conn_op(conn_handle, + proc = ble_gattc_extract_first_by_conn_cid_op(conn_handle, cid, BLE_GATT_OP_INDICATE); if (proc != NULL) { ble_gatts_indicate_rx_rsp(proc); @@ -5101,7 +5374,19 @@ ble_gatts_rx_indicate_rsp(uint16_t conn_handle) void ble_gattc_connection_broken(uint16_t conn_handle) { + struct ble_hs_conn *conn; + struct os_mbuf_pkthdr *omp; + ble_gattc_fail_procs(conn_handle, BLE_GATT_OP_NONE, BLE_HS_ENOTCONN); + + ble_hs_lock(); + conn = ble_hs_conn_find(conn_handle); + ble_hs_unlock(); + + while ((omp = STAILQ_FIRST(&conn->att_tx_q)) != NULL) { + STAILQ_REMOVE_HEAD(&conn->att_tx_q, omp_next); + os_mbuf_free_chain(OS_MBUF_PKTHDR_TO_MBUF(omp)); + } } /** @@ -5118,6 +5403,9 @@ ble_gattc_init(void) { int rc; +#if MYNEWT_VAL(BLE_GATTC_PROC_PREEMPTION_PROTECT) + STAILQ_INIT(&temp_proc_list); +#endif STAILQ_INIT(&ble_gattc_procs); if (MYNEWT_VAL(BLE_GATT_MAX_PROCS) > 0) { diff --git a/src/nimble/nimble/host/src/ble_gattc_cache.c b/src/nimble/nimble/host/src/ble_gattc_cache.c index 6b90902d..d5d5785d 100644 --- a/src/nimble/nimble/host/src/ble_gattc_cache.c +++ b/src/nimble/nimble/host/src/ble_gattc_cache.c @@ -19,14 +19,16 @@ #include #include -#include "../include/host/ble_hs.h" +#include "nimble/nimble/host/include/host/ble_hs.h" #include "ble_hs_conn_priv.h" #include "ble_hs_priv.h" #include "ble_gattc_cache_priv.h" #include "nimble/porting/nimble/include/nimble/storage_port.h" #include "nimble/nimble/host/include/host/ble_gatt.h" +#ifdef ESP_PLATFORM #include "nimble/esp_port/port/include/esp_nimble_mem.h" +#endif #define GATT_CACHE_PREFIX "gatt_" #define INVALID_ADDR_NUM 0xff @@ -388,6 +390,7 @@ ble_gattc_cache_addr_save(uint8_t *out_index, ble_addr_t addr, uint8_t * hash_ke address list. */ if(num > MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) { + nimble_platform_mem_free(p_buf); return BLE_HS_ENOMEM; } BLE_HS_LOG(DEBUG, "BD addr not present"); @@ -396,6 +399,7 @@ ble_gattc_cache_addr_save(uint8_t *out_index, ble_addr_t addr, uint8_t * hash_ke } else { BLE_HS_LOG(DEBUG, "Hash key not present, saving new data"); if(num > MYNEWT_VAL(BLE_GATT_CACHING_MAX_CONNS)) { + nimble_platform_mem_free(p_buf); return BLE_HS_ENOMEM; } insert_ind = num - 1; @@ -485,6 +489,7 @@ ble_gattc_cache_save(struct ble_gattc_cache_conn *peer, size_t num_attr) if(rc != 0) { /* cannot save address, return */ BLE_HS_LOG(ERROR, "Failed to save cache %d", rc); + nimble_platform_mem_free(nv_attr); return; } @@ -530,6 +535,7 @@ static int ble_gattc_add_svc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_attr) { struct ble_gatt_svc *gatt_svc; + int rc; gatt_svc = (struct ble_gatt_svc *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_svc)); if (gatt_svc == NULL) { @@ -540,13 +546,16 @@ ble_gattc_add_svc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_at gatt_svc->end_handle = nv_attr.e_handle; ble_uuid_copy(&gatt_svc->uuid, &nv_attr.uuid.u); - return ble_gattc_cache_conn_svc_add(peer_addr, gatt_svc); + rc = ble_gattc_cache_conn_svc_add(peer_addr, gatt_svc); + nimble_platform_mem_free(gatt_svc); + return rc; } static int ble_gattc_add_inc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_attr) { struct ble_gatt_svc *gatt_svc; + int rc; gatt_svc = (struct ble_gatt_svc *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_svc)); if (gatt_svc == NULL) { @@ -556,13 +565,16 @@ ble_gattc_add_inc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_at gatt_svc->start_handle = nv_attr.s_handle; gatt_svc->end_handle = nv_attr.e_handle; ble_uuid_copy(&gatt_svc->uuid, &nv_attr.uuid.u); - return ble_gattc_cache_conn_inc_add(peer_addr, gatt_svc); + rc = ble_gattc_cache_conn_inc_add(peer_addr, gatt_svc); + nimble_platform_mem_free(gatt_svc); + return rc; } static int ble_gattc_add_chr_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_attr) { struct ble_gatt_chr *gatt_chr; + int rc; gatt_chr = (struct ble_gatt_chr *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_chr)); if (gatt_chr == NULL) { return BLE_HS_ENOMEM; @@ -573,13 +585,16 @@ ble_gattc_add_chr_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_at ble_uuid_copy(&gatt_chr->uuid, &nv_attr.uuid.u); gatt_chr->properties = nv_attr.properties; - return ble_gattc_cache_conn_chr_add(peer_addr, 0, gatt_chr); + rc = ble_gattc_cache_conn_chr_add(peer_addr, 0, gatt_chr); + nimble_platform_mem_free(gatt_chr); + return rc; } static int ble_gattc_add_dsc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_attr) { struct ble_gatt_dsc *gatt_dsc; + int rc; gatt_dsc = (struct ble_gatt_dsc *)nimble_platform_mem_malloc(sizeof(struct ble_gatt_dsc)); if (gatt_dsc == NULL) { return BLE_HS_ENOMEM; @@ -588,7 +603,9 @@ ble_gattc_add_dsc_from_cache(ble_addr_t peer_addr, struct ble_gatt_nv_attr nv_at gatt_dsc->handle = nv_attr.s_handle; ble_uuid_copy(&gatt_dsc->uuid, &nv_attr.uuid.u); - return ble_gattc_cache_conn_dsc_add(peer_addr, 0, gatt_dsc); + rc = ble_gattc_cache_conn_dsc_add(peer_addr, 0, gatt_dsc); + nimble_platform_mem_free(gatt_dsc); + return rc; } int diff --git a/src/nimble/nimble/host/src/ble_gattc_cache_conn.c b/src/nimble/nimble/host/src/ble_gattc_cache_conn.c index 9deff526..e0efebe3 100644 --- a/src/nimble/nimble/host/src/ble_gattc_cache_conn.c +++ b/src/nimble/nimble/host/src/ble_gattc_cache_conn.c @@ -20,7 +20,7 @@ #include #include #include -#include "../include/host/ble_hs.h" +#include "nimble/nimble/host/include/host/ble_hs.h" #include "ble_hs_priv.h" #include "ble_gattc_cache_priv.h" @@ -718,6 +718,7 @@ ble_gattc_cache_conn_bonding_established(uint16_t conn_handle) BLE_HS_DBG_ASSERT(conn != NULL); ble_hs_conn_addrs(conn, &addrs); peer->ble_gattc_cache_conn_addr = conn->bhc_peer_addr; + peer->ble_gattc_cache_conn_addr.type = ble_hs_misc_peer_addr_type_to_id(conn->bhc_peer_addr.type); @@ -811,6 +812,7 @@ ble_gattc_cache_conn_disc_complete(struct ble_gattc_cache_conn *peer, int rc) BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16)); if (bonded || chr != NULL) { /* persist the cache */ + ble_gattc_cacheReset(&hs_conn->bhc_peer_addr); ble_gattc_cache_conn_cache_peer(peer); /* TODO */ } } else { @@ -860,9 +862,15 @@ ble_gattc_cache_conn_disc_complete(struct ble_gattc_cache_conn *peer, int rc) } } -static void -ble_gattc_cache_conn_undisc_all(struct ble_gattc_cache_conn *peer) +void +ble_gattc_cache_conn_undisc_all(ble_addr_t peer_addr) { + struct ble_gattc_cache_conn * peer = NULL; + + peer = ble_gattc_cache_conn_find_by_addr(peer_addr); + if (peer == NULL) { + return; + } ble_gattc_cacheReset(&peer->ble_gattc_cache_conn_addr); struct ble_gattc_cache_conn_svc *svc; @@ -946,7 +954,7 @@ ble_gattc_cache_conn_disc(struct ble_gattc_cache_conn *peer) { int rc; - ble_gattc_cache_conn_undisc_all(peer); + ble_gattc_cache_conn_undisc_all(peer->ble_gattc_cache_conn_addr); peer->disc_prev_chr_val = 1; @@ -964,6 +972,11 @@ ble_gattc_cache_conn_on_read(uint16_t conn_handle, { uint16_t res; + if (error->status == BLE_HS_EDONE) { + /* Ignore Read by UUID follow-up callback */ + return 0; + } + if (error->status != 0) { res = error->status; ble_gattc_cache_conn_disc_complete((struct ble_gattc_cache_conn *)arg, res); @@ -975,9 +988,10 @@ ble_gattc_cache_conn_on_read(uint16_t conn_handle, BLE_HS_LOG(INFO, "Hash value up to date, skipping Discovery"); ble_gattc_cache_conn_disc_complete((struct ble_gattc_cache_conn *)arg, res); return 0; + } else { + res = ble_gattc_cache_conn_disc((struct ble_gattc_cache_conn *)arg); + return res; } - return 0; - } int @@ -1226,6 +1240,10 @@ ble_gattc_cache_conn_update(uint16_t conn_handle, uint16_t start_handle, uint16_ } peer->cache_state = CACHE_INVALID; + if (MYNEWT_VAL(BLE_GATT_CACHING_DISABLE_AUTO)) { + /* Do not automatically re-discover and correct cache */ + return; + } rc = ble_gattc_cache_conn_disc(peer); if (rc != 0) { peer->cache_state = CACHE_INVALID; @@ -1385,7 +1403,6 @@ ble_gattc_cache_error(int status, uint16_t att_handle) static int ble_gattc_cache_conn_verify(struct ble_gattc_cache_conn *conn) { struct ble_hs_conn *gap_conn; - const struct ble_gattc_cache_conn_chr *chr; int rc; if (conn->cache_state == CACHE_VERIFIED) { @@ -1404,16 +1421,10 @@ static int ble_gattc_cache_conn_verify(struct ble_gattc_cache_conn *conn) conn->cache_state = CACHE_VERIFIED; return 0; } - chr = ble_gattc_cache_conn_chr_find_uuid(conn, - BLE_UUID16_DECLARE(BLE_GATT_SVC_UUID16), - BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16)); - if (chr == NULL) { - /* no way to verify */ - conn->cache_state = CACHE_INVALID; - return 0; - } - rc = ble_gattc_read(conn->conn_handle, chr->chr.val_handle, - ble_gattc_cache_conn_on_read, conn); + + rc = ble_gattc_read_by_uuid(conn->conn_handle, 0x0001, 0xFFFF, + BLE_UUID16_DECLARE(BLE_SVC_GATT_CHR_DATABASE_HASH_UUID16), + ble_gattc_cache_conn_on_read, conn); if (rc != 0) { /* no way to verify */ conn->cache_state = CACHE_INVALID; @@ -1440,6 +1451,9 @@ static void ble_gattc_cache_search_all_svcs_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; SLIST_FOREACH(svc, &conn->svcs, next) { @@ -1449,6 +1463,7 @@ static void ble_gattc_cache_search_all_svcs_cb(struct ble_npl_event *ev) } status = BLE_HS_EDONE; dcb(conn->conn_handle, ble_gattc_cache_error(status, 0), &svc->svc, op->cb_arg); + return; } @@ -1513,6 +1528,9 @@ ble_gattc_cache_conn_search_svc_by_uuid_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; SLIST_FOREACH(svc, &conn->svcs, next) { @@ -1522,6 +1540,7 @@ ble_gattc_cache_conn_search_svc_by_uuid_cb(struct ble_npl_event *ev) } status = BLE_HS_EDONE; dcb(conn_handle, ble_gattc_cache_error(status, 0), &svc->svc, op->cb_arg); + return; } @@ -1570,6 +1589,9 @@ ble_gattc_cache_conn_search_inc_svcs_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; SLIST_FOREACH(svc, &conn->svcs, next) { @@ -1580,6 +1602,7 @@ ble_gattc_cache_conn_search_inc_svcs_cb(struct ble_npl_event *ev) } status = BLE_HS_EDONE; dcb(conn->conn_handle, ble_gattc_cache_error(status, 0), &svc->svc, op->cb_arg); + return; } int @@ -1629,6 +1652,9 @@ ble_gattc_cache_conn_search_all_chrs_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; svc = ble_gattc_cache_conn_svc_find_range(conn, op->start_handle); @@ -1638,6 +1664,7 @@ ble_gattc_cache_conn_search_all_chrs_cb(struct ble_npl_event *ev) } status = BLE_HS_EDONE; dcb(conn_handle, ble_gattc_cache_error(status, 0), &chr->chr, op->cb_arg); + return; } @@ -1688,6 +1715,9 @@ ble_gattc_cache_conn_search_chrs_by_uuid_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; svc = ble_gattc_cache_conn_svc_find_range(conn, op->start_handle); @@ -1699,6 +1729,7 @@ ble_gattc_cache_conn_search_chrs_by_uuid_cb(struct ble_npl_event *ev) } status = BLE_HS_EDONE; dcb(conn_handle, ble_gattc_cache_error(status, 0), &chr->chr, op->cb_arg); + return; } @@ -1749,6 +1780,9 @@ ble_gattc_cache_conn_search_all_dscs_cb(struct ble_npl_event *ev) if (conn == NULL) { return; } + + ble_npl_event_deinit(&conn->disc_ev); + op = &conn->pending_op; dcb = op->cb; svc = ble_gattc_cache_conn_svc_find_range(conn, op->start_handle); @@ -1758,6 +1792,7 @@ ble_gattc_cache_conn_search_all_dscs_cb(struct ble_npl_event *ev) } status = BLE_HS_EDONE; dcb(conn_handle, ble_gattc_cache_error(status, 0), chr->chr.val_handle, &dsc->dsc, op->cb_arg); + return; } diff --git a/src/nimble/nimble/host/src/ble_gatts.c b/src/nimble/nimble/host/src/ble_gatts.c index 73546f8d..e0441ad0 100644 --- a/src/nimble/nimble/host/src/ble_gatts.c +++ b/src/nimble/nimble/host/src/ble_gatts.c @@ -25,13 +25,17 @@ #include "nimble/nimble/host/include/host/ble_uuid.h" #include "nimble/nimble/host/include/host/ble_store.h" #include "ble_hs_priv.h" +#ifdef ESP_PLATFORM #include "nimble/esp_port/port/include/esp_nimble_mem.h" +#endif + +static uint8_t perm_flags = BLE_ATT_F_READ | BLE_ATT_F_WRITE ; #if MYNEWT_VAL(BLE_DYNAMIC_SERVICE) #include "nimble/nimble/host/services/gatt/include/services/gatt/ble_svc_gatt.h" #endif #if MYNEWT_VAL(BLE_SVC_HID_SERVICE) -#include "nimble/nimble/host/services/gatt/include/services/hid/ble_svc_hid.h" +#include "services/hid/ble_svc_hid.h" #endif #define BLE_GATTS_INCLUDE_SZ 6 @@ -176,6 +180,11 @@ ble_gatts_clt_cfg_free(struct ble_gatts_clt_cfg *cfg) } #endif +void ble_gatts_set_clt_cfg_perm_flags(uint8_t flags) +{ + perm_flags = flags ; +} + static int ble_gatts_svc_access(uint16_t conn_handle, uint16_t attr_handle, uint8_t op, uint16_t offset, struct os_mbuf **om, @@ -513,6 +522,7 @@ ble_gatts_chr_val_access(uint16_t conn_handle, uint16_t attr_handle, gatt_ctxt.op = ble_gatts_chr_op(att_op); gatt_ctxt.chr = chr_def; + gatt_ctxt.offset = offset; ble_gatts_chr_inc_val_stat(gatt_ctxt.op); rc = ble_gatts_val_access(conn_handle, attr_handle, offset, &gatt_ctxt, om, @@ -606,16 +616,20 @@ ble_gatts_calculate_hash(uint8_t *out_hash_key) rc = ble_att_fill_database_info(buf); if(rc != 0) { - return rc; + goto done; } rc = ble_sm_alg_aes_cmac(key, buf, size, out_hash_key); if(rc != 0) { - return rc; + goto done; } swap_in_place(out_hash_key, 16); - return 0; + + rc = 0; +done: + nimble_platform_mem_free(buf); + return rc; } #endif @@ -1001,8 +1015,7 @@ static int ble_gatts_register_clt_cfg_dsc(uint16_t *att_handle) { int rc; - - rc = ble_att_svr_register(uuid_ccc, BLE_ATT_F_READ | BLE_ATT_F_WRITE, 0, + rc = ble_att_svr_register(uuid_ccc, perm_flags, 0, att_handle, ble_gatts_clt_cfg_access, NULL); if (rc != 0) { return rc; @@ -1509,7 +1522,13 @@ ble_gatts_connection_broken(uint16_t conn_handle) for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { if(memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { - ble_gatts_conn_aware_states[i].aware = conn->bhc_gatt_svr.aware_state; + if(conn->bhc_gatt_svr.half_aware) { + ble_gatts_conn_aware_states[i].aware = false; + ble_gatts_conn_aware_states[i].half_aware = 0; + } else { + ble_gatts_conn_aware_states[i].aware = conn->bhc_gatt_svr.aware_state; + ble_gatts_conn_aware_states[i].half_aware = conn->bhc_gatt_svr.half_aware; + } } } } @@ -2194,8 +2213,8 @@ ble_gatts_peer_cl_sup_feat_get(uint16_t conn_handle, uint8_t *out_supported_feat goto done; } - if (BLE_GATT_CHR_CLI_SUP_FEAT_SZ < len) { - len = BLE_GATT_CHR_CLI_SUP_FEAT_SZ; + if (MYNEWT_VAL(BLE_GATT_CSFC_SIZE) < len) { + len = MYNEWT_VAL(BLE_GATT_CSFC_SIZE); } memcpy(out_supported_feat, conn->bhc_gatt_svr.peer_cl_sup_feat, @@ -2210,7 +2229,9 @@ int ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) { struct ble_hs_conn *conn; - uint8_t feat[BLE_GATT_CHR_CLI_SUP_FEAT_SZ] = {}; + struct ble_store_value_csfc value_csfc; + struct ble_store_key_csfc key_csfc; + uint8_t feat[MYNEWT_VAL(BLE_GATT_CSFC_SIZE)] = {}; uint16_t len; int rc = 0; int i; @@ -2221,8 +2242,8 @@ ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) /* RFU bits are ignored so we can skip any bytes larger than supported */ len = os_mbuf_len(om); - if (len > BLE_GATT_CHR_CLI_SUP_FEAT_SZ) { - len = BLE_GATT_CHR_CLI_SUP_FEAT_SZ; + if (len > MYNEWT_VAL(BLE_GATT_CSFC_SIZE)) { + len = MYNEWT_VAL(BLE_GATT_CSFC_SIZE); } if (os_mbuf_copydata(om, 0, len, feat) < 0) { @@ -2230,7 +2251,7 @@ ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) } /* clear RFU bits */ - for (i = 0; i < BLE_GATT_CHR_CLI_SUP_FEAT_SZ; i++) { + for (i = 0; i < MYNEWT_VAL(BLE_GATT_CSFC_SIZE); i++) { feat[i] &= (BLE_GATT_CHR_CLI_SUP_FEAT_MASK >> (8 * i)); } @@ -2245,7 +2266,7 @@ ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) * Disabling already enabled features is not permitted * (Vol. 3, Part F, 3.3.3) */ - for (i = 0; i < BLE_GATT_CHR_CLI_SUP_FEAT_SZ; i++) { + for (i = 0; i < MYNEWT_VAL(BLE_GATT_CSFC_SIZE); i++) { if ((conn->bhc_gatt_svr.peer_cl_sup_feat[i] & feat[i]) != conn->bhc_gatt_svr.peer_cl_sup_feat[i]) { rc = BLE_ATT_ERR_VALUE_NOT_ALLOWED; @@ -2253,7 +2274,26 @@ ble_gatts_peer_cl_sup_feat_update(uint16_t conn_handle, struct os_mbuf *om) } } - memcpy(conn->bhc_gatt_svr.peer_cl_sup_feat, feat, BLE_GATT_CHR_CLI_SUP_FEAT_SZ); + memcpy(conn->bhc_gatt_svr.peer_cl_sup_feat, feat, MYNEWT_VAL(BLE_GATT_CSFC_SIZE)); + + if (conn->bhc_sec_state.bonded) { + memset(&key_csfc, 0, sizeof key_csfc); + key_csfc.peer_addr = conn->bhc_peer_addr; + + rc = ble_store_delete_csfc(&key_csfc); + if (rc != 0) { + goto done; + } + + memset(&value_csfc, 0, sizeof value_csfc); + value_csfc.peer_addr = conn->bhc_peer_addr; + memcpy(value_csfc.csfc, feat, MYNEWT_VAL(BLE_GATT_CSFC_SIZE)); + + rc = ble_store_write_csfc(&value_csfc); + if (rc != 0) { + goto done; + } + } done: ble_hs_unlock(); @@ -2369,6 +2409,7 @@ void ble_gatts_bonding_established(uint16_t conn_handle) { struct ble_store_value_cccd cccd_value; + struct ble_store_value_csfc csfc; struct ble_gatts_clt_cfg *clt_cfg; struct ble_gatts_conn *gatt_srv; struct ble_hs_conn *conn; @@ -2413,6 +2454,19 @@ ble_gatts_bonding_established(uint16_t conn_handle) } } + csfc.peer_addr = conn->bhc_peer_addr; + csfc.peer_addr.type = + ble_hs_misc_peer_addr_type_to_id(conn->bhc_peer_addr.type); + + memcpy(csfc.csfc, conn->bhc_gatt_svr.peer_cl_sup_feat, MYNEWT_VAL(BLE_GATT_CSFC_SIZE)); + + ble_hs_unlock(); + ble_store_write_csfc(&csfc); + ble_hs_lock(); + + conn = ble_hs_conn_find(conn_handle); + BLE_HS_DBG_ASSERT(conn != NULL); + #if MYNEWT_VAL(BLE_GATT_CACHING) /* store the bonded peer aware_state if space not available delete the @@ -2424,6 +2478,8 @@ ble_gatts_bonding_established(uint16_t conn_handle) sizeof(struct ble_gatts_aware_state)); memcpy(ble_gatts_conn_aware_states[new_idx].peer_id_addr, addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val); + ble_gatts_conn_aware_states[new_idx].aware = conn->bhc_gatt_svr.aware_state; + ble_gatts_conn_aware_states[new_idx].half_aware = conn->bhc_gatt_svr.half_aware; last_conn_aware_state_index = new_idx; #endif ble_hs_unlock(); @@ -2442,6 +2498,8 @@ ble_gatts_bonding_restored(uint16_t conn_handle) { struct ble_store_value_cccd cccd_value; struct ble_store_key_cccd cccd_key; + struct ble_store_value_csfc csfc_value; + struct ble_store_key_csfc csfc_key; struct ble_gatts_clt_cfg *clt_cfg; struct ble_hs_conn *conn; uint8_t att_op; @@ -2469,6 +2527,7 @@ ble_gatts_bonding_restored(uint16_t conn_handle) for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { if(memcmp(ble_gatts_conn_aware_states[i].peer_id_addr, addrs.peer_id_addr.val, sizeof addrs.peer_id_addr.val)) { + conn->bhc_gatt_svr.half_aware = ble_gatts_conn_aware_states[i].half_aware; conn->bhc_gatt_svr.aware_state = ble_gatts_conn_aware_states[i].aware; } } @@ -2541,6 +2600,14 @@ ble_gatts_bonding_restored(uint16_t conn_handle) cccd_key.idx++; } + + memset(&csfc_key, 0, sizeof csfc_key); + csfc_key.peer_addr = conn->bhc_peer_addr; + rc = ble_store_read_csfc(&csfc_key, &csfc_value); + if (rc != 0) { + return; + } + memcpy(conn->bhc_gatt_svr.peer_cl_sup_feat, csfc_value.csfc, MYNEWT_VAL(BLE_GATT_CSFC_SIZE)); } #if MYNEWT_VAL(BLE_DYNAMIC_SERVICE) @@ -2745,6 +2812,7 @@ static void ble_gatts_remove_clt_cfg(struct ble_gatts_clt_cfg_list *clt_cfgs, ui static int ble_gatts_conn_unaware(struct ble_hs_conn *conn, void *arg) { conn->bhc_gatt_svr.aware_state = false; + conn->bhc_gatt_svr.half_aware = 0; return 0; } #endif @@ -2844,6 +2912,7 @@ int ble_gatts_add_dynamic_svcs(const struct ble_gatt_svc_def *svcs) { #if MYNEWT_VAL(BLE_GATT_CACHING) /* make all bonded connections unaware */ for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { + ble_gatts_conn_aware_states[i].half_aware = 0; ble_gatts_conn_aware_states[i].aware = false; } ble_hs_conn_foreach(ble_gatts_conn_unaware, NULL); @@ -2945,6 +3014,7 @@ int ble_gatts_delete_svc(const ble_uuid_t *uuid) { /* make all bonded connections them unaware */ for(i = 0; i < MYNEWT_VAL(BLE_STORE_MAX_BONDS); i++) { ble_gatts_conn_aware_states[i].aware = false; + ble_gatts_conn_aware_states[i].half_aware = 0; } ble_hs_conn_foreach(ble_gatts_conn_unaware, NULL); #endif @@ -2987,6 +3057,19 @@ ble_gatts_add_svcs(const struct ble_gatt_svc_def *svcs) return rc; } +void ble_gatts_free_svcs(void) +{ + /* Ensure the memory is freed only if it was previously allocated */ + if (ble_gatts_svc_defs != NULL) { + /* Free the memory for the service definitions */ + free(ble_gatts_svc_defs); + /* Set the pointer to NULL to avoid dangling pointer */ + ble_gatts_svc_defs = NULL; + /* Reset the number of service definitions to 0 */ + ble_gatts_num_svc_defs = 0; + } +} + int ble_gatts_svc_set_visibility(uint16_t handle, int visible) { @@ -3197,6 +3280,17 @@ ble_gatts_lcl_svc_foreach(ble_gatt_svc_foreach_fn cb, void *arg) #endif } +#if MYNEWT_VAL(BLE_SVC_GAP_GATT_SECURITY_LEVEL) +uint8_t +ble_gatts_security_mode_1_level() { + uint8_t security_level; + + security_level = ble_att_svr_security_mode_1_level(); + + return security_level; +} +#endif + int ble_gatts_reset(void) { diff --git a/src/nimble/nimble/host/src/ble_hs.c b/src/nimble/nimble/host/src/ble_hs.c index ab8b804a..b807ba9f 100644 --- a/src/nimble/nimble/host/src/ble_hs.c +++ b/src/nimble/nimble/host/src/ble_hs.c @@ -23,16 +23,21 @@ #include "nimble/porting/nimble/include/sysinit/sysinit.h" #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/porting/nimble/include/stats/stats.h" -#include "../include/host/ble_hs.h" +#include "nimble/nimble/host/include/host/ble_hs.h" #include "ble_hs_priv.h" #include "nimble/nimble/include/nimble/nimble_npl.h" #ifndef MYNEWT #include "nimble/porting/nimble/include/nimble/nimble_port.h" #endif -#include "../include/host/ble_hs_pvcy.h" +#include "nimble/nimble/host/include/host/ble_hs_pvcy.h" +// #include "bt_common.h" +// #if (BT_HCI_LOG_INCLUDED == TRUE) +// #include "hci_log/bt_hci_log.h" +// #endif // (BT_HCI_LOG_INCLUDED == TRUE) -#define BLE_HS_HCI_EVT_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT) +#define BLE_HS_HCI_EVT_COUNT (MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT) + \ + MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT)) static void ble_hs_event_rx_hci_ev(struct ble_npl_event *ev); #if NIMBLE_BLE_CONNECT @@ -96,7 +101,11 @@ uint16_t ble_hs_max_client_configs; #if MYNEWT_VAL(BLE_HS_DEBUG) #ifdef ESP_PLATFORM +#define MAX_NESTED_LOCKS 5 +static TaskHandle_t ble_hs_task_handles[MAX_NESTED_LOCKS]; +static int ble_hs_task_handle_index = 0; static uint8_t ble_hs_mutex_locked; +static uint8_t counter_lock = 0; static TaskHandle_t ble_hs_task_handle; #endif static uint8_t ble_hs_dbg_mutex_locked; @@ -133,7 +142,7 @@ ble_hs_evq_set(struct ble_npl_eventq *evq) int ble_hs_locked_by_cur_task(void) { -#if MYNEWT +#ifdef MYNEWT struct os_task *owner; if (!ble_npl_os_started()) { @@ -145,7 +154,7 @@ ble_hs_locked_by_cur_task(void) #elif ESP_PLATFORM return (ble_hs_mutex_locked && ble_hs_task_handle == xTaskGetCurrentTaskHandle()); #else - return ble_hs_dbg_mutex_locked; + return 1; #endif } #endif @@ -178,8 +187,11 @@ ble_hs_lock_nested(void) rc = ble_npl_mutex_pend(&ble_hs_mutex, 0xffffffff); #if MYNEWT_VAL(BLE_HS_DEBUG) && defined(ESP_PLATFORM) + counter_lock++; ble_hs_mutex_locked = 1; ble_hs_task_handle = xTaskGetCurrentTaskHandle(); + ble_hs_task_handles[ble_hs_task_handle_index] = xTaskGetCurrentTaskHandle(); + ble_hs_task_handle_index++; #endif BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED); } @@ -198,15 +210,23 @@ ble_hs_unlock_nested(void) return; } #ifdef ESP_PLATFORM - if(ble_hs_task_handle == xTaskGetCurrentTaskHandle()) { - ble_hs_task_handle = NULL; - ble_hs_mutex_locked = 0; + if (counter_lock > 0) { + counter_lock--; + if (counter_lock == 0) { + ble_hs_mutex_locked = 0; + } + if (ble_hs_task_handles[ble_hs_task_handle_index - 1] == xTaskGetCurrentTaskHandle()) { + ble_hs_task_handle_index--; + ble_hs_task_handles[ble_hs_task_handle_index] = NULL; + ble_hs_task_handle = ble_hs_task_handles[ble_hs_task_handle_index -1]; + } } #endif #endif rc = ble_npl_mutex_release(&ble_hs_mutex); BLE_HS_DBG_ASSERT_EVAL(rc == 0 || rc == OS_NOT_STARTED); + } /** @@ -589,11 +609,7 @@ ble_hs_enqueue_hci_event(uint8_t *hci_evt) struct ble_npl_event *ev; ev = os_memblock_get(&ble_hs_hci_ev_pool); -#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS if (ev && ble_hs_evq->eventq) { -#else - if (ev && ble_hs_evq->q) { -#endif memset (ev, 0, sizeof *ev); ble_npl_event_init(ev, ble_hs_event_rx_hci_ev, hci_evt); ble_npl_eventq_put(ble_hs_evq, ev); @@ -702,6 +718,16 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg) { int rc; +// #if ((BT_HCI_LOG_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED) +// uint16_t len = OS_MBUF_PKTHDR(om)->omp_len + 1; +// uint8_t *data = (uint8_t *)malloc(len); +// assert(data != NULL); +// data[0] = 0x02; +// os_mbuf_copydata(om, 0, len - 1, &data[1]); +// bt_hci_log_record_hci_data(HCI_LOG_DATA_TYPE_C2H_ACL, &data[1], len - 1); +// free(data); +// #endif // (BT_HCI_LOG_INCLUDED == TRUE) + /* If flow control is enabled, mark this packet with its corresponding * connection handle. */ @@ -728,6 +754,17 @@ ble_hs_rx_data(struct os_mbuf *om, void *arg) int ble_hs_tx_data(struct os_mbuf *om) { +// #if ((BT_HCI_LOG_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED) +// uint16_t len = 0; +// uint8_t data[MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE) + 1]; +// data[0] = 0x02; +// len++; +// os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &data[1]); +// len += OS_MBUF_PKTLEN(om); + +// bt_hci_log_record_hci_data(data[0], &data[1], len - 1); +// #endif + return ble_transport_to_ll_acl(om); } @@ -771,10 +808,16 @@ ble_hs_init(void) SYSINIT_PANIC_ASSERT(rc == 0); #endif + #if NIMBLE_BLE_CONNECT rc = ble_l2cap_init(); SYSINIT_PANIC_ASSERT(rc == 0); +#endif + + rc = ble_gap_init(); + SYSINIT_PANIC_ASSERT(rc == 0); +#if NIMBLE_BLE_CONNECT rc = ble_att_init(); SYSINIT_PANIC_ASSERT(rc == 0); @@ -792,8 +835,6 @@ ble_hs_init(void) rc = ble_gatts_init(); SYSINIT_PANIC_ASSERT(rc == 0); #endif - rc = ble_gap_init(); - SYSINIT_PANIC_ASSERT(rc == 0); ble_hs_stop_init(); @@ -817,11 +858,6 @@ ble_hs_init(void) ble_hs_evq_set(nimble_port_get_dflt_eventq()); #endif -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED - /* Configure the HCI transport to communicate with a host. */ - ble_hci_trans_cfg_hs(ble_hs_hci_rx_evt, NULL, ble_hs_rx_data, NULL); -#endif - /* Enqueue the start event to the default event queue. Using the default * queue ensures the event won't run until the end of main(). This allows * the application to configure this package in the meantime. @@ -852,6 +888,14 @@ ble_transport_to_hs_acl_impl(struct os_mbuf *om) return ble_hs_rx_data(om, NULL); } +int +ble_transport_to_hs_iso_impl(struct os_mbuf *om) +{ + os_mbuf_free_chain(om); + + return 0; +} + void ble_transport_hs_init(void) { @@ -867,10 +911,6 @@ ble_hs_deinit(void) ble_monitor_deinit(); #endif -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED - ble_hci_trans_cfg_hs(NULL, NULL, NULL, NULL); -#endif - ble_npl_mutex_deinit(&ble_hs_mutex); ble_mqueue_deinit(&ble_hs_rx_q); diff --git a/src/nimble/nimble/host/src/ble_hs_adv.c b/src/nimble/nimble/host/src/ble_hs_adv.c index 8a1dd105..73e1d2df 100644 --- a/src/nimble/nimble/host/src/ble_hs_adv.c +++ b/src/nimble/nimble/host/src/ble_hs_adv.c @@ -22,6 +22,9 @@ #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/host/include/host/ble_hs_adv.h" #include "ble_hs_priv.h" +#if MYNEWT_VAL(ENC_ADV_DATA) +#include "nimble/nimble/host/include/host/ble_ead.h" +#endif struct find_field_data { uint8_t type; @@ -526,6 +529,33 @@ adv_set_fields(const struct ble_hs_adv_fields *adv_fields, } } + /*** 0x27 - LE Supported Features. */ + if (adv_fields->le_supp_feat_is_present) { + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_LE_SUPP_FEAT, + BLE_HS_ADV_LE_SUPP_FEAT_LEN, + adv_fields->le_supp_feat, dst, &dst_len_local, + max_len, om); + } + + /*** 0x2f - Advertising interval - long. */ + if (adv_fields->adv_itvl_long_is_present && adv_fields->adv_itvl_long > 0xFFFF) { + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_ADV_ITVL_LONG, + BLE_HS_ADV_ADV_ITVL_LONG_LEN, + &adv_fields->adv_itvl_long, dst, &dst_len_local, + max_len, om); + } + +#if MYNEWT_VAL(ENC_ADV_DATA) + /*** 0x31 - Encrypted Advertising Data. */ + if ((adv_fields->enc_adv_data != NULL) && + (adv_fields->enc_adv_data_len > BLE_EAD_RANDOMIZER_SIZE + BLE_EAD_MIC_SIZE)) { + rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_ENC_ADV_DATA, + adv_fields->enc_adv_data_len, + adv_fields->enc_adv_data, dst, &dst_len_local, + max_len, om); + } +#endif + /*** 0xff - Manufacturer specific data. */ if ((adv_fields->mfg_data != NULL) && (adv_fields->mfg_data_len >= 2)) { rc = ble_hs_adv_set_flat_mbuf(BLE_HS_ADV_TYPE_MFG_DATA, @@ -862,6 +892,13 @@ ble_hs_adv_parse_one_field(struct ble_hs_adv_fields *adv_fields, } break; +#if MYNEWT_VAL(ENC_ADV_DATA) + case BLE_HS_ADV_TYPE_ENC_ADV_DATA: + adv_fields->enc_adv_data = data; + adv_fields->enc_adv_data_len = data_len; + break; +#endif + case BLE_HS_ADV_TYPE_MFG_DATA: adv_fields->mfg_data = data; adv_fields->mfg_data_len = data_len; diff --git a/src/nimble/nimble/host/src/ble_hs_cfg.c b/src/nimble/nimble/host/src/ble_hs_cfg.c index 0569ccee..51a5d28b 100644 --- a/src/nimble/nimble/host/src/ble_hs_cfg.c +++ b/src/nimble/nimble/host/src/ble_hs_cfg.c @@ -27,7 +27,9 @@ struct ble_hs_cfg ble_hs_cfg = { .sm_bonding = MYNEWT_VAL(BLE_SM_BONDING), .sm_mitm = MYNEWT_VAL(BLE_SM_MITM), .sm_sc = MYNEWT_VAL(BLE_SM_SC), + .sm_sc_only = MYNEWT_VAL(BLE_SM_SC_ONLY), .sm_keypress = MYNEWT_VAL(BLE_SM_KEYPRESS), .sm_our_key_dist = MYNEWT_VAL(BLE_SM_OUR_KEY_DIST), .sm_their_key_dist = MYNEWT_VAL(BLE_SM_THEIR_KEY_DIST), + .eatt = MYNEWT_VAL(BLE_EATT_CHAN_NUM), }; diff --git a/src/nimble/nimble/host/src/ble_hs_conn.c b/src/nimble/nimble/host/src/ble_hs_conn.c index a01ec413..813ce4ca 100644 --- a/src/nimble/nimble/host/src/ble_hs_conn.c +++ b/src/nimble/nimble/host/src/ble_hs_conn.c @@ -194,6 +194,7 @@ ble_hs_conn_alloc(uint16_t conn_handle) } STAILQ_INIT(&conn->bhc_tx_q); + STAILQ_INIT(&conn->att_tx_q); STATS_INC(ble_hs_stats, conn_create); diff --git a/src/nimble/nimble/host/src/ble_hs_conn_priv.h b/src/nimble/nimble/host/src/ble_hs_conn_priv.h index 0e451194..c994ed22 100644 --- a/src/nimble/nimble/host/src/ble_hs_conn_priv.h +++ b/src/nimble/nimble/host/src/ble_hs_conn_priv.h @@ -95,6 +95,7 @@ struct ble_hs_conn { struct ble_gatts_conn bhc_gatt_svr; struct ble_gap_sec_state bhc_sec_state; + struct ble_gap_read_rem_ver_params bhc_rd_rem_ver_params; ble_gap_event_fn *bhc_cb; void *bhc_cb_arg; @@ -102,6 +103,12 @@ struct ble_hs_conn { #if MYNEWT_VAL(BLE_PERIODIC_ADV) struct ble_hs_periodic_sync *psync; #endif + + STAILQ_HEAD(, os_mbuf_pkthdr) att_tx_q; + bool client_att_busy; +#if MYNEWT_VAL(BLE_EATT_CHAN_NUM) > 0 + uint16_t default_cid; +#endif }; struct ble_hs_conn_addrs { diff --git a/src/nimble/nimble/host/src/ble_hs_flow.c b/src/nimble/nimble/host/src/ble_hs_flow.c index d03af253..cda570ad 100644 --- a/src/nimble/nimble/host/src/ble_hs_flow.c +++ b/src/nimble/nimble/host/src/ble_hs_flow.c @@ -237,7 +237,7 @@ ble_hs_flow_startup(void) /* Remove previous event from queue, if any*/ ble_npl_eventq_remove(ble_hs_evq_get(), &ble_hs_flow_ev); - + #if MYNEWT_VAL(SELFTEST) ble_npl_callout_stop(&ble_hs_flow_timer); diff --git a/src/nimble/nimble/host/src/ble_hs_hci.c b/src/nimble/nimble/host/src/ble_hs_hci.c index b90f33e5..5fe33e84 100644 --- a/src/nimble/nimble/host/src/ble_hs_hci.c +++ b/src/nimble/nimble/host/src/ble_hs_hci.c @@ -25,9 +25,239 @@ #include "ble_hs_priv.h" #include "nimble/nimble/transport/include/nimble/transport.h" +// #include "bt_common.h" +// #if (BT_HCI_LOG_INCLUDED == TRUE) +// #include "hci_log/bt_hci_log.h" +// #endif // (BT_HCI_LOG_INCLUDED == TRUE) #define BLE_HCI_CMD_TIMEOUT_MS 2000 +/* HCI ERROR */ +#define BLE_ERR_UNKNOWN_HCI_CMD 0x01 +#define BLE_ERR_UNK_CONN_ID 0x02 +#define BLE_ERR_HW_FAIL 0x03 +#define BLE_ERR_PAGE_TMO 0x04 +#define BLE_ERR_AUTH_FAIL 0x05 +#define BLE_ERR_PINKEY_MISSING 0x06 +#define BLE_ERR_MEM_CAPACITY 0x07 +#define BLE_ERR_CONN_SPVN_TMO 0x08 +#define BLE_ERR_CONN_LIMIT 0x09 +#define BLE_ERR_SYNCH_CONN_LIMIT 0x0a +#define BLE_ERR_ACL_CONN_EXISTS 0x0b +#define BLE_ERR_CMD_DISALLOWED 0x0c +#define BLE_ERR_CONN_REJ_RESOURCES 0x0d +#define BLE_ERR_CONN_REJ_SECURITY 0x0e +#define BLE_ERR_CONN_REJ_BD_ADDR 0x0f +#define BLE_ERR_CONN_ACCEPT_TMO 0x10 +#define BLE_ERR_UNSUPPORTED 0x11 +#define BLE_ERR_INV_HCI_CMD_PARMS 0x12 +#define BLE_ERR_REM_USER_CONN_TERM 0x13 +#define BLE_ERR_RD_CONN_TERM_RESRCS 0x14 +#define BLE_ERR_RD_CONN_TERM_PWROFF 0x15 +#define BLE_ERR_CONN_TERM_LOCAL 0x16 +#define BLE_ERR_REPEATED_ATTEMPTS 0x17 +#define BLE_ERR_NO_PAIRING 0x18 +#define BLE_ERR_UNK_LMP 0x19 +#define BLE_ERR_UNSUPP_REM_FEATURE 0x1a +#define BLE_ERR_SCO_OFFSET 0x1b +#define BLE_ERR_SCO_ITVL 0x1c +#define BLE_ERR_SCO_AIR_MODE 0x1d +#define BLE_ERR_INV_LMP_LL_PARM 0x1e +#define BLE_ERR_UNSPECIFIED 0x1f +#define BLE_ERR_UNSUPP_LMP_LL_PARM 0x20 +#define BLE_ERR_NO_ROLE_CHANGE 0x21 +#define BLE_ERR_LMP_LL_RSP_TMO 0x22 +#define BLE_ERR_LMP_COLLISION 0x23 +#define BLE_ERR_LMP_PDU 0x24 +#define BLE_ERR_ENCRYPTION_MODE 0x25 +#define BLE_ERR_LINK_KEY_CHANGE 0x26 +#define BLE_ERR_UNSUPP_QOS 0x27 +#define BLE_ERR_INSTANT_PASSED 0x28 +#define BLE_ERR_UNIT_KEY_PAIRING 0x29 +#define BLE_ERR_DIFF_TRANS_COLL 0x2a +/*#define BLE_ERR_RESERVED 0x2b*/ +#define BLE_ERR_QOS_PARM 0x2c +#define BLE_ERR_QOS_REJECTED 0x2d +#define BLE_ERR_CHAN_CLASS 0x2e +#define BLE_ERR_INSUFFICIENT_SEC 0x2f +#define BLE_ERR_PARM_OUT_OF_RANGE 0x30 +/*#define BLE_ERR_RESERVED 0x31*/ +#define BLE_ERR_PENDING_ROLE_SW 0x32 +/*#define BLE_ERR_RESERVED 0x33*/ +#define BLE_ERR_RESERVED_SLOT 0x34 +#define BLE_ERR_ROLE_SW_FAIL 0x35 +#define BLE_ERR_INQ_RSP_TOO_BIG 0x36 +#define BLE_ERR_SEC_SIMPLE_PAIR 0x37 +#define BLE_ERR_HOST_BUSY_PAIR 0x38 +#define BLE_ERR_CONN_REJ_CHANNEL 0x39 +#define BLE_ERR_CTLR_BUSY 0x3a +#define BLE_ERR_CONN_PARMS 0x3b +#define BLE_ERR_DIR_ADV_TMO 0x3c +#define BLE_ERR_CONN_TERM_MIC 0x3d +#define BLE_ERR_CONN_ESTABLISHMENT 0x3e +#define BLE_ERR_MAC_CONN_FAIL 0x3f +#define BLE_ERR_COARSE_CLK_ADJ 0x40 +#define BLE_ERR_TYPE0_SUBMAP_NDEF 0x41 +#define BLE_ERR_UNK_ADV_INDENT 0x42 +#define BLE_ERR_LIMIT_REACHED 0x43 +#define BLE_ERR_OPERATION_CANCELLED 0x44 +#define BLE_ERR_PACKET_TOO_LONG 0x45 +#define BLE_ERR_MAX 0xff + +struct err_code { + int error_code; + const char *msg; +}; + +static struct err_code core_err_code_list[] = { + { BLE_HS_EAGAIN, ": BLE_HS_EAGAIN (Temporary failure; try again)" }, + { BLE_HS_EALREADY, ": BLE_HS_EALREADY (Operation already in progress or completed)" }, + { BLE_HS_EINVAL, ": BLE_HS_EINVAL (One or more arguments are invalid)" }, + { BLE_HS_EMSGSIZE, ": BLE_HS_EMSGSIZE (The provided buffer is too small)" }, + { BLE_HS_ENOENT, ": BLE_HS_ENOENT (No entry matching the specified criteria)" }, + { BLE_HS_ENOMEM, ": BLE_HS_ENOMEM (Operation failed due to resource exhaustion)" }, + { BLE_HS_ENOTCONN, ": BLE_HS_ENOTCONN (No open connection with the specified handle)" }, + { BLE_HS_ENOTSUP, ": BLE_HS_ENOTSUP (Operation disabled at compile time)" }, + { BLE_HS_EAPP, ": BLE_HS_EAPP (Application callback behaved unexpectedly)" }, + { BLE_HS_EBADDATA, ": BLE_HS_EBADDATA (Command from peer is invalid)" }, + { BLE_HS_EOS, ": BLE_HS_EOS (Mynewt OS error)" }, + { BLE_HS_ECONTROLLER, ": BLE_HS_ECONTROLLER (Event from controller is invalid)" }, + { BLE_HS_ETIMEOUT, ": BLE_HS_ETIMEOUT (Operation timed out)" }, + { BLE_HS_EDONE, ": BLE_HS_EDONE (Operation completed successfully)" }, + { BLE_HS_EBUSY, ": BLE_HS_EBUSY (Operation cannot be performed until procedure completes)" }, + { BLE_HS_EREJECT, ": BLE_HS_EREJECT (Peer rejected a connection parameter update request)" }, + { BLE_HS_EUNKNOWN, ": BLE_HS_EUNKNOWN (Unexpected failure; catch all)" }, + { BLE_HS_EROLE, ": BLE_HS_EROLE (Operation requires different role (e.g., central vs. peripheral))" }, + { BLE_HS_ETIMEOUT_HCI, ": BLE_HS_ETIMEOUT_HCI (HCI request timed out; controller unresponsive)" }, + { BLE_HS_ENOMEM_EVT, ": BLE_HS_ENOMEM_EVT (Controller failed to send event due to memory exhaustion)" }, + { BLE_HS_ENOADDR, ": BLE_HS_ENOADDR (Operation requires an identity address but none configured)" }, + { BLE_HS_ENOTSYNCED, ": BLE_HS_ENOTSYNCED (Attempt to use the host before it is synced with controller)" }, + { BLE_HS_EAUTHEN, ": BLE_HS_EAUTHEN (Insufficient authentication)" }, + { BLE_HS_EAUTHOR, ": BLE_HS_EAUTHOR (Insufficient authorization)" }, + { BLE_HS_EENCRYPT, ": BLE_HS_EENCRYPT (Insufficient encryption level)" }, + { BLE_HS_EENCRYPT_KEY_SZ, ": BLE_HS_EENCRYPT_KEY_SZ (Insufficient key size" }, + { BLE_HS_ESTORE_CAP, ": BLE_HS_ESTORE_CAP (BLE_HS_ESTORE_FAIL,)" }, + { BLE_HS_ESTORE_FAIL, ": BLE_HS_ESTORE_FAIL (Storage IO error)" }, + { BLE_HS_EPREEMPTED, ": BLE_HS_EPREEMPTED (ation was preempted)" }, + { BLE_HS_EDISABLED, ": BLE_HS_EDISABLED (Operation disabled)" }, + { BLE_HS_ESTALLED, ": BLE_HS_ESTALLED (Operation stalled)" } +}; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" +static struct err_code err_code_list[] = { + { BLE_HS_HCI_ERR(BLE_ERR_UNKNOWN_HCI_CMD), ": BLE_ERR_UNKNOWN_HCI_CMD (Unknown HCI Command)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNK_CONN_ID), ": BLE_ERR_UNK_CONN_ID (Unknown Connection Identifier)" }, + { BLE_HS_HCI_ERR(BLE_ERR_HW_FAIL), ": BLE_ERR_HW_FAIL (Hardware Failure)" }, + { BLE_HS_HCI_ERR(BLE_ERR_PAGE_TMO), ": BLE_ERR_PAGE_TMO (Page Timeout)" }, + { BLE_HS_HCI_ERR(BLE_ERR_AUTH_FAIL), ": BLE_ERR_AUTH_FAIL (Authentication Failure)" }, + { BLE_HS_HCI_ERR(BLE_ERR_PINKEY_MISSING), ": BLE_ERR_PINKEY_MISSING (PIN or Key Missing)" }, + { BLE_HS_HCI_ERR(BLE_ERR_MEM_CAPACITY), ": BLE_ERR_MEM_CAPACITY (Memory Capacity Exceeded)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_SPVN_TMO), ": BLE_ERR_CONN_SPVN_TMO (Connection Timeout)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_LIMIT), ": BLE_ERR_CONN_LIMIT (Connection Limit Exceeded)" }, + { BLE_HS_HCI_ERR(BLE_ERR_SYNCH_CONN_LIMIT), ": BLE_ERR_SYNCH_CONN_LIMIT (Synchronous Connection Limit To A Device Exceeded)" }, + { BLE_HS_HCI_ERR(BLE_ERR_ACL_CONN_EXISTS), ": BLE_ERR_ACL_CONN_EXISTS (ACL Connection Already Exists)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CMD_DISALLOWED), ": BLE_ERR_CMD_DISALLOWED (Command Disallowed)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_REJ_RESOURCES), ": BLE_ERR_CONN_REJ_RESOURCES (Connection Rejected due to Limited Resources)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_REJ_SECURITY), ": BLE_ERR_CONN_REJ_SECURITY (Connection Rejected Due To Security Reasons)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_REJ_BD_ADDR), ": BLE_ERR_CONN_REJ_BD_ADDR (Connection Rejected due to Unacceptable BD_ADDR)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_ACCEPT_TMO), ": BLE_ERR_CONN_ACCEPT_TMO (Connection Accept Timeout Exceeded)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNSUPPORTED), ": BLE_ERR_UNSUPPORTED (Unsupported Feature or Parameter Value)" }, + { BLE_HS_HCI_ERR(BLE_ERR_INV_HCI_CMD_PARMS), ": BLE_ERR_INV_HCI_CMD_PARMS (Invalid HCI Command Parameters)" }, + { BLE_HS_HCI_ERR(BLE_ERR_REM_USER_CONN_TERM), ": BLE_ERR_REM_USER_CONN_TERM (Remote User Terminated Connection)" }, + { BLE_HS_HCI_ERR(BLE_ERR_RD_CONN_TERM_RESRCS), ": BLE_ERR_RD_CONN_TERM_RESRCS (Remote Device Terminated Connection due to Low Resources)" }, + { BLE_HS_HCI_ERR(BLE_ERR_RD_CONN_TERM_PWROFF), ": BLE_ERR_RD_CONN_TERM_PWROFF (Remote Device Terminated Connection due to Power Off)" }, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_TERM_LOCAL), ": BLE_ERR_CONN_TERM_LOCAL (Connection Terminated By Local Host)" }, + { BLE_HS_HCI_ERR(BLE_ERR_REPEATED_ATTEMPTS), ": BLE_ERR_REPEATED_ATTEMPTS (Repeated Attempts)" }, + { BLE_HS_HCI_ERR(BLE_ERR_NO_PAIRING), ": BLE_ERR_NO_PAIRING (Pairing Not Allowed)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNK_LMP), ": BLE_ERR_UNK_LMP (Unknown LMP PDU)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNSUPP_REM_FEATURE), ": BLE_ERR_UNSUPP_REM_FEATURE (Unsupported Remote Feature / Unsupported LMP Feature)" }, + { BLE_HS_HCI_ERR(BLE_ERR_SCO_OFFSET), ": BLE_ERR_SCO_OFFSET (SCO Offset Rejected)" }, + { BLE_HS_HCI_ERR(BLE_ERR_SCO_ITVL), ": BLE_ERR_SCO_ITVL (SCO Interval Rejected)" }, + { BLE_HS_HCI_ERR(BLE_ERR_SCO_AIR_MODE), ": BLE_ERR_SCO_AIR_MODE (SCO Air Mode Rejected)" }, + { BLE_HS_HCI_ERR(BLE_ERR_INV_LMP_LL_PARM), ": BLE_ERR_INV_LMP_LL_PARM (Invalid LMP Parameters / Invalid LL Parameters)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNSPECIFIED), ": BLE_ERR_UNSPECIFIED (Unspecified Error)" }, + { BLE_HS_HCI_ERR(BLE_ERR_UNSUPP_LMP_LL_PARM), ": BLE_ERR_UNSUPP_LMP_LL_PARM (Unsupported LMP Parameter Value / Unsupported LL Parameter Value)" }, + { BLE_HS_HCI_ERR(BLE_ERR_NO_ROLE_CHANGE), ": BLE_ERR_NO_ROLE_CHANGE (Role Change Not Allowed)" }, + { BLE_HS_HCI_ERR(BLE_ERR_LMP_LL_RSP_TMO), ": BLE_ERR_LMP_LL_RSP_TMO (LMP Response Timeout / LL Response Timeout)" }, + { BLE_HS_HCI_ERR(BLE_ERR_LMP_COLLISION), ": BLE_ERR_LMP_COLLISION (LMP Error Transaction Collision)" }, + { BLE_HS_HCI_ERR(BLE_ERR_LMP_PDU), ": BLE_ERR_LMP_PDU (LMP PDU Not Allowed)" }, + { BLE_HS_HCI_ERR(BLE_ERR_ENCRYPTION_MODE), ": BLE_ERR_ENCRYPTION_MODE (Encryption Mode Not Acceptable)"}, + { BLE_HS_HCI_ERR(BLE_ERR_LINK_KEY_CHANGE), ": BLE_ERR_LINK_KEY_CHANGE (Link Key cannot be Changed)"}, + { BLE_HS_HCI_ERR(BLE_ERR_UNSUPP_QOS), ": BLE_ERR_UNSUPP_QOS (Requested QoS Not Supported)"}, + { BLE_HS_HCI_ERR(BLE_ERR_INSTANT_PASSED), ": BLE_ERR_INSTANT_PASSED (Instant Passed)"}, + { BLE_HS_HCI_ERR(BLE_ERR_UNIT_KEY_PAIRING), ": BLE_ERR_UNIT_KEY_PAIRING (Pairing With Unit Key Not Supported)"}, + { BLE_HS_HCI_ERR(BLE_ERR_DIFF_TRANS_COLL), ": BLE_ERR_DIFF_TRANS_COLL (Different Transaction Collision)"}, + { BLE_HS_HCI_ERR(BLE_ERR_QOS_PARM), ": BLE_ERR_QOS_PARM (QoS Unacceptable Parameter)"}, + { BLE_HS_HCI_ERR(BLE_ERR_QOS_REJECTED), ": BLE_ERR_QOS_REJECTED (QoS Rejected)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CHAN_CLASS), ": BLE_ERR_CHAN_CLASS (Channel Classification Not Supported)"}, + { BLE_HS_HCI_ERR(BLE_ERR_INSUFFICIENT_SEC), ": BLE_ERR_INSUFFICIENT_SEC (Insufficient Security)"}, + { BLE_HS_HCI_ERR(BLE_ERR_PARM_OUT_OF_RANGE), ": BLE_ERR_PARM_OUT_OF_RANGE (Parameter Out Of Mandatory Range)"}, + { BLE_HS_HCI_ERR(BLE_ERR_PENDING_ROLE_SW), ": BLE_ERR_PENDING_ROLE_SW (Role Switch Pending)"}, + { BLE_HS_HCI_ERR(BLE_ERR_RESERVED_SLOT), ": BLE_ERR_RESERVED_SLOT (Reserved Slot Violation)"}, + { BLE_HS_HCI_ERR(BLE_ERR_ROLE_SW_FAIL), ": BLE_ERR_ROLE_SW_FAIL (Role Switch Failed)"}, + { BLE_HS_HCI_ERR(BLE_ERR_INQ_RSP_TOO_BIG), ": BLE_ERR_INQ_RSP_TOO_BIG (Extended Inquiry Response Too Large)"}, + { BLE_HS_HCI_ERR(BLE_ERR_SEC_SIMPLE_PAIR), ": BLE_ERR_SEC_SIMPLE_PAIR (Secure Simple Pairing Not Supported By Host)"}, + { BLE_HS_HCI_ERR(BLE_ERR_HOST_BUSY_PAIR), ": BLE_ERR_HOST_BUSY_PAIR (Host Busy - Pairing)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_REJ_CHANNEL), ": BLE_ERR_CONN_REJ_CHANNEL (Connection Rejected due to No Suitable Channel Found)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CTLR_BUSY), ": BLE_ERR_CTLR_BUSY (Controller Busy)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_PARMS), ": BLE_ERR_CONN_PARMS (Unacceptable Connection Parameters)"}, + { BLE_HS_HCI_ERR(BLE_ERR_DIR_ADV_TMO), ": BLE_ERR_DIR_ADV_TMO (Directed Advertising Timeout)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_TERM_MIC), ": BLE_ERR_CONN_TERM_MIC (Connection Terminated due to MIC Failure)"}, + { BLE_HS_HCI_ERR(BLE_ERR_CONN_ESTABLISHMENT), ": BLE_ERR_CONN_ESTABLISHMENT (Connection Failed to be Established)"}, + { BLE_HS_HCI_ERR(BLE_ERR_MAC_CONN_FAIL), ": BLE_ERR_MAC_CONN_FAIL (MAC Connection Failed)"}, + { BLE_HS_HCI_ERR(BLE_ERR_COARSE_CLK_ADJ), ": BLE_ERR_COARSE_CLK_ADJ (Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging)"}, + { BLE_HS_HCI_ERR(BLE_ERR_TYPE0_SUBMAP_NDEF), ": BLE_ERR_TYPE0_SUBMAP_NDEF (Type0 Submap Not Defined)"}, + { BLE_HS_HCI_ERR(BLE_ERR_UNK_ADV_INDENT), ": BLE_ERR_UNK_ADV_INDENT (Unknown Advertising Identifier)"}, + { BLE_HS_HCI_ERR(BLE_ERR_LIMIT_REACHED), ": BLE_ERR_LIMIT_REACHED (Limit Reached)"}, + { BLE_HS_HCI_ERR(BLE_ERR_OPERATION_CANCELLED), ": BLE_ERR_OPERATION_CANCELLED (Operation Cancelled by Host)"}, + { BLE_HS_HCI_ERR(BLE_ERR_PACKET_TOO_LONG), ": BLE_ERR_PACKET_TOO_LONG (Packet Too Long)"}, + { BLE_HS_HCI_ERR(BLE_ERR_MAX), ": BLE_ERR_MAX"} +}; +#pragma GCC diagnostic pop + +static void esp_core_err_to_name(int error_code, uint16_t *opcode) +{ + for (int i = 0; iopcode) { case BLE_HCI_EVCODE_COMMAND_COMPLETE: enqueue = (cmd_complete->opcode == BLE_HCI_OPCODE_NOP); @@ -659,6 +917,18 @@ ble_hs_hci_get_hci_version(void) return ble_hs_hci_version; } +void +ble_hs_hci_set_hci_supported_cmd(struct ble_hs_hci_sup_cmd sup_cmd) +{ + ble_hs_hci_sup_cmd = sup_cmd; +} + +struct ble_hs_hci_sup_cmd +ble_hs_hci_get_hci_supported_cmd(void) +{ + return ble_hs_hci_sup_cmd; +} + void ble_hs_hci_init(void) { diff --git a/src/nimble/nimble/host/src/ble_hs_hci_cmd.c b/src/nimble/nimble/host/src/ble_hs_hci_cmd.c index 0c06d7a9..32b8147c 100644 --- a/src/nimble/nimble/host/src/ble_hs_hci_cmd.c +++ b/src/nimble/nimble/host/src/ble_hs_hci_cmd.c @@ -24,13 +24,24 @@ #include "nimble/porting/nimble/include/os/os.h" #include "nimble/nimble/include/nimble/hci_common.h" #include "ble_hs_priv.h" + #ifdef ESP_PLATFORM -# if defined __has_include -# if __has_include ("soc/soc_caps.h") -# include "soc/soc_caps.h" -# endif -# endif -#endif +// #include "bt_common.h" +// #if (BT_HCI_LOG_INCLUDED == TRUE) +// #include "hci_log/bt_hci_log.h" +// #endif // (BT_HCI_LOG_INCLUDED == TRUE) + + +/* + * HCI Command Header + * + * Comprises the following fields + * -> Opcode group field & Opcode command field (2) + * -> Parameter Length (1) + * Length of all the parameters (does not include any part of the hci + * command header + */ +#define BLE_HCI_CMD_HDR_LEN (3) static int ble_hs_hci_cmd_transport(struct ble_hci_cmd *cmd) @@ -50,18 +61,6 @@ ble_hs_hci_cmd_transport(struct ble_hci_cmd *cmd) } } -#ifdef ESP_PLATFORM -/* - * HCI Command Header - * - * Comprises the following fields - * -> Opcode group field & Opcode command field (2) - * -> Parameter Length (1) - * Length of all the parameters (does not include any part of the hci - * command header - */ -#define BLE_HCI_CMD_HDR_LEN (3) - static int ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) { @@ -94,6 +93,16 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) buf--; #endif +// #if ((BT_HCI_LOG_INCLUDED == TRUE) && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED) +// uint8_t *data; +// #if !(SOC_ESP_NIMBLE_CONTROLLER) && CONFIG_BT_CONTROLLER_ENABLED +// data = (uint8_t *)buf + 1; +// #else +// data = (uint8_t *)buf; +// #endif +// bt_hci_log_record_hci_data(0x01, data, len + BLE_HCI_CMD_HDR_LEN); +// #endif + rc = ble_hs_hci_cmd_transport((void *) buf); if (rc == 0) { @@ -104,8 +113,25 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) return rc; } +# else /* ! ESP_PLATFORM */ +static int +ble_hs_hci_cmd_transport(struct ble_hci_cmd *cmd) +{ + int rc; + + rc = ble_transport_to_ll_cmd(cmd); + switch (rc) { + case 0: + return 0; + + case BLE_ERR_MEM_CAPACITY: + return BLE_HS_ENOMEM_EVT; + + default: + return BLE_HS_EUNKNOWN; + } +} -#else static int ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) { @@ -131,7 +157,8 @@ ble_hs_hci_cmd_send(uint16_t opcode, uint8_t len, const void *cmddata) return rc; } -#endif + +#endif /*ESP_PLATFORM */ int ble_hs_hci_cmd_send_buf(uint16_t opcode, const void *buf, uint8_t buf_len) diff --git a/src/nimble/nimble/host/src/ble_hs_hci_evt.c b/src/nimble/nimble/host/src/ble_hs_hci_evt.c index d1580512..c8055dfd 100644 --- a/src/nimble/nimble/host/src/ble_hs_hci_evt.c +++ b/src/nimble/nimble/host/src/ble_hs_hci_evt.c @@ -25,7 +25,9 @@ #include "nimble/nimble/host/include/host/ble_gap.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" +#ifdef ESP_PLATFORM #include "nimble/esp_port/port/include/esp_nimble_mem.h" +#endif #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) struct ble_gap_reattempt_ctxt { @@ -35,12 +37,7 @@ struct ble_gap_reattempt_ctxt { extern int ble_gap_master_connect_reattempt(uint16_t conn_handle); extern int ble_gap_slave_adv_reattempt(void); - -#ifdef CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT -#define MAX_REATTEMPT_ALLOWED CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT -#else -#define MAX_REATTEMPT_ALLOWED 0 -#endif +extern int slave_conn[MYNEWT_VAL(BLE_MAX_CONNECTIONS) + 1]; #endif #if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) @@ -57,6 +54,7 @@ typedef int ble_hs_hci_evt_fn(uint8_t event_code, const void *data, unsigned int len); static ble_hs_hci_evt_fn ble_hs_hci_evt_hw_error; static ble_hs_hci_evt_fn ble_hs_hci_evt_num_completed_pkts; +static ble_hs_hci_evt_fn ble_hs_hci_evt_rd_rem_ver_complete; #if NIMBLE_BLE_CONNECT static ble_hs_hci_evt_fn ble_hs_hci_evt_disconn_complete; static ble_hs_hci_evt_fn ble_hs_hci_evt_encrypt_change; @@ -93,6 +91,9 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_rpt; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_lost; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_scan_req_rcvd; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_sync_transfer; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_biginfo_adv_report; +#endif #if MYNEWT_VAL(BLE_POWER_CONTROL) static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_pathloss_threshold; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_transmit_power_report; @@ -100,6 +101,15 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_transmit_power_report; #if MYNEWT_VAL(BLE_CONN_SUBRATING) static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_subrate_change; #endif +#if MYNEWT_VAL(BLE_AOA_AOD) +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_connless_iq_report; +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_iq_report; +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_cte_req_failed; +#endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_subev_data_req; +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_periodic_adv_subev_resp_rep; +#endif /* Statistics */ struct host_hci_stats { @@ -119,6 +129,7 @@ struct ble_hs_hci_evt_dispatch_entry { static const struct ble_hs_hci_evt_dispatch_entry ble_hs_hci_evt_dispatch[] = { { BLE_HCI_EVCODE_LE_META, ble_hs_hci_evt_le_meta }, + { BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP, ble_hs_hci_evt_rd_rem_ver_complete }, { BLE_HCI_EVCODE_NUM_COMP_PKTS, ble_hs_hci_evt_num_completed_pkts }, #if NIMBLE_BLE_CONNECT { BLE_HCI_EVCODE_DISCONN_CMP, ble_hs_hci_evt_disconn_complete }, @@ -127,7 +138,7 @@ static const struct ble_hs_hci_evt_dispatch_entry ble_hs_hci_evt_dispatch[] = { #endif { BLE_HCI_EVCODE_HW_ERROR, ble_hs_hci_evt_hw_error }, #if MYNEWT_VAL(BLE_HCI_VS) - { BLE_HCI_EVCODE_VS_DEBUG, ble_hs_hci_evt_vs }, + { BLE_HCI_EVCODE_VS, ble_hs_hci_evt_vs }, #endif { BLE_HCI_OCF_LE_RX_TEST, ble_hs_hci_evt_rx_test }, { BLE_HCI_OCF_LE_TX_TEST, ble_hs_hci_evt_tx_test }, @@ -164,6 +175,9 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = { [BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED] = ble_hs_hci_evt_le_adv_set_terminated, [BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD] = ble_hs_hci_evt_le_scan_req_rcvd, [BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER] = ble_hs_hci_evt_le_periodic_adv_sync_transfer, +#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) + [BLE_HCI_LE_SUBEV_BIGINFO_ADV_REPORT] = ble_hs_hci_evt_le_biginfo_adv_report, +#endif #if MYNEWT_VAL(BLE_POWER_CONTROL) [BLE_HCI_LE_SUBEV_PATH_LOSS_THRESHOLD] = ble_hs_hci_evt_le_pathloss_threshold, [BLE_HCI_LE_SUBEV_TRANSMIT_POWER_REPORT] = ble_hs_hci_evt_le_transmit_power_report, @@ -171,6 +185,19 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = { #if MYNEWT_VAL(BLE_CONN_SUBRATING) [BLE_HCI_LE_SUBEV_SUBRATE_CHANGE] = ble_hs_hci_evt_le_subrate_change, #endif +#if MYNEWT_VAL(BLE_AOA_AOD) + [BLE_HCI_LE_SUBEV_CONNLESS_IQ_RPT] = ble_hs_hci_evt_le_connless_iq_report, + [BLE_HCI_LE_SUBEV_CONN_IQ_RPT] = ble_hs_hci_evt_le_conn_iq_report, + [BLE_HCI_LE_SUBEV_CTE_REQ_FAILED] = ble_hs_hci_evt_le_cte_req_failed, +#endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + [BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB_V2] = ble_hs_hci_evt_le_periodic_adv_sync_estab, + [BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT_V2] = ble_hs_hci_evt_le_periodic_adv_rpt, + [BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER_V2] = ble_hs_hci_evt_le_periodic_adv_sync_transfer, + [BLE_HCI_LE_SUBEV_PERIODIC_ADV_SUBEV_DATA_REQ] = ble_hs_hci_evt_le_periodic_adv_subev_data_req, + [BLE_HCI_LE_SUBEV_PERIODIC_ADV_RESP_REPORT] = ble_hs_hci_evt_le_periodic_adv_subev_resp_rep, + [BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE_V2] = ble_hs_hci_evt_le_enh_conn_complete, +#endif }; #define BLE_HS_HCI_EVT_LE_DISPATCH_SZ \ @@ -180,7 +207,7 @@ static const struct ble_hs_hci_evt_dispatch_entry * ble_hs_hci_evt_dispatch_find(uint8_t event_code) { const struct ble_hs_hci_evt_dispatch_entry *entry; - int i; + unsigned int i; for (i = 0; i < BLE_HS_HCI_EVT_DISPATCH_SZ; i++) { entry = ble_hs_hci_evt_dispatch + i; @@ -192,13 +219,16 @@ ble_hs_hci_evt_dispatch_find(uint8_t event_code) return NULL; } +#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) + static const uint8_t ble_hs_conn_null_addr[6]; +#endif + static ble_hs_hci_evt_le_fn * ble_hs_hci_evt_le_dispatch_find(uint8_t event_code) { if (event_code >= BLE_HS_HCI_EVT_LE_DISPATCH_SZ) { return NULL; } - return ble_hs_hci_evt_le_dispatch[event_code]; } @@ -222,46 +252,68 @@ ble_hs_hci_evt_disconn_complete(uint8_t event_code, const void *data, ble_hs_unlock(); #if MYNEWT_VAL(BLE_ENABLE_CONN_REATTEMPT) - if (conn && ev->reason == BLE_ERR_CONN_ESTABLISHMENT) { + if (conn) { uint16_t handle; int rc; - if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) { //slave - BLE_HS_LOG(INFO, "Reattempt advertising; reason: 0x%x, status = %x", - ev->reason, ev->status); - - rc = ble_gap_slave_adv_reattempt(); - if (rc != 0) { - BLE_HS_LOG(INFO, "Adv reattempt failed; rc= %d ", rc); - } - - return 0; // Restart advertising, so don't post disconnect event - - } else { // master - if (reattempt_conn.count < MAX_REATTEMPT_ALLOWED ) { - /* Got for connection */ - BLE_HS_LOG(INFO, "Reattempt connection; reason = 0x%x, status = %d," + /* For master role, check if failure reason is 0x3E, to restart connect attempt + * For slave role, check whether + * a. Failure reason is 0x3E + * b. Connect event was not posted and 0x8 was received + * Restart advertising in above reasons for slave. + */ + + if ((conn->bhc_flags & BLE_HS_CONN_F_MASTER) && \ + (ev->reason == BLE_ERR_CONN_ESTABLISHMENT)) { // master + if (reattempt_conn.count < MAX_REATTEMPT_ALLOWED) { + /* Go for connection */ + BLE_HS_LOG(INFO, "Reattempt connection; reason = 0x%x, status = %d," "reattempt count = %d ", ev->reason, ev->status, reattempt_conn.count); reattempt_conn.count += 1; - handle = le16toh(ev->conn_handle); - /* Post event to interested application */ - ble_gap_reattempt_count(handle, reattempt_conn.count); + handle = le16toh(ev->conn_handle); + /* Post event to interested application */ + ble_gap_reattempt_count(handle, reattempt_conn.count); rc = ble_gap_master_connect_reattempt(ev->conn_handle); - if (rc != 0) { - BLE_HS_LOG(INFO, "Master reconnect attempt failed; rc = %d", rc); - } + if (rc != 0) { + BLE_HS_LOG(INFO, "Master reconnect attempt failed; rc = %d", rc); + } } else { - /* Exhausted attempts */ - memset(&reattempt_conn, 0x0, sizeof (struct ble_gap_reattempt_ctxt)); + /* Exhausted attempts */ + memset(&reattempt_conn, 0x0, sizeof (struct ble_gap_reattempt_ctxt)); } } - } - else { + else if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER) && \ + ((ev->reason == BLE_ERR_CONN_ESTABLISHMENT) || \ + (!slave_conn[ev->conn_handle] && ev->reason == BLE_ERR_CONN_SPVN_TMO))) { //slave + + BLE_HS_LOG(INFO, "Reattempt advertising; reason: 0x%x, status = %x", + ev->reason, ev->status); + ble_l2cap_sig_conn_broken(ev->conn_handle, BLE_ERR_CONN_ESTABLISHMENT); + ble_sm_connection_broken(ev->conn_handle); + ble_gatts_connection_broken(ev->conn_handle); + ble_gattc_connection_broken(ev->conn_handle); + ble_hs_flow_connection_broken(ev->conn_handle);; +#if MYNEWT_VAL(BLE_GATT_CACHING) + ble_gattc_cache_conn_broken(ev->conn_handle); +#endif + rc = ble_hs_atomic_conn_delete(ev->conn_handle); + if (rc != 0) { + return rc; + } + + rc = ble_gap_slave_adv_reattempt(); + if (rc != 0) { + BLE_HS_LOG(INFO, "Adv reattempt failed; rc= %d ", rc); + } + + return 0; // Restart advertising, so don't post disconnect event + } else { /* Normal disconnect. Reset the structure */ memset(&reattempt_conn, 0x0, sizeof (struct ble_gap_reattempt_ctxt)); + } } #endif @@ -331,6 +383,10 @@ ble_hs_hci_evt_num_completed_pkts(uint8_t event_code, const void *data, uint16_t num_pkts; int i; + if (len < sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + if (len != sizeof(*ev) + (ev->count * sizeof(ev->completed[0]))) { return BLE_HS_ECONTROLLER; } @@ -364,7 +420,7 @@ ble_hs_hci_evt_num_completed_pkts(uint8_t event_code, const void *data, static int ble_hs_hci_evt_vs(uint8_t event_code, const void *data, unsigned int len) { - const struct ble_hci_ev_vs_debug *ev = data; + const struct ble_hci_ev_vs *ev = data; if (len < sizeof(*ev)) { return BLE_HS_ECONTROLLER; @@ -423,11 +479,6 @@ static struct ble_gap_conn_complete pend_conn_complete; #endif #if NIMBLE_BLE_CONNECT - -#if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) -static const uint8_t ble_hs_conn_null_addr[6]; -#endif - static int ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data, unsigned int len) @@ -454,7 +505,7 @@ ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data, #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) /* RPA needs to be resolved here, as controller is not aware of the * address is RPA in Host based RPA */ - if (ble_host_rpa_enabled() && !memcmp(evt.local_rpa, ble_hs_conn_null_addr, 6) == 0) { + if (ble_host_rpa_enabled() && ((!memcmp(evt.local_rpa, ble_hs_conn_null_addr, 6)) == 0)) { uint8_t *local_id_rpa = ble_hs_get_rpa_local(); memcpy(evt.local_rpa, local_id_rpa, BLE_DEV_ADDR_LEN); } @@ -472,7 +523,7 @@ ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data, evt.connection_handle = BLE_HS_CONN_HANDLE_NONE; #endif } -#if MYNEWT_VAL(BLE_EXT_ADV) +#if MYNEWT_VAL(BLE_EXT_ADV) && !MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) if (evt.status == BLE_ERR_DIR_ADV_TMO || evt.role == BLE_HCI_LE_CONN_COMPLETE_ROLE_SLAVE) { /* store this until we get set terminated event with adv handle */ @@ -480,6 +531,16 @@ ble_hs_hci_evt_le_enh_conn_complete(uint8_t subevent, const void *data, return 0; } #endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + if (subevent == BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE) { + evt.adv_handle = 0xFF; + evt.sync_handle = 0xFF; + } else { + evt.adv_handle = ev->adv_handle; + evt.sync_handle = ev->sync_handle; + } +#endif return ble_gap_rx_conn_complete(&evt, 0); } @@ -539,8 +600,6 @@ ble_hs_hci_evt_le_conn_complete(uint8_t subevent, const void *data, } #endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpointer-arith" static int ble_hs_hci_evt_le_adv_rpt_first_pass(const void *data, unsigned int len) { @@ -568,15 +627,13 @@ ble_hs_hci_evt_le_adv_rpt_first_pass(const void *data, unsigned int len) rpt = data; - len -= sizeof(*rpt) + 1; - data += sizeof(rpt) + 1; - if (rpt->data_len > len) { return BLE_HS_ECONTROLLER; } - len -= rpt->data_len; - data += rpt->data_len; + /* extra byte for RSSI after adv data */ + len -= sizeof(*rpt) + 1 + rpt->data_len; + data += sizeof(*rpt) + 1 + rpt->data_len; } /* Make sure length was correct */ @@ -652,7 +709,6 @@ ble_hs_hci_evt_le_adv_rpt(uint8_t subevent, const void *data, unsigned int len) return 0; } -#pragma GCC diagnostic pop static int ble_hs_hci_evt_le_dir_adv_rpt(uint8_t subevent, const void *data, unsigned int len) @@ -698,6 +754,22 @@ ble_hs_hci_evt_le_rd_rem_used_feat_complete(uint8_t subevent, const void *data, return 0; } +static int +ble_hs_hci_evt_rd_rem_ver_complete(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_rd_rem_ver_info_cmp *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_rd_rem_ver_info_complete(ev); + + return 0; +} + + #if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN static int ble_hs_hci_decode_legacy_type(uint16_t evt_type) @@ -718,29 +790,66 @@ ble_hs_hci_decode_legacy_type(uint16_t evt_type) return -1; } } -#endif static int -ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, const void *data, - unsigned int len) +ble_hs_hci_evt_le_ext_adv_rpt_first_pass(const void *data, unsigned int len) { -#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN const struct ble_hci_ev_le_subev_ext_adv_rpt *ev = data; const struct ext_adv_report *report; - struct ble_gap_ext_disc_desc desc; int i; - int legacy_event_type; if (len < sizeof(*ev)) { - return BLE_HS_EBADDATA; + return BLE_HS_ECONTROLLER; } + len -= sizeof(*ev); + data += sizeof(*ev); + if (ev->num_reports < BLE_HCI_LE_ADV_RPT_NUM_RPTS_MIN || ev->num_reports > BLE_HCI_LE_ADV_RPT_NUM_RPTS_MAX) { return BLE_HS_EBADDATA; } - /* TODO properly validate len of the event */ + for (i = 0; i < ev->num_reports; i++) { + if (len < sizeof(*report)) { + return BLE_HS_ECONTROLLER; + } + + report = data; + + if (report->data_len > len) { + return BLE_HS_ECONTROLLER; + } + + len -= sizeof(*report) + report->data_len; + data += sizeof(*report) + report->data_len; + } + + /* Make sure length was correct */ + if (len) { + return BLE_HS_ECONTROLLER; + } + + return 0; +} +#endif + +static int +ble_hs_hci_evt_le_ext_adv_rpt(uint8_t subevent, const void *data, + unsigned int len) +{ +#if MYNEWT_VAL(BLE_EXT_ADV) && NIMBLE_BLE_SCAN + const struct ble_hci_ev_le_subev_ext_adv_rpt *ev = data; + const struct ext_adv_report *report; + struct ble_gap_ext_disc_desc desc; + int legacy_event_type; + int rc; + int i; + + rc = ble_hs_hci_evt_le_ext_adv_rpt_first_pass(data, len); + if (rc != 0) { + return rc; + } report = &ev->reports[0]; for (i = 0; i < ev->num_reports; i++) { @@ -889,6 +998,23 @@ ble_hs_hci_evt_le_periodic_adv_sync_transfer(uint8_t subevent, const void *data, return 0; } +#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) +static int +ble_hs_hci_evt_le_biginfo_adv_report(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_biginfo_adv_report *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_EBADDATA; + } + + ble_gap_rx_biginfo_adv_rpt(ev); + + return 0; +} +#endif + static int ble_hs_hci_evt_le_scan_timeout(uint8_t subevent, const void *data, unsigned int len) @@ -916,6 +1042,13 @@ ble_hs_hci_evt_le_adv_set_terminated(uint8_t subevent, const void *data, return BLE_HS_ECONTROLLER; } + /* this indicates bug in controller as host uses instances from + * 0-BLE_ADV_INSTANCES range only + */ + if (ev->adv_handle >= BLE_ADV_INSTANCES) { + return BLE_HS_ECONTROLLER; + } + if (ev->status == 0) { /* ignore return code as we need to terminate advertising set anyway */ ble_gap_rx_conn_complete(&pend_conn_complete, ev->adv_handle); @@ -937,6 +1070,13 @@ ble_hs_hci_evt_le_scan_req_rcvd(uint8_t subevent, const void *data, return BLE_HS_ECONTROLLER; } + /* this indicates bug in controller as host uses instances from + * 0-BLE_ADV_INSTANCES range only + */ + if (ev->adv_handle >= BLE_ADV_INSTANCES) { + return BLE_HS_ECONTROLLER; + } + ble_gap_rx_scan_req_rcvd(ev); #endif @@ -960,6 +1100,116 @@ ble_hs_hci_evt_le_subrate_change(uint8_t subevent, const void *data, } #endif +#if MYNEWT_VAL(BLE_AOA_AOD) +static int +ble_hs_hci_evt_le_connless_iq_report(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_connless_iq_rpt *ev = data; + + if (len < sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_connless_iq_report(ev); + + return 0; +} + +static int +ble_hs_hci_evt_le_conn_iq_report(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_conn_iq_rpt *ev = data; + if (len < sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_conn_iq_report(ev); + + return 0; +} + +static int +ble_hs_hci_evt_le_cte_req_failed(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_cte_req_failed *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_cte_req_failed(ev); + + return 0; +} +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) +static int +ble_hs_hci_evt_le_periodic_adv_subev_data_req(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_periodic_adv_subev_data_req *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_periodic_adv_subev_data_req(ev); + + return 0; +} + +static int +ble_hs_hci_evt_le_periodic_adv_subev_resp_rep(uint8_t subevent, const void *data, unsigned int len) +{ + const struct ble_hci_ev_le_subev_periodic_adv_resp_rep *ev = data; + const struct periodic_adv_response *response; + struct ble_gap_periodic_adv_response resp; + uint32_t size; + + /* TODO: compare with the total length including the response data. */ + size = sizeof(*ev); + for (uint8_t i = 0; i < ev->num_responses; i ++) { + size += sizeof(struct periodic_adv_response) + ev->responses[i].data_length; + } + if (len < size) { + return BLE_HS_ECONTROLLER; + } + + len -= sizeof(*ev); + data += sizeof(*ev); + + resp.adv_handle = ev->adv_handle; + resp.subevent = ev->subevent; + resp.tx_status = ev->tx_status; + + for (uint8_t i = 0; i < ev->num_responses; i++) { + response = data; + if (len < sizeof(*response) + response->data_length) { + return BLE_HS_ECONTROLLER; + } + + len -= sizeof(*response) + response->data_length; + data += sizeof(*response) + response->data_length; + + resp.tx_power = response->tx_power; + resp.rssi = response->rssi; + resp.cte_type = response->cte_type; + resp.response_slot = response->response_slot; + resp.data_length = response->data_length; + resp.data = response->data; + resp.data_status = response->data_status; + + ble_gap_rx_periodic_adv_response(resp); + } + + return 0; +} +#endif + #if NIMBLE_BLE_CONNECT static int ble_hs_hci_evt_le_conn_upd_complete(uint8_t subevent, const void *data, @@ -1068,8 +1318,8 @@ ble_hs_hci_evt_process(struct ble_hci_ev *ev) if(ev->opcode == BLE_HCI_EVCODE_COMMAND_COMPLETE) { /* Check if this Command complete has a parsable opcode */ - struct ble_hci_ev_command_complete *cmd_complete = (void *) ev->data; - entry = ble_hs_hci_evt_dispatch_find(cmd_complete->opcode); + struct ble_hci_ev_command_complete *cmd_complete = (void *) ev->data; + entry = ble_hs_hci_evt_dispatch_find(cmd_complete->opcode); } else { entry = ble_hs_hci_evt_dispatch_find(ev->opcode); @@ -1085,8 +1335,9 @@ ble_hs_hci_evt_process(struct ble_hci_ev *ev) BLE_HS_LOG(DEBUG, "ble_hs_event_rx_hci_ev; opcode=0x%x ", ev->opcode); /* For LE Meta, print subevent code */ - if(ev->opcode == 0x3e) + if(ev->opcode == 0x3e) { BLE_HS_LOG(DEBUG, "subevent: 0x%x", ev->data[0]); + } BLE_HS_LOG(DEBUG, "\n"); } diff --git a/src/nimble/nimble/host/src/ble_hs_hci_priv.h b/src/nimble/nimble/host/src/ble_hs_hci_priv.h index ab699d9f..c63b55c4 100644 --- a/src/nimble/nimble/host/src/ble_hs_hci_priv.h +++ b/src/nimble/nimble/host/src/ble_hs_hci_priv.h @@ -79,6 +79,10 @@ struct hci_periodic_adv_params #endif #endif +struct ble_hs_hci_sup_cmd { + uint8_t commands[64]; +}; + extern uint16_t ble_hs_hci_avail_pkts; /* This function is not waiting for command status/complete HCI events */ @@ -92,6 +96,8 @@ void ble_hs_hci_set_le_supported_feat(uint32_t feat); uint32_t ble_hs_hci_get_le_supported_feat(void); void ble_hs_hci_set_hci_version(uint8_t hci_version); uint8_t ble_hs_hci_get_hci_version(void); +void ble_hs_hci_set_hci_supported_cmd(struct ble_hs_hci_sup_cmd sup_cmd); +struct ble_hs_hci_sup_cmd ble_hs_hci_get_hci_supported_cmd(void); #if MYNEWT_VAL(BLE_HS_PHONY_HCI_ACKS) typedef int ble_hs_hci_phony_ack_fn(uint8_t *ack, int ack_buf_len); @@ -102,6 +108,12 @@ int ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_pwr); int ble_hs_hci_util_rand(void *dst, int len); int ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi); int ble_hs_hci_util_set_random_addr(const uint8_t *addr); +int ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets, + uint16_t tx_time); +int ble_hs_hci_util_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets, + uint16_t *out_sugg_max_tx_time); +int ble_hs_hci_util_write_sugg_def_data_len(uint16_t sugg_max_tx_octets, + uint16_t sugg_max_tx_time); int ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om, struct hci_data_hdr *out_hdr); int ble_hs_hci_evt_process(struct ble_hci_ev *ev); diff --git a/src/nimble/nimble/host/src/ble_hs_hci_util.c b/src/nimble/nimble/host/src/ble_hs_hci_util.c index 4273c784..6b2e364b 100644 --- a/src/nimble/nimble/host/src/ble_hs_hci_util.c +++ b/src/nimble/nimble/host/src/ble_hs_hci_util.c @@ -81,7 +81,7 @@ ble_hs_hci_util_rand(void *dst, int len) return rc; } - chunk_sz = min(len, sizeof(rsp)); + chunk_sz = min(len, (int)sizeof(rsp)); memcpy(u8ptr, &rsp.random_number, chunk_sz); len -= chunk_sz; @@ -184,12 +184,14 @@ ble_hs_hci_util_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets, if (*out_sugg_max_tx_octets < BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MIN || *out_sugg_max_tx_octets > BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX) { - BLE_HS_LOG(WARN, "received suggested maximum tx octets is out of range\n"); + BLE_HS_LOG(WARN, + "received suggested maximum tx octets is out of range\n"); } if (*out_sugg_max_tx_time < BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MIN || *out_sugg_max_tx_time > BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX) { - BLE_HS_LOG(WARN, "received suggested maximum tx time is out of range\n"); + BLE_HS_LOG(WARN, + "received suggested maximum tx time is out of range\n"); } return 0; diff --git a/src/nimble/nimble/host/src/ble_hs_id.c b/src/nimble/nimble/host/src/ble_hs_id.c index 0b1e48c2..f20b626a 100644 --- a/src/nimble/nimble/host/src/ble_hs_id.c +++ b/src/nimble/nimble/host/src/ble_hs_id.c @@ -24,6 +24,8 @@ static uint8_t ble_hs_id_pub[6]; static uint8_t ble_hs_id_rnd[6]; +static const uint8_t ble_hs_misc_null_addr[6]; + bool ble_hs_is_rpa(uint8_t *addr, uint8_t addr_type) @@ -222,11 +224,13 @@ ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr, switch (id_addr_type) { case BLE_ADDR_PUBLIC: + case BLE_ADDR_PUBLIC_ID: id_addr = ble_hs_id_pub; nrpa = 0; break; case BLE_ADDR_RANDOM: + case BLE_ADDR_RANDOM_ID: id_addr = ble_hs_id_rnd; nrpa = (ble_hs_id_rnd[5] & 0xc0) == 0; break; diff --git a/src/nimble/nimble/host/src/ble_hs_mbuf.c b/src/nimble/nimble/host/src/ble_hs_mbuf.c index c1236f96..24af8bcd 100644 --- a/src/nimble/nimble/host/src/ble_hs_mbuf.c +++ b/src/nimble/nimble/host/src/ble_hs_mbuf.c @@ -100,12 +100,12 @@ ble_hs_mbuf_l2cap_pkt(void) struct os_mbuf * ble_hs_mbuf_att_pkt(void) { - /* Prepare write request and response are the larget ATT commands which + /* Prepare write request and response are the largest ATT commands which * contain attribute data. */ - return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ + - BLE_L2CAP_HDR_SZ + - BLE_ATT_PREP_WRITE_CMD_BASE_SZ); + return ble_hs_mbuf_gen_pkt(BLE_HCI_DATA_HDR_SZ + + BLE_L2CAP_HDR_SZ + + BLE_ATT_PREP_WRITE_CMD_BASE_SZ); } struct os_mbuf * diff --git a/src/nimble/nimble/host/src/ble_hs_misc.c b/src/nimble/nimble/host/src/ble_hs_misc.c index b9567f38..8591a3c6 100644 --- a/src/nimble/nimble/host/src/ble_hs_misc.c +++ b/src/nimble/nimble/host/src/ble_hs_misc.c @@ -22,8 +22,6 @@ #include "nimble/porting/nimble/include/os/os.h" #include "ble_hs_priv.h" -const uint8_t ble_hs_misc_null_addr[6]; - int ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid, struct ble_hs_conn **out_conn, diff --git a/src/nimble/nimble/host/src/ble_hs_priv.h b/src/nimble/nimble/host/src/ble_hs_priv.h index ed900e58..1ec09747 100644 --- a/src/nimble/nimble/host/src/ble_hs_priv.h +++ b/src/nimble/nimble/host/src/ble_hs_priv.h @@ -24,6 +24,7 @@ #include #include "ble_att_cmd_priv.h" #include "ble_att_priv.h" +#include "ble_eatt_priv.h" #include "ble_gap_priv.h" #include "ble_gatt_priv.h" #include "ble_hs_hci_priv.h" @@ -97,8 +98,6 @@ extern struct os_mbuf_pool ble_hs_mbuf_pool; extern uint8_t ble_hs_sync_state; extern uint8_t ble_hs_enabled_state; -extern const uint8_t ble_hs_misc_null_addr[6]; - extern uint16_t ble_hs_max_attrs; extern uint16_t ble_hs_max_services; extern uint16_t ble_hs_max_client_configs; diff --git a/src/nimble/nimble/host/src/ble_hs_pvcy.c b/src/nimble/nimble/host/src/ble_hs_pvcy.c index dee55e87..29cbc752 100644 --- a/src/nimble/nimble/host/src/ble_hs_pvcy.c +++ b/src/nimble/nimble/host/src/ble_hs_pvcy.c @@ -51,11 +51,11 @@ ble_hs_pvcy_set_addr_timeout(uint16_t timeout) &cmd, sizeof(cmd), NULL, 0); } -void ble_hs_set_rpa_timeout (uint16_t timeout) +int ble_hs_set_rpa_timeout (uint16_t timeout) { rpa_timeout = timeout; - ble_hs_pvcy_set_addr_timeout(rpa_timeout); + return ble_hs_pvcy_set_addr_timeout(rpa_timeout); } uint16_t ble_hs_get_rpa_timeout(void) diff --git a/src/nimble/nimble/host/src/ble_hs_resolv.c b/src/nimble/nimble/host/src/ble_hs_resolv.c index 2d6b55b2..3dfa93dd 100644 --- a/src/nimble/nimble/host/src/ble_hs_resolv.c +++ b/src/nimble/nimble/host/src/ble_hs_resolv.c @@ -29,20 +29,13 @@ #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/nimble_opt.h" #include "ble_hs_resolv_priv.h" -#include "../store/config/include/store/config/ble_store_config.h" -#include "../store/config/src/ble_store_config_priv.h" +#include "nimble/nimble/host/store/config/include/store/config/ble_store_config.h" +#include "nimble/nimble/host/store/config/src/ble_store_config_priv.h" /* Resolve list size, additional space to save local device's configuration */ #define BLE_RESOLV_LIST_SIZE (MYNEWT_VAL(BLE_STORE_MAX_BONDS) + 1) #define BLE_MAX_RPA_TIMEOUT_VAL 0xA1B8 -static struct ble_hs_resolv_data g_ble_hs_resolv_data; -static struct ble_hs_resolv_entry g_ble_hs_resolv_list[BLE_RESOLV_LIST_SIZE]; -/* Allocate one extra space for peer_records than no. of Bonds, it will take - * care of storage overflow */ -static struct ble_hs_dev_records peer_dev_rec[BLE_RESOLV_LIST_SIZE]; -static int ble_store_num_peer_dev_rec; - struct ble_hs_resolv_data { uint8_t addr_res_enabled; uint8_t rl_cnt; @@ -50,6 +43,13 @@ struct ble_hs_resolv_data { struct ble_npl_callout rpa_timer; }; +static struct ble_hs_resolv_data g_ble_hs_resolv_data; +static struct ble_hs_resolv_entry g_ble_hs_resolv_list[BLE_RESOLV_LIST_SIZE]; +/* Allocate one extra space for peer_records than no. of Bonds, it will take + * care of storage overflow */ +static struct ble_hs_dev_records peer_dev_rec[BLE_RESOLV_LIST_SIZE]; +static int ble_store_num_peer_dev_rec; + /* NRPA bit: Enables NRPA as private address. */ static bool nrpa_pvcy; @@ -563,25 +563,9 @@ ble_hs_resolv_list_add(uint8_t *cmdbuf) addr_type = cmdbuf[0]; ident_addr = cmdbuf + 1; -/*--------------------------------------------------------------------------------*/ - /* Temporary workaround to resolve an issue when deinitializing the stack - * and reinitializing. If the a peer deletes the bonding info after deiniting - * it will not be able to re-bond without this. Awaiting upstream fix. - */ -/* if (ble_hs_is_on_resolv_list(ident_addr, addr_type)) { return BLE_HS_EINVAL; } -*/ - int position = ble_hs_is_on_resolv_list(ident_addr, addr_type); - if (position) { - memmove(&g_ble_hs_resolv_list[position], - &g_ble_hs_resolv_list[position + 1], - (g_ble_hs_resolv_data.rl_cnt - position) * sizeof (struct - ble_hs_resolv_entry)); - --g_ble_hs_resolv_data.rl_cnt; - } -/*--------------------------------------------------------------------------------*/ rl = &g_ble_hs_resolv_list[g_ble_hs_resolv_data.rl_cnt]; memset(rl, 0, sizeof(*rl)); diff --git a/src/nimble/nimble/host/src/ble_hs_shutdown.c b/src/nimble/nimble/host/src/ble_hs_shutdown.c index 9dacccba..bdd7f727 100644 --- a/src/nimble/nimble/host/src/ble_hs_shutdown.c +++ b/src/nimble/nimble/host/src/ble_hs_shutdown.c @@ -17,9 +17,9 @@ * under the License. */ -#if MYNEWT +#ifdef MYNEWT -#include "nimble/porting/nimble/include/os/mynewt.h" +#include "os/mynewt.h" #include "ble_hs_priv.h" static struct ble_hs_stop_listener ble_hs_shutdown_stop_listener; diff --git a/src/nimble/nimble/host/src/ble_hs_startup.c b/src/nimble/nimble/host/src/ble_hs_startup.c index 9670dd46..3d3421ee 100644 --- a/src/nimble/nimble/host/src/ble_hs_startup.c +++ b/src/nimble/nimble/host/src/ble_hs_startup.c @@ -68,6 +68,26 @@ ble_hs_startup_read_local_ver_tx(void) return 0; } +static int +ble_hs_startup_read_sup_cmd_tx(void) +{ + struct ble_hci_ip_rd_loc_supp_cmd_rp rsp; + struct ble_hs_hci_sup_cmd sup_cmd; + int rc; + + rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS, + BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD), + NULL, 0, &rsp, sizeof(rsp)); + if (rc != 0) { + return rc; + } + + memcpy(&sup_cmd.commands, &rsp.commands, sizeof(sup_cmd)); + ble_hs_hci_set_hci_supported_cmd(sup_cmd); + + return 0; +} + static int ble_hs_startup_le_read_sup_f_tx(void) { @@ -247,6 +267,18 @@ ble_hs_startup_le_set_evmask_tx(void) * 0x0000000400000000 LE Subrate change event */ mask |= 0x0000000400000000; + } +#endif + +#if MYNEWT_VAL(BLE_POWER_CONTROL) + if (version >= BLE_HCI_VER_BCS_5_2) { + /** + * Enable the following LE events: + * 0x0000000080000000 LE Path Loss Threshold event + * 0x0000000100000000 LE Transmit Power Reporting event + */ + mask |= 0x0000000180000000; + } #endif #if MYNEWT_VAL(BLE_POWER_CONTROL) @@ -260,6 +292,52 @@ ble_hs_startup_le_set_evmask_tx(void) } #endif +#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_BIGINFO_REPORTS) + if (version >= BLE_HCI_VER_BCS_5_2) { + /** + * Enable the following LE events: + * 0x0000000200000000 LE BIGInfo Advertising Report event + */ + mask |= 0x0000000200000000; + } +#endif + +#if MYNEWT_VAL(BLE_AOA_AOD) + if (version >= BLE_HCI_VER_BCS_5_1) { + /** + * Enable the following LE events: + * 0x0000000000100000 LE Connectionless IQ Report event + * 0x0000000000200000 LE Connection IQ Report event + * 0x0000000000400000 LE CTE Request Failed event + */ + mask |= 0x0000000000700000; + } +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + if (version >= BLE_HCI_VER_BCS_5_4) { + /** + * Enable the following LE events: + * 0x0000000800000000 LE Periodic Advertising Sync Established event V2 + * 0x0000001000000000 LE Periodic Advertising Report Event V2 + * 0x0000004000000000 LE Periodic Advertising Subevent Data Request event + * 0x0000008000000000 LE Periodic Advertising Response Report event + * 0x0000010000000000 LE Enhanced Connection Complete event V2 + */ + mask |= 0x000001d800000000; + } +#endif + +#if MYNEWT_VAL(BLE_PERIODIC_ADV_SYNC_TRANSFER) + if (version >= BLE_HCI_VER_BCS_5_4) { + /** + * Enable the following LE events: + * 0x0000002000000000 LE Periodic Advertising Sync Transfer Received event V2 + */ + mask |= 0x0000002000000000; + } +#endif + cmd.event_mask = htole64(mask); rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, @@ -278,20 +356,23 @@ ble_hs_startup_set_evmask_tx(void) struct ble_hci_cb_set_event_mask_cp cmd; struct ble_hci_cb_set_event_mask2_cp cmd2; uint8_t version; + struct ble_hs_hci_sup_cmd sup_cmd; int rc; version = ble_hs_hci_get_hci_version(); + sup_cmd = ble_hs_hci_get_hci_supported_cmd(); /** * Enable the following events: * 0x0000000000000010 Disconnection Complete Event * 0x0000000000000080 Encryption Change Event + * 0x0000000000000800 Read Remote Version Information Complete event * 0x0000000000008000 Hardware Error Event * 0x0000000002000000 Data Buffer Overflow Event * 0x0000800000000000 Encryption Key Refresh Complete Event * 0x2000000000000000 LE Meta-Event */ - cmd.event_mask = htole64(0x2000800002008090); + cmd.event_mask = htole64(0x2000800002008890); rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND, BLE_HCI_OCF_CB_SET_EVENT_MASK), @@ -300,7 +381,7 @@ ble_hs_startup_set_evmask_tx(void) return rc; } - if (version >= BLE_HCI_VER_BCS_4_1) { + if ((version >= BLE_HCI_VER_BCS_4_1) && ((sup_cmd.commands[22] & 0x04) != 0)) { /** * Enable the following events: * 0x0000000000800000 Authenticated Payload Timeout Event @@ -328,6 +409,7 @@ ble_hs_startup_reset_tx(void) int ble_hs_startup_go(void) { + struct ble_store_gen_key gen_key; int rc; rc = ble_hs_startup_reset_tx(); @@ -340,7 +422,11 @@ ble_hs_startup_go(void) return rc; } - /* XXX: Read local supported commands. */ + /* Read local supported commands. */ + rc = ble_hs_startup_read_sup_cmd_tx(); + if (rc != 0) { + return rc; + } /* we need to check this only if using external controller */ #if !MYNEWT_VAL(BLE_CONTROLLER) @@ -382,9 +468,22 @@ ble_hs_startup_go(void) return rc; } - ble_hs_pvcy_set_default_irk(); + if (ble_hs_cfg.store_gen_key_cb) { + memset(&gen_key, 0, sizeof(gen_key)); + rc = ble_hs_cfg.store_gen_key_cb(BLE_STORE_GEN_KEY_IRK, &gen_key, + BLE_HS_CONN_HANDLE_NONE); + if (rc == 0) { + ble_hs_pvcy_set_our_irk(gen_key.irk); + } + } else { + rc = -1; + } - ble_hs_pvcy_set_our_irk(NULL); + if (rc != 0) { + ble_hs_pvcy_set_default_irk(); + + ble_hs_pvcy_set_our_irk(NULL); + } /* If flow control is enabled, configure the controller to use it. */ ble_hs_flow_startup(); diff --git a/src/nimble/nimble/host/src/ble_hs_stop.c b/src/nimble/nimble/host/src/ble_hs_stop.c index e93af773..6f2c8871 100644 --- a/src/nimble/nimble/host/src/ble_hs_stop.c +++ b/src/nimble/nimble/host/src/ble_hs_stop.c @@ -21,7 +21,7 @@ #include "nimble/porting/nimble/include/sysinit/sysinit.h" #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "ble_hs_priv.h" -#include "../include/host/ble_hs_stop.h" +#include "nimble/nimble/host/include/host/ble_hs_stop.h" #include "nimble/nimble/include/nimble/nimble_npl.h" #ifndef MYNEWT #include "nimble/porting/nimble/include/nimble/nimble_port.h" diff --git a/src/nimble/nimble/host/src/ble_l2cap.c b/src/nimble/nimble/host/src/ble_l2cap.c index e41452fc..ca062d24 100644 --- a/src/nimble/nimble/host/src/ble_l2cap.c +++ b/src/nimble/nimble/host/src/ble_l2cap.c @@ -21,7 +21,7 @@ #include #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/porting/nimble/include/os/os.h" -#include "../include/host/ble_l2cap.h" +#include "nimble/nimble/host/include/host/ble_l2cap.h" #include "nimble/nimble/include/nimble/ble.h" #include "nimble/nimble/include/nimble/hci_common.h" #include "ble_hs_priv.h" @@ -208,7 +208,29 @@ ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu } } - return ble_l2cap_sig_coc_reconfig(conn_handle, chans, num, new_mtu); + return ble_l2cap_sig_coc_reconfig(conn_handle, chans, num, new_mtu, MYNEWT_VAL(BLE_L2CAP_COC_MPS)); +} + +int +ble_l2cap_reconfig_mtu_mps(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu, uint16_t new_mps) +{ + int i; + uint16_t conn_handle; + + if (num == 0 || !chans) { + return BLE_HS_EINVAL; + } + + conn_handle = chans[0]->conn_handle; + + for (i = 1; i < num; i++) { + if (conn_handle != chans[i]->conn_handle) { + BLE_HS_LOG(ERROR, "All channels should have same conn handle\n"); + return BLE_HS_EINVAL; + } + } + + return ble_l2cap_sig_coc_reconfig(conn_handle, chans, num, new_mtu, new_mps); } int @@ -331,10 +353,6 @@ ble_l2cap_get_mtu(struct ble_l2cap_chan *chan) * pointer to the appropriate handler gets * written here. The caller should pass the * receive buffer to this callback. - * @param out_rx_buf If a full L2CAP packet has been received, this - * will point to the entire L2CAP packet. To - * process the packet, pass this buffer to the - * receive handler (out_rx_cb). * @param out_reject_cid Indicates whether an L2CAP Command Reject * command should be sent. If this equals -1, * no reject should get sent. Otherwise, the @@ -389,7 +407,7 @@ ble_l2cap_rx(struct ble_hs_conn *conn, } /* For CIDs from dynamic range we check if SDU size isn't larger than MPS */ - if (chan->dcid >= 0x0040 && chan->dcid <= 0x007F && l2cap_hdr.len > chan->my_coc_mps) { + if (chan->dcid >= 0x0040 && chan->dcid <= 0x007F && l2cap_hdr.len > (chan->my_coc_mps + BLE_L2CAP_SDU_SZ)) { /* Data exceeds MPS */ BLE_HS_LOG(ERROR, "error: sdu_len > chan->my_coc_mps (%d>%d)\n", l2cap_hdr.len, chan->my_coc_mps); @@ -403,7 +421,7 @@ ble_l2cap_rx(struct ble_hs_conn *conn, ble_l2cap_remove_rx(conn, chan); } - if (l2cap_hdr.len > ble_l2cap_get_mtu(chan)) { + if (l2cap_hdr.len - BLE_L2CAP_SDU_SZ > ble_l2cap_get_mtu(chan)) { /* More data than we expected on the channel. * Disconnect peer with invalid behaviour */ diff --git a/src/nimble/nimble/host/src/ble_l2cap_coc.c b/src/nimble/nimble/host/src/ble_l2cap_coc.c index ec5ef1d7..bed64de6 100644 --- a/src/nimble/nimble/host/src/ble_l2cap_coc.c +++ b/src/nimble/nimble/host/src/ble_l2cap_coc.c @@ -35,7 +35,7 @@ static struct ble_l2cap_coc_srv_list ble_l2cap_coc_srvs; static os_membuf_t ble_l2cap_coc_srv_mem[ OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM), - sizeof (struct ble_l2cap_coc_srv)) + sizeof(struct ble_l2cap_coc_srv)) ]; static struct os_mempool ble_l2cap_coc_srv_pool; @@ -75,9 +75,9 @@ ble_l2cap_coc_srv_alloc(void) int ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, - ble_l2cap_event_fn *cb, void *cb_arg) + ble_l2cap_event_fn *cb, void *cb_arg) { - struct ble_l2cap_coc_srv * srv; + struct ble_l2cap_coc_srv *srv; srv = ble_l2cap_coc_srv_alloc(); if (!srv) { @@ -111,7 +111,7 @@ ble_l2cap_clear_used_cid(uint32_t *cid_mask, int bit) static inline int ble_l2cap_get_first_available_bit(uint32_t *cid_mask) { - int i; + unsigned int i; int bit = 0; for (i = 0; i < BLE_HS_CONN_L2CAP_COC_CID_MASK_LEN; i++) { @@ -121,7 +121,7 @@ ble_l2cap_get_first_available_bit(uint32_t *cid_mask) * a) If bit == 0 means all the bits are used * b) this function returns 1 + index */ - bit = __builtin_ffs(~(unsigned int)(cid_mask[i])); + bit = __builtin_ffs(~(unsigned int) (cid_mask[i])); if (bit != 0) { break; } @@ -156,8 +156,8 @@ ble_l2cap_coc_srv_find(uint16_t psm) srv = NULL; STAILQ_FOREACH(cur, &ble_l2cap_coc_srvs, next) { if (cur->psm == psm) { - srv = cur; - break; + srv = cur; + break; } } @@ -183,6 +183,7 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) { int rc; struct os_mbuf **om; + struct os_mbuf *rx_sdu; struct ble_l2cap_coc_endpoint *rx; uint16_t om_total; @@ -194,10 +195,13 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) rx = &chan->coc_rx; BLE_HS_DBG_ASSERT(rx != NULL); + rx_sdu = rx->sdus[chan->coc_rx.current_sdu_idx]; + BLE_HS_DBG_ASSERT(rx_sdu != NULL); + om_total = OS_MBUF_PKTLEN(*om); /* First LE frame */ - if (OS_MBUF_PKTLEN(rx->sdu) == 0) { + if (OS_MBUF_PKTLEN(rx_sdu) == 0) { uint16_t sdu_len; rc = ble_hs_mbuf_pullup_base(om, BLE_L2CAP_SDU_SIZE); @@ -207,12 +211,15 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) sdu_len = get_le16((*om)->om_data); + BLE_HS_LOG(DEBUG, "First LE frame received %d, SDU len: %d\n", + om_total, sdu_len + 2); + /* We should receive payload of size sdu_len + 2 bytes of sdu_len field */ if (om_total > sdu_len + 2) { BLE_HS_LOG(ERROR, "Payload larger than expected (%d>%d)\n", om_total, sdu_len + 2); /* Disconnect peer with invalid behaviour */ - rx->sdu = NULL; + rx_sdu = NULL; rx->data_offset = 0; ble_l2cap_disconnect(chan); return BLE_HS_EBADDATA; @@ -226,12 +233,13 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) return BLE_HS_EBADDATA; } - BLE_HS_LOG(DEBUG, "sdu_len=%d, received LE frame=%d, credits=%d\n", - sdu_len, om_total, rx->credits); + BLE_HS_LOG(DEBUG, + "sdu_len=%d, received LE frame=%d, credits=%d, current_sdu_idx=%d\n", + sdu_len, om_total, rx->credits, chan->coc_rx.current_sdu_idx); - os_mbuf_adj(*om , BLE_L2CAP_SDU_SIZE); + os_mbuf_adj(*om, BLE_L2CAP_SDU_SIZE); - rc = os_mbuf_appendfrom(rx->sdu, *om, 0, om_total - BLE_L2CAP_SDU_SIZE); + rc = os_mbuf_appendfrom(rx_sdu, *om, 0, om_total - BLE_L2CAP_SDU_SIZE); if (rc != 0) { /* FIXME: User shall give us big enough buffer. * need to handle it better @@ -246,16 +254,16 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) } else { BLE_HS_LOG(DEBUG, "Continuation...received %d\n", (*om)->om_len); - if (OS_MBUF_PKTLEN(rx->sdu) + (*om)->om_len > rx->data_offset) { + if (OS_MBUF_PKTLEN(rx_sdu) + (*om)->om_len > rx->data_offset) { /* Disconnect peer with invalid behaviour */ BLE_HS_LOG(ERROR, "Payload larger than expected (%d>%d)\n", - OS_MBUF_PKTLEN(rx->sdu) + (*om)->om_len, rx->data_offset); - rx->sdu = NULL; + OS_MBUF_PKTLEN(rx_sdu) + (*om)->om_len, rx->data_offset); + rx_sdu = NULL; rx->data_offset = 0; ble_l2cap_disconnect(chan); return BLE_HS_EBADDATA; } - rc = os_mbuf_appendfrom(rx->sdu, *om, 0, om_total); + rc = os_mbuf_appendfrom(rx_sdu, *om, 0, om_total); if (rc != 0) { /* FIXME: need to handle it better */ BLE_HS_LOG(DEBUG, "Could not append data rc=%d\n", rc); @@ -265,17 +273,19 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) rx->credits--; - if (OS_MBUF_PKTLEN(rx->sdu) == rx->data_offset) { - struct os_mbuf *sdu_rx = rx->sdu; + if (OS_MBUF_PKTLEN(rx_sdu) == rx->data_offset) { + struct os_mbuf *sdu_rx = rx_sdu; BLE_HS_LOG(DEBUG, "Received sdu_len=%d, credits left=%d\n", - OS_MBUF_PKTLEN(rx->sdu), rx->credits); + OS_MBUF_PKTLEN(rx_sdu), rx->credits); /* Lets get back control to os_mbuf to application. * Since it this callback application might want to set new sdu * we need to prepare space for this. Therefore we need sdu_rx */ - rx->sdu = NULL; + rx_sdu = NULL; + chan->coc_rx.current_sdu_idx = + (chan->coc_rx.current_sdu_idx + 1) % BLE_L2CAP_SDU_BUFF_CNT; rx->data_offset = 0; ble_l2cap_event_coc_received_data(chan, sdu_rx); @@ -288,7 +298,7 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) * However, we still have buffer to for next LE Frame so lets give one more * credit to peer so it can send us full SDU */ - if (rx->credits == 0) { + if (chan->disable_auto_credit_update == false && rx->credits == 0) { /* Remote did not send full SDU. Lets give him one more credits to do * so since we have still buffer to handle it */ @@ -296,14 +306,16 @@ ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan) ble_l2cap_sig_le_credits(chan->conn_handle, chan->scid, rx->credits); } - BLE_HS_LOG(DEBUG, "Received partial sdu_len=%d, credits left=%d\n", - OS_MBUF_PKTLEN(rx->sdu), rx->credits); + BLE_HS_LOG(DEBUG, + "Received partial sdu_len=%d, credits left=%d, current_sdu_idx=%d\n", + OS_MBUF_PKTLEN(rx_sdu), rx->credits, chan->coc_rx.current_sdu_idx); return 0; } void -ble_l2cap_coc_set_new_mtu_mps(struct ble_l2cap_chan *chan, uint16_t mtu, uint16_t mps) +ble_l2cap_coc_set_new_mtu_mps(struct ble_l2cap_chan *chan, uint16_t mtu, + uint16_t mps) { chan->my_coc_mps = mps; chan->coc_rx.mtu = mtu; @@ -332,7 +344,17 @@ ble_l2cap_coc_chan_alloc(struct ble_hs_conn *conn, uint16_t psm, uint16_t mtu, chan->my_coc_mps = MYNEWT_VAL(BLE_L2CAP_COC_MPS); chan->rx_fn = ble_l2cap_coc_rx_fn; chan->coc_rx.mtu = mtu; - chan->coc_rx.sdu = sdu_rx; + chan->coc_rx.sdus[0] = sdu_rx; + for (int i = 1; i < BLE_L2CAP_SDU_BUFF_CNT; i++) { + chan->coc_rx.sdus[i] = NULL; + } + chan->coc_rx.current_sdu_idx = 0; + + if (BLE_L2CAP_SDU_BUFF_CNT == 1) { + chan->coc_rx.next_sdu_alloc_idx = 0; + } else { + chan->coc_rx.next_sdu_alloc_idx = chan->coc_rx.sdus[0] == NULL ? 0 : 1; + } /* Number of credits should allow to send full SDU with on given * L2CAP MTU @@ -370,7 +392,7 @@ ble_l2cap_coc_create_srv_chan(struct ble_hs_conn *conn, uint16_t psm, static void ble_l2cap_event_coc_disconnected(struct ble_l2cap_chan *chan) { - struct ble_l2cap_event event = { }; + struct ble_l2cap_event event = {}; /* FIXME */ if (!chan->cb) { @@ -389,7 +411,7 @@ ble_l2cap_coc_cleanup_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan { /* PSM 0 is used for fixed channels. */ if (chan->psm == 0) { - return; + return; } ble_l2cap_event_coc_disconnected(chan); @@ -399,14 +421,16 @@ ble_l2cap_coc_cleanup_chan(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan chan->scid - BLE_L2CAP_COC_CID_START); } - os_mbuf_free_chain(chan->coc_rx.sdu); - os_mbuf_free_chain(chan->coc_tx.sdu); + for (int i = 0; i < BLE_L2CAP_SDU_BUFF_CNT; i++) { + os_mbuf_free_chain(chan->coc_rx.sdus[i]); + } + os_mbuf_free_chain(chan->coc_tx.sdus[0]); } static void ble_l2cap_event_coc_unstalled(struct ble_l2cap_chan *chan, int status) { - struct ble_l2cap_event event = { }; + struct ble_l2cap_event event = {}; if (!chan->cb) { return; @@ -435,7 +459,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan) /* If there is no data to send, just return success */ tx = &chan->coc_tx; - if (!tx->sdu) { + if (!tx->sdus[0]) { ble_hs_unlock(); return 0; } @@ -446,7 +470,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan) BLE_HS_LOG(DEBUG, "Available credits %d\n", tx->credits); /* lets calculate data we are going to send */ - left_to_send = OS_MBUF_PKTLEN(tx->sdu) - tx->data_offset; + left_to_send = OS_MBUF_PKTLEN(tx->sdus[0]) - tx->data_offset; if (tx->data_offset == 0) { sdu_size_offset = BLE_L2CAP_SDU_SIZE; @@ -466,9 +490,10 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan) if (tx->data_offset == 0) { /* First packet needs SDU len first. Left to send */ - uint16_t l = htole16(OS_MBUF_PKTLEN(tx->sdu)); + uint16_t l = htole16(OS_MBUF_PKTLEN(tx->sdus[0])); - BLE_HS_LOG(DEBUG, "Sending SDU len=%d\n", OS_MBUF_PKTLEN(tx->sdu)); + BLE_HS_LOG(DEBUG, "Sending SDU len=%d\n", + OS_MBUF_PKTLEN(tx->sdus[0])); rc = os_mbuf_append(txom, &l, sizeof(uint16_t)); if (rc) { rc = BLE_HS_ENOMEM; @@ -481,7 +506,7 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan) * that for first packet we need to decrease data size by 2 bytes for sdu * size */ - rc = os_mbuf_appendfrom(txom, tx->sdu, tx->data_offset, + rc = os_mbuf_appendfrom(txom, tx->sdus[0], tx->data_offset, len - sdu_size_offset); if (rc) { rc = BLE_HS_ENOMEM; @@ -502,18 +527,19 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan) } BLE_HS_LOG(DEBUG, "Sent %d bytes, credits=%d, to send %d bytes \n", - len, tx->credits, OS_MBUF_PKTLEN(tx->sdu)- tx->data_offset); + len, tx->credits, + OS_MBUF_PKTLEN(tx->sdus[0]) - tx->data_offset); - if (tx->data_offset == OS_MBUF_PKTLEN(tx->sdu)) { + if (tx->data_offset == OS_MBUF_PKTLEN(tx->sdus[0])) { BLE_HS_LOG(DEBUG, "Complete package sent\n"); - os_mbuf_free_chain(tx->sdu); - tx->sdu = NULL; + os_mbuf_free_chain(tx->sdus[0]); + tx->sdus[0] = NULL; tx->data_offset = 0; break; } } - if (tx->sdu) { + if (tx->sdus[0]) { /* Not complete SDU sent, wait for credits */ tx->flags |= BLE_L2CAP_COC_FLAG_STALLED; ble_hs_unlock(); @@ -531,8 +557,8 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan) return 0; failed: - os_mbuf_free_chain(tx->sdu); - tx->sdu = NULL; + os_mbuf_free_chain(tx->sdus[0]); + tx->sdus[0] = NULL; os_mbuf_free_chain(txom); if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) { @@ -590,7 +616,15 @@ ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx) return BLE_HS_EINVAL; } - chan->coc_rx.sdu = sdu_rx; + if (chan->coc_rx.sdus[0] != NULL && + chan->coc_rx.next_sdu_alloc_idx == chan->coc_rx.current_sdu_idx && + BLE_L2CAP_SDU_BUFF_CNT != 1) { + return BLE_HS_EBUSY; + } + + chan->coc_rx.sdus[chan->coc_rx.next_sdu_alloc_idx] = sdu_rx; + chan->coc_rx.next_sdu_alloc_idx = + (chan->coc_rx.next_sdu_alloc_idx + 1) % BLE_L2CAP_SDU_BUFF_CNT; ble_hs_lock(); conn = ble_hs_conn_find_assert(chan->conn_handle); @@ -603,7 +637,7 @@ ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx) /* We want to back only that much credits which remote side is missing * to be able to send complete SDU. */ - if (chan->coc_rx.credits < c->initial_credits) { + if (chan->disable_auto_credit_update == false && chan->coc_rx.credits < c->initial_credits) { ble_hs_unlock(); ble_l2cap_sig_le_credits(chan->conn_handle, chan->scid, c->initial_credits - chan->coc_rx.credits); @@ -633,11 +667,11 @@ ble_l2cap_coc_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx) } ble_hs_lock(); - if (tx->sdu) { + if (tx->sdus[0]) { ble_hs_unlock(); return BLE_HS_EBUSY; } - tx->sdu = sdu_tx; + tx->sdus[0] = sdu_tx; /* leave the host locked on purpose when ble_l2cap_coc_continue_tx() */ @@ -650,10 +684,10 @@ ble_l2cap_coc_init(void) STAILQ_INIT(&ble_l2cap_coc_srvs); return os_mempool_init(&ble_l2cap_coc_srv_pool, - MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM), - sizeof (struct ble_l2cap_coc_srv), - ble_l2cap_coc_srv_mem, - "ble_l2cap_coc_srv_pool"); + MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM), + sizeof(struct ble_l2cap_coc_srv), + ble_l2cap_coc_srv_mem, + "ble_l2cap_coc_srv_pool"); } #endif diff --git a/src/nimble/nimble/host/src/ble_l2cap_coc_priv.h b/src/nimble/nimble/host/src/ble_l2cap_coc_priv.h index 911946e0..719003e3 100644 --- a/src/nimble/nimble/host/src/ble_l2cap_coc_priv.h +++ b/src/nimble/nimble/host/src/ble_l2cap_coc_priv.h @@ -37,8 +37,14 @@ struct ble_l2cap_chan; #define BLE_L2CAP_COC_FLAG_STALLED 0x01 +#define BLE_L2CAP_SDU_BUFF_CNT (MYNEWT_VAL(BLE_L2CAP_COC_SDU_BUFF_COUNT)) + struct ble_l2cap_coc_endpoint { - struct os_mbuf *sdu; + struct os_mbuf *sdus[BLE_L2CAP_SDU_BUFF_CNT]; + /* Index for currently used sdu from sdus */ + uint16_t current_sdu_idx; + /* Index indicating free sdus slot to allocate next sdu */ + uint16_t next_sdu_alloc_idx; uint16_t mtu; uint16_t credits; uint16_t data_offset; diff --git a/src/nimble/nimble/host/src/ble_l2cap_priv.h b/src/nimble/nimble/host/src/ble_l2cap_priv.h index 838014d7..138476f0 100644 --- a/src/nimble/nimble/host/src/ble_l2cap_priv.h +++ b/src/nimble/nimble/host/src/ble_l2cap_priv.h @@ -55,6 +55,7 @@ extern struct os_mempool ble_l2cap_chan_pool; #define BLE_L2CAP_CID_BLACK_HOLE 0xffff #define BLE_L2CAP_HDR_SZ 4 +#define BLE_L2CAP_SDU_SZ 2 typedef uint8_t ble_l2cap_chan_flags; @@ -91,6 +92,19 @@ struct ble_l2cap_chan { struct ble_l2cap_coc_endpoint coc_rx; struct ble_l2cap_coc_endpoint coc_tx; uint16_t initial_credits; +/** + * Disable automatically sending credits to a remote + * + * This field disables automatically sending extra credit to a + * remote that has exhausted all of its available credits. + * Setting this field to "true" will enable behaviour to + * "not automatically send credits to a peer whose credits are exhausted" + * Setting this field to "false" will enable behaviour to + * "automatically send credits to a peer whose credits are exhausted" + * this behaviour. + * + */ + bool disable_auto_credit_update; ble_l2cap_event_fn *cb; void *cb_arg; #endif @@ -137,6 +151,7 @@ int ble_l2cap_enhanced_connect(uint16_t conn_handle, uint8_t num, struct os_mbuf *sdu_rx[], ble_l2cap_event_fn *cb, void *cb_arg); int ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu); +int ble_l2cap_reconfig_mtu_mps(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu, uint16_t new_mps); #ifdef __cplusplus } diff --git a/src/nimble/nimble/host/src/ble_l2cap_sig.c b/src/nimble/nimble/host/src/ble_l2cap_sig.c index de5c8a98..b37b7831 100644 --- a/src/nimble/nimble/host/src/ble_l2cap_sig.c +++ b/src/nimble/nimble/host/src/ble_l2cap_sig.c @@ -795,14 +795,14 @@ ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle, } if (hdr->length <= sizeof(*req)) { - rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM); + rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCEPTED_PARAM); goto failed; } req = (struct ble_l2cap_sig_credit_base_reconfig_req *)(*om)->om_data; if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) { - rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM); + rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCEPTED_PARAM); goto failed; } @@ -811,7 +811,7 @@ ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle, cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t); if (cid_cnt > BLE_L2CAP_MAX_COC_CONN_REQ) { - rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM); + rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCEPTED_PARAM); goto failed; } @@ -1493,7 +1493,7 @@ ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, int ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], - uint8_t num, uint16_t new_mtu) + uint8_t num, uint16_t new_mtu, uint16_t new_mps) { struct ble_hs_conn *conn; struct ble_l2cap_sig_proc *proc; @@ -1529,7 +1529,7 @@ ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], proc->op = BLE_L2CAP_SIG_PROC_OP_RECONFIG; proc->reconfig.cid_cnt = num; proc->reconfig.new_mtu = new_mtu; - proc->reconfig.new_mps = MYNEWT_VAL(BLE_L2CAP_COC_MPS); + proc->reconfig.new_mps = new_mps; proc->id = ble_l2cap_sig_next_id(); proc->conn_handle = conn_handle; diff --git a/src/nimble/nimble/host/src/ble_l2cap_sig_priv.h b/src/nimble/nimble/host/src/ble_l2cap_sig_priv.h index a0e2e58c..6b8addfd 100644 --- a/src/nimble/nimble/host/src/ble_l2cap_sig_priv.h +++ b/src/nimble/nimble/host/src/ble_l2cap_sig_priv.h @@ -154,7 +154,7 @@ int ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, uint8_t num, struct os_mbuf *sdu_rx[], ble_l2cap_event_fn *cb, void *cb_arg); int ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], - uint8_t num, uint16_t new_mtu); + uint8_t num, uint16_t new_mtu, uint16_t new_mps); #else static inline int ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, @@ -166,7 +166,7 @@ ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, } static inline int ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, struct ble_l2cap_chan *chans[], - uint8_t num, uint16_t new_mtu) + uint8_t num, uint16_t new_mtu, uint16_t new_mps) { return BLE_HS_ENOTSUP; } diff --git a/src/nimble/nimble/host/src/ble_sm.c b/src/nimble/nimble/host/src/ble_sm.c index 445879b5..6c036c17 100644 --- a/src/nimble/nimble/host/src/ble_sm.c +++ b/src/nimble/nimble/host/src/ble_sm.c @@ -48,7 +48,7 @@ #include "nimble/nimble/host/include/host/ble_sm.h" #include "ble_hs_priv.h" #include "ble_hs_resolv_priv.h" -#include "../store/config/src/ble_store_config_priv.h" +#include "nimble/nimble/host/store/config/src/ble_store_config_priv.h" #if NIMBLE_BLE_CONNECT @@ -557,11 +557,12 @@ ble_sm_persist_keys(struct ble_sm_proc *proc) switch (peer_addr.type) { case BLE_ADDR_PUBLIC: case BLE_ADDR_PUBLIC_ID: - conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC_ID; #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) /* In case of Host based privacy, we should not be changing * peer address type to BLE_ADDR_PUBLIC_ID */ conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC; +#else + conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC_ID; #endif break; @@ -602,7 +603,8 @@ ble_sm_persist_keys(struct ble_sm_proc *proc) ble_hs_unlock(); if (identity_ev) { - ble_gap_identity_event(proc->conn_handle); + /* Use peer_addr since it does have proper addr type (i.e. 0/1, not 2/3) */ + ble_gap_identity_event(proc->conn_handle, &peer_addr); } authenticated = proc->flags & BLE_SM_PROC_F_AUTHENTICATED; @@ -945,7 +947,8 @@ ble_sm_chk_repeat_pairing(uint16_t conn_handle, } void -ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res) +ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res, + bool tx_fail) { struct ble_sm_proc *prev; struct ble_sm_proc *proc; @@ -972,7 +975,7 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res) &prev); if (proc != NULL) { - if (res->execute) { + if (res && res->execute) { ble_sm_exec(proc, res, res->state_arg); } @@ -991,7 +994,7 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res) } } - if (res->sm_err != 0) { + if (res && (res->sm_err != 0) && tx_fail) { ble_sm_pair_fail_tx(conn_handle, res->sm_err); } @@ -1001,20 +1004,32 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res) break; } - if (res->app_status == 518 ) { - conn = ble_hs_conn_find(conn_handle); + if (res->app_status == 518 ) { + conn = ble_hs_conn_find(conn_handle); conn_flags = conn->bhc_flags; ble_sm_proc_free(proc); - if (conn_flags & BLE_HS_CONN_F_MASTER) { - ble_sm_pair_initiate(conn_handle); - } - else { - ble_sm_slave_initiate(conn_handle); + if (conn_flags & BLE_HS_CONN_F_MASTER) { + ble_sm_pair_initiate(conn_handle); + } else { + ble_sm_slave_initiate(conn_handle); } - break; + break; + } + + if (res->enc_cb && + res->app_status != BLE_HS_ENOTCONN) { + /* Do not send this event on broken connection */ + ble_gap_pairing_complete_event(conn_handle, res->sm_err); + } + /* Persist keys if bonding has successfully completed. */ + if (res->app_status == 0 && + rm && + proc->flags & BLE_SM_PROC_F_BONDING) { + + ble_sm_persist_keys(proc); } if (res->enc_cb) { @@ -1028,13 +1043,6 @@ ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res) ble_gap_passkey_event(conn_handle, &res->passkey_params); } - /* Persist keys if bonding has successfully completed. */ - if (res->app_status == 0 && - rm && - proc->flags & BLE_SM_PROC_F_BONDING) { - - ble_sm_persist_keys(proc); - } if (rm) { ble_sm_proc_free(proc); @@ -1272,7 +1280,7 @@ ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted) ble_hs_unlock(); res.bonded = bonded; - ble_sm_process_result(conn_handle, &res); + ble_sm_process_result(conn_handle, &res, true); } void @@ -1302,15 +1310,15 @@ ble_sm_retrieve_ltk(uint16_t ediv, uint64_t rand, uint8_t peer_addr_type, struct ble_store_key_sec key_sec; int rc; - /* Tell applicaiton to look up LTK by peer address and ediv/rand pair. */ + /* Tell application to look up LTK by peer address and ediv/rand pair. */ memset(&key_sec, 0, sizeof key_sec); key_sec.peer_addr.type = peer_addr_type; memcpy(key_sec.peer_addr.val, peer_addr, 6); - key_sec.ediv = ediv; - key_sec.rand_num = rand; - key_sec.ediv_rand_present = 1; rc = ble_store_read_our_sec(&key_sec, value_sec); + if (value_sec->ediv != ediv || value_sec->rand_num != rand) { + return BLE_HS_ENOENT; + } return rc; } @@ -1493,7 +1501,7 @@ ble_sm_ltk_req_rx(const struct ble_hci_ev_le_subev_lt_key_req *ev) } } - ble_sm_process_result(conn_handle, &res); + ble_sm_process_result(conn_handle, &res, true); return 0; } @@ -1827,10 +1835,10 @@ ble_sm_verify_auth_requirements(uint8_t cmd) return false; } } - /* Fail if Secure Connections level forces MITM protection and remote does not + /* Fail if security level forces MITM protection and remote does not * support it */ - if (MYNEWT_VAL(BLE_SM_SC_LVL) >= 3 && !(cmd & BLE_SM_PAIR_AUTHREQ_MITM)) { + if (MYNEWT_VAL(BLE_SM_LVL) >= 3 && !(cmd & BLE_SM_PAIR_AUTHREQ_MITM)) { return false; } return true; @@ -1914,7 +1922,7 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om, if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) { res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP); - } else if (MYNEWT_VAL(BLE_SM_SC_LVL) == 1) { + } else if (MYNEWT_VAL(BLE_SM_LVL) == 1) { res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP); } else if (req->max_enc_key_size < BLE_SM_PAIR_KEY_SZ_MIN) { @@ -1923,12 +1931,18 @@ ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om, } else if (req->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { res->sm_err = BLE_SM_ERR_INVAL; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); - } else if (MYNEWT_VAL(BLE_SM_SC_ONLY) && (req->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX)) { - /* Fail if Secure Connections Only mode is on and remote does not meet - * key size requirements - MITM was checked in last step - */ + } else if (ble_hs_cfg.sm_sc_only && !(req->authreq & BLE_SM_PAIR_AUTHREQ_SC)) { + /* Fail if Secure Connections Only mode is on and SC is not supported by peer + */ + res->sm_err = BLE_SM_ERR_AUTHREQ; + res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ); + res->enc_cb = 1; + } else if (ble_hs_cfg.sm_sc_only && (req->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX)) { + /* Fail if Secure Connections Only mode is on and key size is too small + */ res->sm_err = BLE_SM_ERR_ENC_KEY_SZ; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ); + res->enc_cb = 1; } else if (!ble_sm_verify_auth_requirements(req->authreq)) { res->sm_err = BLE_SM_ERR_AUTHREQ; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ); @@ -1992,7 +2006,7 @@ ble_sm_pair_rsp_rx(uint16_t conn_handle, struct os_mbuf **om, } else if (rsp->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) { res->sm_err = BLE_SM_ERR_INVAL; res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL); - } else if (MYNEWT_VAL(BLE_SM_SC_ONLY) && (rsp->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX)) { + } else if (ble_hs_cfg.sm_sc_only && (rsp->max_enc_key_size != BLE_SM_PAIR_KEY_SZ_MAX)) { /* Fail if Secure Connections Only mode is on and remote does not meet * key size requirements - MITM was checked in last step */ @@ -2161,6 +2175,7 @@ ble_sm_key_exch_success(struct ble_sm_proc *proc, struct ble_sm_result *res) res->app_status = 0; res->enc_cb = 1; res->bonded = bonded; + res->sm_err = BLE_SM_ERR_SUCCESS; } static void @@ -2179,6 +2194,8 @@ ble_sm_key_exch_exec(struct ble_sm_proc *proc, struct ble_sm_result *res, uint8_t our_key_dist; struct os_mbuf *txom; const uint8_t *irk; + struct ble_store_gen_key gen_key; + int ltk_gen = 0; int rc; ble_sm_key_dist(proc, &init_key_dist, &resp_key_dist); @@ -2196,15 +2213,37 @@ ble_sm_key_exch_exec(struct ble_sm_proc *proc, struct ble_sm_result *res, goto err; } - rc = ble_sm_gen_ltk(proc, enc_info->ltk); - if (rc != 0) { - os_mbuf_free_chain(txom); - goto err; + proc->our_keys.key_size = proc->key_size; + + if (ble_hs_cfg.store_gen_key_cb) { + memset(&gen_key, 0, sizeof(gen_key)); + rc = ble_hs_cfg.store_gen_key_cb(BLE_STORE_GEN_KEY_LTK, &gen_key, + proc->conn_handle); + if (rc == 0) { + /* Trim LRK to keysize */ + memset(gen_key.ltk_periph + proc->key_size, 0, + 16 - proc->key_size); + + proc->our_keys.ediv = gen_key.ediv; + proc->our_keys.rand_val = gen_key.rand; + memcpy(proc->our_keys.ltk, gen_key.ltk_periph, 16); + + ltk_gen = 1; + } } - /* store LTK before sending since ble_sm_tx consumes tx mbuf */ - memcpy(proc->our_keys.ltk, enc_info->ltk, 16); - proc->our_keys.key_size = proc->key_size; + if (!ltk_gen) { + rc = ble_sm_gen_ltk(proc, enc_info->ltk); + if (rc != 0) { + os_mbuf_free_chain(txom); + goto err; + } + + /* store LTK before sending since ble_sm_tx consumes tx mbuf */ + memcpy(proc->our_keys.ltk, enc_info->ltk, 16); + } else { + memcpy(enc_info->ltk, proc->our_keys.ltk, 16); + } proc->our_keys.ltk_valid = 1; rc = ble_sm_tx(proc->conn_handle, txom); @@ -2220,20 +2259,25 @@ ble_sm_key_exch_exec(struct ble_sm_proc *proc, struct ble_sm_result *res, goto err; } - rc = ble_sm_gen_ediv(master_id); - if (rc != 0) { - os_mbuf_free_chain(txom); - goto err; - } - rc = ble_sm_gen_master_id_rand(master_id); - if (rc != 0) { - os_mbuf_free_chain(txom); - goto err; - } + if (!ltk_gen) { + rc = ble_sm_gen_ediv(master_id); + if (rc != 0) { + os_mbuf_free_chain(txom); + goto err; + } + rc = ble_sm_gen_master_id_rand(master_id); + if (rc != 0) { + os_mbuf_free_chain(txom); + goto err; + } + proc->our_keys.rand_val = master_id->rand_val; + proc->our_keys.ediv = master_id->ediv; + } else { + master_id->ediv = proc->our_keys.ediv; + master_id->rand_val = proc->our_keys.rand_val; + } proc->our_keys.ediv_rand_valid = 1; - proc->our_keys.rand_val = master_id->rand_val; - proc->our_keys.ediv = master_id->ediv; rc = ble_sm_tx(proc->conn_handle, txom); if (rc != 0) { @@ -2311,12 +2355,28 @@ ble_sm_key_exch_exec(struct ble_sm_proc *proc, struct ble_sm_result *res, goto err; } - rc = ble_sm_gen_csrk(proc, sign_info->sig_key); - if (rc != 0) { - os_mbuf_free_chain(txom); - goto err; + if (ble_hs_cfg.store_gen_key_cb) { + memset(&gen_key, 0, sizeof(gen_key)); + rc = ble_hs_cfg.store_gen_key_cb(BLE_STORE_GEN_KEY_CSRK, &gen_key, + proc->conn_handle); + if (rc == 0) { + memcpy(proc->our_keys.csrk, gen_key.csrk, 16); + } + } else { + rc = -1; } + if (rc != 0) { + rc = ble_sm_gen_csrk(proc, sign_info->sig_key); + if (rc != 0) { + os_mbuf_free_chain(txom); + goto err; + } + + memcpy(proc->our_keys.csrk, sign_info->sig_key, 16); + } else { + memcpy(sign_info->sig_key, proc->our_keys.csrk, 16); + } proc->our_keys.csrk_valid = 1; proc->our_keys.sign_counter = 0; memcpy(proc->our_keys.csrk, sign_info->sig_key, 16); @@ -2571,6 +2631,7 @@ ble_sm_fail_rx(uint16_t conn_handle, struct os_mbuf **om, cmd = (struct ble_sm_pair_fail *)(*om)->om_data; res->app_status = BLE_HS_SM_PEER_ERR(cmd->reason); + res->sm_err = cmd->reason; } } @@ -2590,42 +2651,42 @@ ble_sm_fail_rx(uint16_t conn_handle, struct os_mbuf **om, int ble_sm_incr_our_sign_counter(uint16_t conn_handle) { - struct ble_store_key_sec key_sec; - struct ble_store_value_sec value_sec; - struct ble_gap_conn_desc desc; - int rc; + struct ble_store_key_sec key_sec; + struct ble_store_value_sec value_sec; + struct ble_gap_conn_desc desc; + int rc; - rc = ble_gap_conn_find(conn_handle, &desc); - if (rc != 0) { - return rc; - } + rc = ble_gap_conn_find(conn_handle, &desc); + if (rc != 0) { + return rc; + } - memset(&key_sec, 0, sizeof key_sec); - key_sec.peer_addr = desc.peer_id_addr; + memset(&key_sec, 0, sizeof key_sec); + key_sec.peer_addr = desc.peer_id_addr; - rc = ble_store_read_our_sec(&key_sec, &value_sec); - if (rc != 0) { - return rc; - } - if (value_sec.csrk_present != 1) { - return BLE_HS_ENOENT; - } - if (value_sec.sign_counter == (uint32_t)0xffffffff) { - return BLE_HS_ENOMEM; - } + rc = ble_store_read_our_sec(&key_sec, &value_sec); + if (rc != 0) { + return rc; + } + if (value_sec.csrk_present != 1) { + return BLE_HS_ENOENT; + } + if (value_sec.sign_counter == (uint32_t)0xffffffff) { + return BLE_HS_ENOMEM; + } - rc = ble_store_delete_our_sec(&key_sec); - if (rc != 0) { - return rc; - } + rc = ble_store_delete_our_sec(&key_sec); + if (rc != 0) { + return rc; + } - value_sec.sign_counter += 1; - rc = ble_store_write_our_sec(&value_sec); - if (rc != 0) { - return rc; - } + value_sec.sign_counter += 1; + rc = ble_store_write_our_sec(&value_sec); + if (rc != 0) { + return rc; + } - return 0; + return 0; } /** @@ -2640,42 +2701,48 @@ ble_sm_incr_our_sign_counter(uint16_t conn_handle) int ble_sm_incr_peer_sign_counter(uint16_t conn_handle) { - struct ble_store_key_sec key_sec; - struct ble_store_value_sec value_sec; - struct ble_gap_conn_desc desc; - int rc; + struct ble_store_key_sec key_sec; + struct ble_store_value_sec value_sec; + struct ble_gap_conn_desc desc; + int rc; - rc = ble_gap_conn_find(conn_handle, &desc); - if (rc != 0) { - return rc; - } + rc = ble_gap_conn_find(conn_handle, &desc); + if (rc != 0) { + return rc; + } - memset(&key_sec, 0, sizeof key_sec); - key_sec.peer_addr = desc.peer_id_addr; + memset(&key_sec, 0, sizeof key_sec); + key_sec.peer_addr = desc.peer_id_addr; - rc = ble_store_read_peer_sec(&key_sec, &value_sec); - if (rc != 0) { - return rc; - } - if (value_sec.csrk_present != 1) { - return BLE_HS_ENOENT; - } - if (value_sec.sign_counter == (uint32_t)0xffffffff) { - return BLE_HS_ENOMEM; - } + rc = ble_store_read_peer_sec(&key_sec, &value_sec); + if (rc != 0) { + return rc; + } + if (value_sec.csrk_present != 1) { + return BLE_HS_ENOENT; + } + if (value_sec.sign_counter == (uint32_t)0xffffffff) { + return BLE_HS_ENOMEM; + } + + rc = ble_store_delete_peer_sec(&key_sec); + if (rc != 0) { + return rc; + } - rc = ble_store_delete_peer_sec(&key_sec); - if (rc != 0) { - return rc; - } + if (value_sec.irk_present == 1) { + ble_hs_pvcy_remove_entry(value_sec.peer_addr.type, value_sec.peer_addr.val); + // No need to check if the above command fails or passes + // Proceed with trying to write the new sign counter + } - value_sec.sign_counter += 1; - rc = ble_store_write_peer_sec(&value_sec); - if (rc != 0) { - return rc; - } + value_sec.sign_counter += 1; + rc = ble_store_write_peer_sec(&value_sec); + if (rc != 0) { + return rc; + } - return 0; + return 0; } /** @@ -2758,7 +2825,7 @@ ble_sm_pair_initiate(uint16_t conn_handle) } if (proc != NULL) { - ble_sm_process_result(conn_handle, &res); + ble_sm_process_result(conn_handle, &res, true); } return res.app_status; @@ -2797,7 +2864,7 @@ ble_sm_slave_initiate(uint16_t conn_handle) ble_hs_unlock(); if (proc != NULL) { - ble_sm_process_result(conn_handle, &res); + ble_sm_process_result(conn_handle, &res, true); } return res.app_status; @@ -2851,7 +2918,7 @@ ble_sm_enc_initiate(uint16_t conn_handle, uint8_t key_size, ble_hs_unlock(); - ble_sm_process_result(conn_handle, &res); + ble_sm_process_result(conn_handle, &res, true); return res.app_status; } @@ -2889,7 +2956,8 @@ ble_sm_rx(struct ble_l2cap_chan *chan) memset(&res, 0, sizeof res); rx_cb(conn_handle, om, &res); - ble_sm_process_result(conn_handle, &res); + ble_sm_process_result(conn_handle, &res, op == BLE_SM_OP_PAIR_FAIL ? + false : true); rc = res.app_status; } else { rc = BLE_HS_ENOTSUP; @@ -3001,7 +3069,7 @@ ble_sm_inject_io(uint16_t conn_handle, struct ble_sm_io *pkey) return rc; } - ble_sm_process_result(conn_handle, &res); + ble_sm_process_result(conn_handle, &res, true); return res.app_status; } @@ -3014,7 +3082,7 @@ ble_sm_connection_broken(uint16_t conn_handle) res.app_status = BLE_HS_ENOTCONN; res.enc_cb = 1; - ble_sm_process_result(conn_handle, &res); + ble_sm_process_result(conn_handle, &res, true); } int diff --git a/src/nimble/nimble/host/src/ble_sm_alg.c b/src/nimble/nimble/host/src/ble_sm_alg.c index 496f08e4..99a1cda4 100644 --- a/src/nimble/nimble/host/src/ble_sm_alg.c +++ b/src/nimble/nimble/host/src/ble_sm_alg.c @@ -30,7 +30,7 @@ #include "ble_hs_priv.h" #if MYNEWT_VAL(BLE_CRYPTO_STACK_MBEDTLS) -#include "mbedtls/aes.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" #if MYNEWT_VAL(BLE_SM_SC) #include "mbedtls/cipher.h" @@ -45,9 +45,9 @@ #include "nimble/ext/tinycrypt/include/tinycrypt/aes.h" #include "nimble/ext/tinycrypt/include/tinycrypt/constants.h" #include "nimble/ext/tinycrypt/include/tinycrypt/utils.h" +#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" #if MYNEWT_VAL(BLE_SM_SC) -#include "nimble/ext/tinycrypt/include/tinycrypt/cmac_mode.h" #include "nimble/ext/tinycrypt/include/tinycrypt/ecc_dh.h" #if MYNEWT_VAL(TRNG) #include "trng/trng.h" @@ -240,16 +240,6 @@ ble_sm_alg_c1(const uint8_t *k, const uint8_t *r, return rc; } -#if MYNEWT_VAL(BLE_SM_SC) - -static void -ble_sm_alg_log_buf(const char *name, const uint8_t *buf, int len) -{ - BLE_HS_LOG(DEBUG, " %s=", name); - ble_hs_log_flat_buf(buf, len); - BLE_HS_LOG(DEBUG, "\n"); -} - /** * Cypher based Message Authentication Code (CMAC) with AES 128 bit * @@ -321,6 +311,16 @@ ble_sm_alg_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len, } #endif +#if MYNEWT_VAL(BLE_SM_SC) + +static void +ble_sm_alg_log_buf(const char *name, const uint8_t *buf, int len) +{ + BLE_HS_LOG(DEBUG, " %s=", name); + ble_hs_log_flat_buf(buf, len); + BLE_HS_LOG(DEBUG, "\n"); +} + int ble_sm_alg_f4(const uint8_t *u, const uint8_t *v, const uint8_t *x, uint8_t z, uint8_t *out_enc_data) @@ -510,7 +510,7 @@ ble_sm_alg_g2(const uint8_t *u, const uint8_t *v, const uint8_t *x, ble_sm_alg_log_buf("res", xs, 16); *passkey = get_be32(xs + 12) % 1000000; - BLE_HS_LOG(DEBUG, " passkey=%" PRIu32"\n", *passkey); + BLE_HS_LOG(DEBUG, " passkey=%" PRIu32 "\n", *passkey); return 0; } @@ -598,11 +598,11 @@ ble_sm_alg_gen_dhkey(const uint8_t *peer_pub_key_x, const uint8_t *peer_pub_key_ } #else - if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) { + if (uECC_valid_public_key(pk, uECC_secp256r1()) < 0) { return BLE_HS_EUNKNOWN; } - rc = uECC_shared_secret(pk, priv, dh, &curve_secp256r1); + rc = uECC_shared_secret(pk, priv, dh, uECC_secp256r1()); if (rc == TC_CRYPTO_FAIL) { return BLE_HS_EUNKNOWN; } @@ -711,7 +711,7 @@ ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv) return BLE_HS_EUNKNOWN; } #else - if (uECC_make_key(pk, priv, &curve_secp256r1) != TC_CRYPTO_SUCCESS) { + if (uECC_make_key(pk, priv, uECC_secp256r1()) != TC_CRYPTO_SUCCESS) { return BLE_HS_EUNKNOWN; } #endif diff --git a/src/nimble/nimble/host/src/ble_sm_cmd.c b/src/nimble/nimble/host/src/ble_sm_cmd.c index 279375dc..92a28a14 100644 --- a/src/nimble/nimble/host/src/ble_sm_cmd.c +++ b/src/nimble/nimble/host/src/ble_sm_cmd.c @@ -29,18 +29,20 @@ void * ble_sm_cmd_get(uint8_t opcode, size_t len, struct os_mbuf **txom) { struct ble_sm_hdr *hdr; + void *data; *txom = ble_hs_mbuf_l2cap_pkt(); if (*txom == NULL) { return NULL; } - if (os_mbuf_extend(*txom, sizeof(*hdr) + len) == NULL) { + data = os_mbuf_extend(*txom, sizeof(*hdr) + len); + if (data == NULL) { os_mbuf_free_chain(*txom); return NULL; } - hdr = (struct ble_sm_hdr *)(*txom)->om_data; + hdr = (struct ble_sm_hdr *)data; hdr->opcode = opcode; diff --git a/src/nimble/nimble/host/src/ble_sm_priv.h b/src/nimble/nimble/host/src/ble_sm_priv.h index 261147a1..59fcc1e0 100644 --- a/src/nimble/nimble/host/src/ble_sm_priv.h +++ b/src/nimble/nimble/host/src/ble_sm_priv.h @@ -25,7 +25,7 @@ #include "nimble/porting/nimble/include/os/queue.h" #include "nimble/nimble/include/nimble/nimble_opt.h" #if MYNEWT_VAL(ENC_ADV_DATA) -#include "../include/host/ble_ead.h" +#include "nimble/nimble/host/include/host/ble_ead.h" #endif #ifdef __cplusplus @@ -386,7 +386,8 @@ uint8_t *ble_sm_our_pair_rand(struct ble_sm_proc *proc); uint8_t *ble_sm_peer_pair_rand(struct ble_sm_proc *proc); int ble_sm_ioact_state(uint8_t action); int ble_sm_proc_can_advance(struct ble_sm_proc *proc); -void ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res); +void ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res, + bool tx_fail); void ble_sm_confirm_advance(struct ble_sm_proc *proc); void ble_sm_ia_ra(struct ble_sm_proc *proc, uint8_t *out_iat, uint8_t *out_ia, diff --git a/src/nimble/nimble/host/src/ble_store.c b/src/nimble/nimble/host/src/ble_store.c index f6ceb3f0..4a343d37 100644 --- a/src/nimble/nimble/host/src/ble_store.c +++ b/src/nimble/nimble/host/src/ble_store.c @@ -285,6 +285,42 @@ ble_store_delete_cccd(const struct ble_store_key_cccd *key) return rc; } +int +ble_store_read_csfc(const struct ble_store_key_csfc *key, + struct ble_store_value_csfc *out_value) +{ + union ble_store_value *store_value; + union ble_store_key *store_key; + int rc; + + store_key = (void *)key; + store_value = (void *)out_value; + rc = ble_store_read(BLE_STORE_OBJ_TYPE_CSFC, store_key, store_value); + return rc; +} + +int +ble_store_write_csfc(const struct ble_store_value_csfc *value) +{ + union ble_store_value *store_value; + int rc; + + store_value = (void *)value; + rc = ble_store_write(BLE_STORE_OBJ_TYPE_CSFC, store_value); + return rc; +} + +int +ble_store_delete_csfc(const struct ble_store_key_csfc *key) +{ + union ble_store_key *store_key; + int rc; + + store_key = (void *)key; + rc = ble_store_delete(BLE_STORE_OBJ_TYPE_CSFC, store_key); + return rc; +} + void ble_store_key_from_value_cccd(struct ble_store_key_cccd *out_key, const struct ble_store_value_cccd *value) @@ -299,10 +335,6 @@ ble_store_key_from_value_sec(struct ble_store_key_sec *out_key, const struct ble_store_value_sec *value) { out_key->peer_addr = value->peer_addr; - - out_key->ediv = value->ediv; - out_key->rand_num = value->rand_num; - out_key->ediv_rand_present = 1; out_key->idx = 0; } @@ -440,6 +472,14 @@ ble_store_key_from_value_rpa_rec(struct ble_store_key_rpa_rec *out_key, out_key->idx = 0; } +void +ble_store_key_from_value_csfc(struct ble_store_key_csfc *out_key, + const struct ble_store_value_csfc *value) +{ + out_key->peer_addr = value->peer_addr; + out_key->idx = 0; +} + void ble_store_key_from_value(int obj_type, union ble_store_key *out_key, @@ -460,12 +500,17 @@ ble_store_key_from_value(int obj_type, break; #endif case BLE_STORE_OBJ_TYPE_PEER_ADDR: - ble_store_key_from_value_rpa_rec(&out_key->rpa_rec, &value->rpa_rec); - break; + ble_store_key_from_value_rpa_rec(&out_key->rpa_rec, &value->rpa_rec); + break; - case BLE_STORE_OBJ_TYPE_LOCAL_IRK: + case BLE_STORE_OBJ_TYPE_LOCAL_IRK: ble_store_key_from_value_local_irk(&out_key->local_irk, &value->local_irk); - break; + break; + + case BLE_STORE_OBJ_TYPE_CSFC: + ble_store_key_from_value_csfc(&out_key->csfc, &value->csfc); + break; + default: BLE_HS_DBG_ASSERT(0); @@ -487,33 +532,36 @@ ble_store_iterate(int obj_type, /* a magic value to retrieve anything */ memset(&key, 0, sizeof(key)); switch(obj_type) { - case BLE_STORE_OBJ_TYPE_PEER_SEC: - case BLE_STORE_OBJ_TYPE_OUR_SEC: - key.sec.peer_addr = *BLE_ADDR_ANY; - pidx = &key.sec.idx; - break; - case BLE_STORE_OBJ_TYPE_CCCD: - key.cccd.peer_addr = *BLE_ADDR_ANY; - pidx = &key.cccd.idx; - break; + case BLE_STORE_OBJ_TYPE_PEER_SEC: + case BLE_STORE_OBJ_TYPE_OUR_SEC: + key.sec.peer_addr = *BLE_ADDR_ANY; + pidx = &key.sec.idx; + break; + case BLE_STORE_OBJ_TYPE_CCCD: + key.cccd.peer_addr = *BLE_ADDR_ANY; + pidx = &key.cccd.idx; + break; #if MYNEWT_VAL(ENC_ADV_DATA) - case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: - key.ead.peer_addr = *BLE_ADDR_ANY; - pidx = &key.ead.idx; - break; + case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: + key.ead.peer_addr = *BLE_ADDR_ANY; + pidx = &key.ead.idx; + break; #endif - case BLE_STORE_OBJ_TYPE_PEER_ADDR: - key.rpa_rec.peer_rpa_addr = *BLE_ADDR_ANY; - pidx = &key.rpa_rec.idx; - break; - case BLE_STORE_OBJ_TYPE_LOCAL_IRK: - key.local_irk.addr = *BLE_ADDR_ANY; - pidx = &key.local_irk.idx; - break; - - default: - BLE_HS_DBG_ASSERT(0); - return BLE_HS_EINVAL; + case BLE_STORE_OBJ_TYPE_PEER_ADDR: + key.rpa_rec.peer_rpa_addr = *BLE_ADDR_ANY; + pidx = &key.rpa_rec.idx; + break; + case BLE_STORE_OBJ_TYPE_LOCAL_IRK: + key.local_irk.addr = *BLE_ADDR_ANY; + pidx = &key.local_irk.idx; + break; + case BLE_STORE_OBJ_TYPE_CSFC: + key.csfc.peer_addr = *BLE_ADDR_ANY; + pidx = &key.csfc.idx; + break; + default: + BLE_HS_DBG_ASSERT(0); + return BLE_HS_EINVAL; } while (1) { @@ -555,6 +603,7 @@ ble_store_clear(void) BLE_STORE_OBJ_TYPE_OUR_SEC, BLE_STORE_OBJ_TYPE_PEER_SEC, BLE_STORE_OBJ_TYPE_CCCD, + BLE_STORE_OBJ_TYPE_CSFC, BLE_STORE_OBJ_TYPE_PEER_ADDR, BLE_STORE_OBJ_TYPE_LOCAL_IRK, #if MYNEWT_VAL(ENC_ADV_DATA) @@ -564,7 +613,7 @@ ble_store_clear(void) union ble_store_key key; int obj_type; int rc; - int i; + unsigned int i; /* A zeroed key will always retrieve the first value. */ memset(&key, 0, sizeof key); diff --git a/src/nimble/nimble/host/src/ble_store_util.c b/src/nimble/nimble/host/src/ble_store_util.c index 368429fe..4a696564 100644 --- a/src/nimble/nimble/host/src/ble_store_util.c +++ b/src/nimble/nimble/host/src/ble_store_util.c @@ -154,6 +154,14 @@ ble_store_util_delete_peer(const ble_addr_t *peer_id_addr) return rc; } + memset(&key, 0, sizeof key); + key.csfc.peer_addr = *peer_id_addr; + + rc = ble_store_util_delete_all(BLE_STORE_OBJ_TYPE_CSFC, &key); + if (rc != 0) { + return rc; + } + #if MYNEWT_VAL(BLE_HOST_BASED_PRIVACY) struct ble_hs_dev_records *peer_rec = ble_rpa_find_peer_dev_rec(key.sec.peer_addr.val); @@ -346,6 +354,7 @@ ble_store_util_status_rr(struct ble_store_status_event *event, void *arg) case BLE_STORE_OBJ_TYPE_PEER_ADDR: return ble_gap_unpair_oldest_peer(); case BLE_STORE_OBJ_TYPE_CCCD: + case BLE_STORE_OBJ_TYPE_CSFC: /* Try unpairing oldest peer except current peer */ return ble_gap_unpair_oldest_except(&event->overflow.value->cccd.peer_addr); #if MYNEWT_VAL(ENC_ADV_DATA) diff --git a/src/nimble/nimble/host/src/ble_uuid.c b/src/nimble/nimble/host/src/ble_uuid.c index 9463eb73..1a1ddddc 100644 --- a/src/nimble/nimble/host/src/ble_uuid.c +++ b/src/nimble/nimble/host/src/ble_uuid.c @@ -26,6 +26,10 @@ #include "ble_hs_priv.h" #include "nimble/nimble/host/include/host/ble_uuid.h" +#define BLE_UUID16_STR_MAX_LEN 6 +#define BLE_UUID32_STR_MAX_LEN 10 +#define BLE_UUID128_STR_MAX_LEN 36 + static uint8_t ble_uuid_base[16] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 @@ -40,6 +44,52 @@ static uint8_t ble_uuid_base[16] = { #define VERIFY_UUID(uuid) #endif +static int +hex2val(char c, uint8_t *value) +{ + if (c >= '0' && c <= '9') { + *value = c - '0'; + } else if (c >= 'a' && c <= 'f') { + *value = c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + *value = c - 'A' + 10; + } else { + return BLE_HS_EINVAL; + } + return 0; +} + + +static size_t +hex2bin(const char *hex, uint8_t *bin, size_t bin_len) +{ + size_t len = 0; + uint8_t tmp_val; + int rc; + + while (*hex && len < bin_len) { + rc = hex2val(*hex++, &tmp_val); + if (rc != 0) { + return 0; + } + + bin[len] = tmp_val << 4; + + if (!*hex) { + len++; + break; + } + + rc = hex2val(*hex++, &tmp_val); + if (rc != 0) { + return 0; + } + bin[len++] |= tmp_val; + } + + return len; +} + int ble_uuid_init_from_buf(ble_uuid_any_t *uuid, const void *buf, size_t len) { @@ -136,6 +186,106 @@ ble_uuid_to_str(const ble_uuid_t *uuid, char *dst) return dst; } +int +ble_uuid_from_str(ble_uuid_any_t *uuid, const char *str) +{ + uint8_t tmp_rslt = 0; + uint8_t *u8p; + const char *str_ptr; + uint16_t u16 = 0; + uint32_t u32 = 0; + int len = (int) strlen(str); + + if ((len < 4) || (len % 2 != 0)) { + return BLE_HS_EINVAL; + } + + str_ptr = &str[len - 2]; + + if (len <= BLE_UUID16_STR_MAX_LEN) { + uuid->u.type = BLE_UUID_TYPE_16; + } else if (len <= BLE_UUID32_STR_MAX_LEN) { + uuid->u.type = BLE_UUID_TYPE_32; + } else if (len <= BLE_UUID128_STR_MAX_LEN) { + uuid->u.type = BLE_UUID_TYPE_128; + } else { + return BLE_HS_EINVAL; + } + + switch (uuid->u.type) { + case BLE_UUID_TYPE_128: + uuid->u.type = BLE_UUID_TYPE_128; + u8p = uuid->u128.value; + for (int i = 0; i < 16; i++) { + if (hex2bin(str_ptr, u8p, 1) != 1) { + return BLE_HS_EINVAL; + } + + /* Check if string end */ + if (str_ptr == str) { + break; + } + + /* Remove '-' */ + if (*(str_ptr - 1) == '-') { + str_ptr--; + } + + str_ptr -= 2; + u8p++; + } + + if (memcmp(ble_uuid_base, uuid->u128.value, 12) == 0) { + uint8_t *tmp_ptr = &uuid->u128.value[12]; + uint32_t tmp_val32 = 0; + for (int i = 0; i < 4; i++) { + tmp_val32 |= ((uint32_t)(*tmp_ptr++) << 8 * i); + } + + if (tmp_val32 <= UINT16_MAX) { + uuid->u.type = BLE_UUID_TYPE_16; + uuid->u16.value = (uint16_t) tmp_val32; + } else { + uuid->u.type = BLE_UUID_TYPE_32; + uuid->u32.value = tmp_val32; + } + } + break; + case BLE_UUID_TYPE_32: + for (int i = 0; i < 4; i++) { + if (hex2bin(str_ptr, &tmp_rslt, 1) != 1) { + return BLE_HS_EINVAL; + } + u32 |= ((uint32_t) tmp_rslt) << (i * 8); + + if (str_ptr == str) { + break; + } + str_ptr -= 2; + } + uuid->u32.value = u32; + break; + case BLE_UUID_TYPE_16: + for (int i = 0; i < 2; i++) { + if (hex2bin(str_ptr, &tmp_rslt, 1) != 1) { + return BLE_HS_EINVAL; + } + u16 |= ((uint32_t) tmp_rslt) << (i * 8); + + if (str_ptr == str) { + break; + } + str_ptr -= 2; + } + uuid->u16.value = u16; + break; + default: + return BLE_HS_EINVAL; + } + + return 0; +} + uint16_t ble_uuid_u16(const ble_uuid_t *uuid) { @@ -227,8 +377,6 @@ ble_uuid_to_mbuf(const ble_uuid_t *uuid, struct os_mbuf *om) return 0; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpointer-arith" int ble_uuid_flat(const ble_uuid_t *uuid, void *dst) { @@ -251,7 +399,6 @@ ble_uuid_flat(const ble_uuid_t *uuid, void *dst) return 0; } -#pragma GCC diagnostic pop int ble_uuid_length(const ble_uuid_t *uuid) diff --git a/src/nimble/nimble/host/store/config/src/ble_store_config.c b/src/nimble/nimble/host/store/config/src/ble_store_config.c index 4b785767..5f65dbc6 100644 --- a/src/nimble/nimble/host/store/config/src/ble_store_config.c +++ b/src/nimble/nimble/host/store/config/src/ble_store_config.c @@ -24,7 +24,7 @@ #include "nimble/porting/nimble/include/sysinit/sysinit.h" #include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/store/config/ble_store_config.h" +#include "nimble/nimble/host/store/config/include/store/config/ble_store_config.h" #include "ble_store_config_priv.h" #if MYNEWT_VAL(BLE_STORE_MAX_BONDS) @@ -50,6 +50,12 @@ struct ble_store_value_cccd int ble_store_config_num_cccds; +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) +struct ble_store_value_csfc + ble_store_config_csfcs[MYNEWT_VAL(BLE_STORE_MAX_CSFCS)]; +#endif +int ble_store_config_num_csfcs; + #if MYNEWT_VAL(ENC_ADV_DATA) struct ble_store_value_ead ble_store_config_eads[MYNEWT_VAL(BLE_STORE_MAX_EADS)]; @@ -205,10 +211,6 @@ ble_store_config_print_key_sec(const struct ble_store_key_sec *key_sec) ble_hs_log_flat_buf(key_sec->peer_addr.val, 6); BLE_HS_LOG(DEBUG, " "); } - if (key_sec->ediv_rand_present) { - BLE_HS_LOG(DEBUG, "ediv=0x%02x rand=0x%llx ", - key_sec->ediv, key_sec->rand_num); - } } #if MYNEWT_VAL(BLE_STORE_MAX_BONDS) @@ -218,36 +220,20 @@ ble_store_config_find_sec(const struct ble_store_key_sec *key_sec, int num_value_secs) { const struct ble_store_value_sec *cur; - int skipped; int i; - skipped = 0; - - for (i = 0; i < num_value_secs; i++) { - cur = value_secs + i; - - if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) { - if (ble_addr_cmp(&cur->peer_addr, &key_sec->peer_addr)) { - continue; - } + if (!ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) { + if (key_sec->idx < num_value_secs) { + return key_sec->idx; } + } else if (key_sec->idx == 0) { + for (i = 0; i < num_value_secs; i++) { + cur = &value_secs[i]; - if (key_sec->ediv_rand_present) { - if (cur->ediv != key_sec->ediv) { - continue; - } - - if (cur->rand_num != key_sec->rand_num) { - continue; + if (!ble_addr_cmp(&cur->peer_addr, &key_sec->peer_addr)) { + return i; } } - - if (key_sec->idx > skipped) { - skipped++; - continue; - } - - return i; } return -1; @@ -323,7 +309,6 @@ ble_store_config_write_our_sec(const struct ble_store_value_sec *value_sec) } -#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) static int ble_store_config_delete_obj(void *values, int value_size, int idx, int *num_values) @@ -345,6 +330,7 @@ ble_store_config_delete_obj(void *values, int value_size, int idx, return 0; } +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) static int ble_store_config_delete_sec(const struct ble_store_key_sec *key_sec, struct ble_store_value_sec *value_secs, @@ -893,6 +879,7 @@ ble_store_config_write_rpa_rec(const struct ble_store_value_rpa_rec *value_rpa_r static int ble_store_config_delete_rpa_rec(const struct ble_store_key_rpa_rec *key_rpa_rec) { +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) int idx; int rc; @@ -914,6 +901,113 @@ ble_store_config_delete_rpa_rec(const struct ble_store_key_rpa_rec *key_rpa_rec) return rc; } + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +/***************************************************************************** + * $csfc * + *****************************************************************************/ + +static int +ble_store_config_find_csfc(const struct ble_store_key_csfc *key, + const struct ble_store_value_csfc *value_csfc, + int num_value_csfc) +{ + const struct ble_store_value_csfc *cur; + int i; + + if (!ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) { + if (key->idx < num_value_csfc) { + return key->idx; + } + } else if (key->idx == 0) { + for (i = 0; i < num_value_csfc; i++) { + cur = &value_csfc[i]; + + if (!ble_addr_cmp(&cur->peer_addr, &key->peer_addr)) { + return i; + } + } + } + + return -1; +} + +static int +ble_store_config_delete_csfc(const struct ble_store_key_csfc *key_csfc) +{ + int idx; + int rc; + + idx = ble_store_config_find_csfc(key_csfc, ble_store_config_csfcs, + ble_store_config_num_csfcs); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + rc = ble_store_config_delete_obj(ble_store_config_csfcs, + sizeof *ble_store_config_csfcs, + idx, &ble_store_config_num_csfcs); + + if (rc != 0) { + return rc; + } + + rc = ble_store_config_persist_csfcs(); + if (rc != 0) { + return rc; + } + + return 0; +} + +static int +ble_store_config_read_csfc(const struct ble_store_key_csfc *key_csfc, + struct ble_store_value_csfc *value_csfc) +{ + int idx; + + idx = ble_store_config_find_csfc(key_csfc, ble_store_config_csfcs, + ble_store_config_num_csfcs); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_csfc = ble_store_config_csfcs[idx]; + return 0; +} + +static int +ble_store_config_write_csfc(const struct ble_store_value_csfc *value_csfc) +{ + struct ble_store_key_csfc key_csfc; + int idx; + int rc; + + ble_store_key_from_value_csfc(&key_csfc, value_csfc); + idx = ble_store_config_find_csfc(&key_csfc, ble_store_config_csfcs, + ble_store_config_num_csfcs); + if (idx == -1) { + if (ble_store_config_num_csfcs >= MYNEWT_VAL(BLE_STORE_MAX_CSFCS)) { + BLE_HS_LOG(DEBUG, "error persisting csfc; too many entries (%d)\n", + ble_store_config_num_csfcs); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_config_num_csfcs; + ble_store_config_num_csfcs++; + } + + ble_store_config_csfcs[idx] = *value_csfc; + + rc = ble_store_config_persist_csfcs(); + if (rc != 0) { + return rc; + } + return 0; } @@ -959,6 +1053,10 @@ ble_store_config_read(int obj_type, const union ble_store_key *key, rc = ble_store_config_read_cccd(&key->cccd, &value->cccd); return rc; + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_config_read_csfc(&key->csfc, &value->csfc); + return rc; + #if MYNEWT_VAL(ENC_ADV_DATA) case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: rc = ble_store_config_read_ead(&key->ead, &value->ead); @@ -1000,6 +1098,10 @@ ble_store_config_write(int obj_type, const union ble_store_value *val) rc = ble_store_config_write_cccd(&val->cccd); return rc; + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_config_write_csfc(&val->csfc); + return rc; + #if MYNEWT_VAL(ENC_ADV_DATA) case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: rc = ble_store_config_write_ead(&val->ead); @@ -1036,6 +1138,10 @@ ble_store_config_delete(int obj_type, const union ble_store_key *key) rc = ble_store_config_delete_cccd(&key->cccd); return rc; + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_config_delete_csfc(&key->csfc); + return rc; + #if MYNEWT_VAL(ENC_ADV_DATA) case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: rc = ble_store_config_delete_ead(&key->ead); @@ -1068,6 +1174,7 @@ ble_store_config_init(void) ble_store_config_num_our_secs = 0; ble_store_config_num_peer_secs = 0; ble_store_config_num_cccds = 0; + ble_store_config_num_csfcs = 0; #if MYNEWT_VAL(ENC_ADV_DATA) ble_store_config_num_eads = 0; #endif diff --git a/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c b/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c index 3d7247dd..c6ad62b8 100644 --- a/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c +++ b/src/nimble/nimble/host/store/config/src/ble_store_config_conf.c @@ -17,10 +17,6 @@ * under the License. */ -/* - * Modified work Copyright (c) 2021 Ryan Powell. - */ - #ifndef ESP_PLATFORM #include "nimble/porting/nimble/include/syscfg/syscfg.h" @@ -28,31 +24,15 @@ #if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) #include -//#include +#include #include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "../../../include/host/ble_hs.h" -//#include "config/config.h" +#include "nimble/nimble/host/include/host/ble_hs.h" #include "base64/base64.h" -#include "../include/store/config/ble_store_config.h" +#include "nimble/nimble/host/store/config/include/store/config/ble_store_config.h" #include "ble_store_config_priv.h" #include "ble_bond_nvs.h" -/* -static int -ble_store_config_conf_set(int argc, char **argv, char *val); -static int -ble_store_config_conf_export(void (*func)(char *name, char *val), - enum conf_export_tgt tgt); - -static struct conf_handler ble_store_config_conf_handler = { - .ch_name = "ble_hs", - .ch_get = NULL, - .ch_set = ble_store_config_conf_set, - .ch_commit = NULL, - .ch_export = ble_store_config_conf_export -}; -*/ #define BLE_STORE_CONFIG_SEC_ENCODE_SZ \ BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_sec)) @@ -65,6 +45,12 @@ static struct conf_handler ble_store_config_conf_handler = { #define BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ \ (MYNEWT_VAL(BLE_STORE_MAX_CCCDS) * BLE_STORE_CONFIG_CCCD_ENCODE_SZ + 1) +#define BLE_STORE_CONFIG_CSFC_ENCODE_SZ \ + BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_csfc)) + +#define BLE_STORE_CONFIG_CSFC_SET_ENCODE_SZ \ + (MYNEWT_VAL(BLE_STORE_MAX_CSFCS) * BLE_STORE_CONFIG_CSFC_ENCODE_SZ + 1) + #if MYNEWT_VAL(ENC_ADV_DATA) #define BLE_STORE_CONFIG_EAD_ENCODE_SZ \ BASE64_ENCODE_SIZE(sizeof (struct ble_store_value_ead)) @@ -85,7 +71,13 @@ static struct conf_handler ble_store_config_conf_handler = { #define BLE_STORE_CONFIG_IRK_SET_ENCODE_SZ \ (MYNEWT_VAL(BLE_STORE_MAX_BONDS) * BLE_STORE_CONFIG_IRK_ENCODE_SZ + 1) -static const uint32_t our_irk = 0x6b72696f; /* oirk */ +#define CCCD_LABEL 0x64636363 /* cccd */ +#define CSFC_LABEL 0x63667363 /* csfc */ +#define RPA_REC_LABEL 0x72617072 /* rpar */ +#define IRK_LABEL 0x6b72696f /* oirk */ +#define EAD_LABEL 0x00646165 /* ead */ +#define PEER_SEC_LABEL 0x63657370 /* psec */ +#define OUR_SEC_LABEL 0x6365736f /* osec */ static void ble_store_config_serialize_arr(const void *arr, int obj_sz, int num_objs, @@ -115,107 +107,7 @@ ble_store_config_deserialize_arr(const char *enc, *out_num_objs = len / obj_sz; return 0; } -/* -static int -ble_store_config_conf_set(int argc, char **argv, char *val) -{ - int rc; - - if (argc == 1) { - if (strcmp(argv[0], "our_sec") == 0) { - rc = ble_store_config_deserialize_arr( - val, - ble_store_config_our_secs, - sizeof *ble_store_config_our_secs, - &ble_store_config_num_our_secs); - printf("\nloading: %s %s rc=%d\n", *argv, val, rc); - return rc; - } else if (strcmp(argv[0], "peer_sec") == 0) { - rc = ble_store_config_deserialize_arr( - val, - ble_store_config_peer_secs, - sizeof *ble_store_config_peer_secs, - &ble_store_config_num_peer_secs); - printf("\nloading: %s %s rc=%d\n", *argv, val, rc); - return rc; - } else if (strcmp(argv[0], "cccd") == 0) { - rc = ble_store_config_deserialize_arr( - val, - ble_store_config_cccds, - sizeof *ble_store_config_cccds, - &ble_store_config_num_cccds); - printf("\nloading: %s %s rc=%d\n", *argv, val, rc); - return rc; - } -#if MYNEWT_VAL(ENC_ADV_DATA) - else if (strcmp(argv[0], "ead") == 0) { - rc = ble_store_config_deserialize_arr( - val, - ble_store_config_eads, - sizeof *ble_store_config_eads, - &ble_store_config_num_eads); - return rc; - } -#endif - else if (strcmp(argv[0],"rpa_rec") == 0){ - rc = ble_store_config_deserialize_arr( - val, - ble_store_config_rpa_recs, - sizeof *ble_store_config_rpa_recs, - &ble_store_config_num_rpa_recs); - return rc; - } - } - return OS_ENOENT; -} -static int -ble_store_config_conf_export(void (*func)(char *name, char *val), - enum conf_export_tgt tgt) -{ - union { - char sec[BLE_STORE_CONFIG_SEC_SET_ENCODE_SZ]; - char cccd[BLE_STORE_CONFIG_CCCD_SET_ENCODE_SZ]; - char rpa_rec[BLE_STORE_CONFIG_RPA_REC_SET_ENCODE_SZ]; - } buf; - - ble_store_config_serialize_arr(ble_store_config_our_secs, - sizeof *ble_store_config_our_secs, - ble_store_config_num_our_secs, - buf.sec, - sizeof buf.sec); - func("ble_hs/our_sec", buf.sec); - - ble_store_config_serialize_arr(ble_store_config_peer_secs, - sizeof *ble_store_config_peer_secs, - ble_store_config_num_peer_secs, - buf.sec, - sizeof buf.sec); - func("ble_hs/peer_sec", buf.sec); - - ble_store_config_serialize_arr(ble_store_config_cccds, - sizeof *ble_store_config_cccds, - ble_store_config_num_cccds, - buf.cccd, - sizeof buf.cccd); - func("ble_hs/cccd", buf.cccd); - -#if MYNEWT_VAL(ENC_ADV_DATA) - ble_store_config_serialize_arr(ble_store_config_eads, - sizeof *ble_store_config_eads, - ble_store_config_num_eads, - buf.ead, - sizeof buf.ead); - func("ble_hs/ead", buf.ead); -#endif - ble_store_config_serialize_arr(ble_store_config_rpa_recs, - sizeof *ble_store_config_rpa_recs, - ble_store_config_num_rpa_recs, - buf.rpa_rec, - sizeof buf.rpa_rec); - return 0; -} -*/ static int ble_store_config_persist_sec_set(uint32_t setting_name, const struct ble_store_value_sec *secs, @@ -226,7 +118,6 @@ ble_store_config_persist_sec_set(uint32_t setting_name, ble_store_config_serialize_arr(secs, sizeof *secs, num_secs, buf, sizeof buf); - rc = ble_bond_nvs_save_entry(setting_name, buf); if (rc != 0) { return BLE_HS_ESTORE_FAIL; @@ -240,7 +131,7 @@ ble_store_config_persist_our_secs(void) { int rc; - rc = ble_store_config_persist_sec_set(our_sec, + rc = ble_store_config_persist_sec_set(OUR_SEC_LABEL, ble_store_config_our_secs, ble_store_config_num_our_secs); if (rc != 0) { @@ -255,7 +146,7 @@ ble_store_config_persist_peer_secs(void) { int rc; - rc = ble_store_config_persist_sec_set(peer_sec, + rc = ble_store_config_persist_sec_set(PEER_SEC_LABEL, ble_store_config_peer_secs, ble_store_config_num_peer_secs); if (rc != 0) { @@ -276,8 +167,26 @@ ble_store_config_persist_cccds(void) ble_store_config_num_cccds, buf, sizeof buf); + rc = ble_bond_nvs_save_entry(CCCD_LABEL, buf); + if (rc != 0) { + return BLE_HS_ESTORE_FAIL; + } + + return 0; +} + +int +ble_store_config_persist_csfcs(void) +{ + char buf[BLE_STORE_CONFIG_CSFC_SET_ENCODE_SZ]; + int rc; - rc = ble_bond_nvs_save_entry(cccd, buf); + ble_store_config_serialize_arr(ble_store_config_csfcs, + sizeof *ble_store_config_csfcs, + ble_store_config_num_csfcs, + buf, + sizeof buf); + rc = ble_bond_nvs_save_entry(CSFC_LABEL, buf); if (rc != 0) { return BLE_HS_ESTORE_FAIL; } @@ -296,7 +205,8 @@ ble_store_config_persist_eads(void) ble_store_config_num_eads, buf, sizeof buf); - rc = conf_save_one("ble_hs/ead", buf); + + rc = ble_bond_nvs_save_entry(EAD_LABEL, buf); if (rc != 0) { return BLE_HS_ESTORE_FAIL; } @@ -307,7 +217,6 @@ ble_store_config_persist_eads(void) int ble_store_config_persist_rpa_recs(void) { -#if 0 char buf[BLE_STORE_CONFIG_RPA_REC_SET_ENCODE_SZ]; int rc; ble_store_config_serialize_arr(ble_store_config_rpa_recs, @@ -315,13 +224,11 @@ ble_store_config_persist_rpa_recs(void) ble_store_config_num_rpa_recs, buf, sizeof buf); - rc = conf_save_one("ble_hs/rpa_rec", buf); + rc = ble_bond_nvs_save_entry(RPA_REC_LABEL, buf); if (rc != 0) { return BLE_HS_ESTORE_FAIL; } return 0; -#endif - return BLE_HS_ESTORE_FAIL; } int @@ -334,7 +241,7 @@ ble_store_config_persist_local_irk(void) { ble_store_config_num_local_irks, buf, sizeof buf); - rc = ble_bond_nvs_save_entry(our_irk, buf); + rc = ble_bond_nvs_save_entry(IRK_LABEL, buf); if (rc != 0) { return BLE_HS_ESTORE_FAIL; } @@ -348,7 +255,7 @@ ble_store_config_conf_init(void) uint32_t val_addr = 0; int rc = 0; - rc = ble_bond_nvs_get_entry(our_sec, &val_addr); + rc = ble_bond_nvs_get_entry(OUR_SEC_LABEL, &val_addr); if (rc == 0) { rc = ble_store_config_deserialize_arr( (char*)val_addr, @@ -356,11 +263,11 @@ ble_store_config_conf_init(void) sizeof *ble_store_config_our_secs, &ble_store_config_num_our_secs); if (rc != 0) { - BLE_HS_LOG(ERROR, "our_sec restore error rc=%d\n", rc); + BLE_HS_LOG(ERROR, "our_sec restore error rc=%d\n", rc); return; } - rc = ble_bond_nvs_get_entry(peer_sec, &val_addr); + rc = ble_bond_nvs_get_entry(PEER_SEC_LABEL, &val_addr); if (rc == 0) { rc = ble_store_config_deserialize_arr( (char*)val_addr, @@ -368,7 +275,7 @@ ble_store_config_conf_init(void) sizeof *ble_store_config_peer_secs, &ble_store_config_num_peer_secs); if (rc != 0) { - BLE_HS_LOG(ERROR, "peer_sec restore error rc=%d\n", rc); + BLE_HS_LOG(ERROR, "peer_sec restore error rc=%d\n", rc); return; } @@ -381,7 +288,7 @@ ble_store_config_conf_init(void) return; } - rc = ble_bond_nvs_get_entry(cccd, &val_addr); + rc = ble_bond_nvs_get_entry(CCCD_LABEL, &val_addr); if (rc == 0) { rc = ble_store_config_deserialize_arr( (char*)val_addr, @@ -389,13 +296,60 @@ ble_store_config_conf_init(void) sizeof *ble_store_config_cccds, &ble_store_config_num_cccds); if (rc != 0) { - BLE_HS_LOG(ERROR, "cccd restore error rc=%d\n", rc); + BLE_HS_LOG(ERROR, "cccd restore error rc=%d\n", rc); return; } } + + rc = ble_bond_nvs_get_entry(CSFC_LABEL, &val_addr); + if (rc == 0) { + rc = ble_store_config_deserialize_arr( + (char*)val_addr, + ble_store_config_csfcs, + sizeof *ble_store_config_csfcs, + &ble_store_config_num_csfcs); + if (rc != 0) { + BLE_HS_LOG(ERROR, "cfsc restore error rc=%d\n", rc); + return; + } + } + +#if MYNEWT_VAL(ENC_ADV_DATA) + rc = ble_bond_nvs_get_entry(EAD_LABEL, &val_addr); + if (rc == 0) { + rc = ble_store_config_deserialize_arr( + (char*)val_addr, + ble_store_config_eads, + sizeof *ble_store_config_eads, + &ble_store_config_num_eads); + if (rc != 0) { + BLE_HS_LOG(ERROR, "ead restore error rc=%d\n", rc); + return; + } + } +#endif + rc = ble_bond_nvs_get_entry(RPA_REC_LABEL, &val_addr); + if (rc == 0) { + rc = ble_store_config_deserialize_arr( + (char*)val_addr, + ble_store_config_rpa_recs, + sizeof *ble_store_config_rpa_recs, + &ble_store_config_num_rpa_recs); + if (rc != 0) { + BLE_HS_LOG(ERROR, "rpa_rec restore error rc=%d\n", rc); + return; + } + } + } else { + /* If we have a security entry for our security but not a peer + * we should assume something wrong with the store so delete it. + */ + BLE_HS_LOG(ERROR, "our_sec info not found\n"); + ble_store_clear(); + return; } - rc = ble_bond_nvs_get_entry(our_irk, &val_addr); + rc = ble_bond_nvs_get_entry(IRK_LABEL, &val_addr); if (rc == 0) { rc = ble_store_config_deserialize_arr( (char*)val_addr, @@ -403,18 +357,11 @@ ble_store_config_conf_init(void) sizeof *ble_store_config_local_irks, &ble_store_config_num_local_irks); if (rc != 0) { - BLE_HS_LOG(ERROR, "irk restore error rc=%d\n", rc); + BLE_HS_LOG(ERROR, "irk restore error rc=%d\n", rc); return; } } - - /* int rc; - - rc = conf_register(&ble_store_config_conf_handler); - SYSINIT_PANIC_ASSERT_MSG(rc == 0, - "Failed to register ble_store_config conf"); - */ } #endif /* MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) */ -#endif /* ESP_PLATFORM */ \ No newline at end of file +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h b/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h index 581cefdc..a3dcc6aa 100644 --- a/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h +++ b/src/nimble/nimble/host/store/config/src/ble_store_config_priv.h @@ -36,6 +36,10 @@ extern struct ble_store_value_cccd ble_store_config_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)]; extern int ble_store_config_num_cccds; +extern struct ble_store_value_csfc + ble_store_config_csfcs[MYNEWT_VAL(BLE_STORE_MAX_CSFCS)]; +extern int ble_store_config_num_csfcs; + #if MYNEWT_VAL(ENC_ADV_DATA) extern struct ble_store_value_ead ble_store_config_eads[MYNEWT_VAL(BLE_STORE_MAX_EADS)]; @@ -56,6 +60,7 @@ extern int ble_store_config_num_local_irks; int ble_store_config_persist_our_secs(void); int ble_store_config_persist_peer_secs(void); int ble_store_config_persist_cccds(void); +int ble_store_config_persist_csfcs(void); #if MYNEWT_VAL(BLE_STORE_MAX_BONDS) int ble_restore_our_sec_nvs(void); int ble_restore_peer_sec_nvs(void); @@ -72,6 +77,7 @@ void ble_store_config_conf_init(void); static inline int ble_store_config_persist_our_secs(void) { return 0; } static inline int ble_store_config_persist_peer_secs(void) { return 0; } static inline int ble_store_config_persist_cccds(void) { return 0; } +static inline int ble_store_config_persist_csfcs(void) { return 0; } #if MYNEWT_VAL(ENC_ADV_DATA) static inline int ble_store_config_persist_eads(void) { return 0; } #endif diff --git a/src/nimble/nimble/host/store/config/src/ble_store_nvs.c b/src/nimble/nimble/host/store/config/src/ble_store_nvs.c index 35b0aadf..0abe4bc4 100644 --- a/src/nimble/nimble/host/store/config/src/ble_store_nvs.c +++ b/src/nimble/nimble/host/store/config/src/ble_store_nvs.c @@ -20,6 +20,7 @@ */ #ifdef ESP_PLATFORM + #include "nimble/porting/nimble/include/syscfg/syscfg.h" #if MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) @@ -28,17 +29,18 @@ #include #include "nimble/porting/nimble/include/sysinit/sysinit.h" #include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/store/config/ble_store_config.h" +#include "nimble/nimble/host/store/config/include/store/config/ble_store_config.h" #include "ble_store_config_priv.h" #include "esp_log.h" #include "nvs.h" -#include "../../../src/ble_hs_resolv_priv.h" +#include "nimble/nimble/host/src/ble_hs_resolv_priv.h" #define NIMBLE_NVS_STR_NAME_MAX_LEN 16 #define NIMBLE_NVS_PEER_SEC_KEY "peer_sec" #define NIMBLE_NVS_OUR_SEC_KEY "our_sec" #define NIMBLE_NVS_CCCD_SEC_KEY "cccd_sec" +#define NIMBLE_NVS_CSFC_SEC_KEY "csfc_sec" #define NIMBLE_NVS_PEER_RECORDS_KEY "p_dev_rec" #define NIMBLE_NVS_NAMESPACE "nimble_bond" @@ -67,7 +69,7 @@ get_nvs_key_string(int obj_type, int index, char *key_string) } else if (obj_type == BLE_STORE_OBJ_TYPE_OUR_SEC) { sprintf(key_string, "%s_%d", NIMBLE_NVS_OUR_SEC_KEY, index); #if MYNEWT_VAL(ENC_ADV_DATA) - } else if (obj_type == NIMBLE_NVS_EAD_SEC_KEY) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { sprintf(key_string, "%s_%d", NIMBLE_NVS_EAD_SEC_KEY, index); #endif } else if (obj_type == BLE_STORE_OBJ_TYPE_LOCAL_IRK) { @@ -75,8 +77,10 @@ get_nvs_key_string(int obj_type, int index, char *key_string) } else if (obj_type == BLE_STORE_OBJ_TYPE_PEER_ADDR){ sprintf(key_string, "%s_%d", NIMBLE_NVS_RPA_RECORDS_KEY, index); - }else { + } else if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { sprintf(key_string, "%s_%d", NIMBLE_NVS_CCCD_SEC_KEY, index); + } else { + sprintf(key_string, "%s_%d", NIMBLE_NVS_CSFC_SEC_KEY, index); } } } @@ -111,8 +115,10 @@ get_nvs_max_obj_value(int obj_type) } else { if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { return MYNEWT_VAL(BLE_STORE_MAX_CCCDS); + } else if (obj_type == BLE_STORE_OBJ_TYPE_CSFC) { + return MYNEWT_VAL(BLE_STORE_MAX_CSFCS); #if MYNEWT_VAL(ENC_ADV_DATA) - } else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { return MYNEWT_VAL(BLE_STORE_MAX_EADS); #endif } else { @@ -177,8 +183,11 @@ get_nvs_db_value(int obj_type, char *key_string, union ble_store_value *val) if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { err = nvs_get_blob(nimble_handle, key_string, &val->cccd, &required_size); + } else if (obj_type == BLE_STORE_OBJ_TYPE_CSFC) { + err = nvs_get_blob(nimble_handle, key_string, &val->csfc, + &required_size); #if MYNEWT_VAL(ENC_ADV_DATA) - } else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { err = nvs_get_blob(nimble_handle, key_string, &val->ead, &required_size); #endif @@ -256,8 +265,11 @@ get_nvs_db_attribute(int obj_type, bool empty, void *value, int num_value) if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { err = get_nvs_matching_index(&cur.sec, value, num_value, sizeof(struct ble_store_value_cccd)); + } else if (obj_type == BLE_STORE_OBJ_TYPE_CSFC) { + err = get_nvs_matching_index(&cur.csfc, value, num_value, + sizeof(struct ble_store_value_csfc)); #if MYNEWT_VAL(ENC_ADV_DATA) - } else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { err = get_nvs_matching_index(&cur.sec, value, num_value, sizeof(struct ble_store_value_ead)); #endif @@ -393,8 +405,11 @@ ble_store_nvs_write(int obj_type, const union ble_store_value *val) if (obj_type == BLE_STORE_OBJ_TYPE_CCCD) { return ble_nvs_write_key_value(key_string, &val->cccd, sizeof(struct ble_store_value_cccd)); + } else if (obj_type == BLE_STORE_OBJ_TYPE_CSFC) { + return ble_nvs_write_key_value(key_string, &val->csfc, sizeof(struct + ble_store_value_csfc)); #if MYNEWT_VAL(ENC_ADV_DATA) - } else if (obj_type == BLE_STORE_OBJ_TYPE_EAD) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { return ble_nvs_write_key_value(key_string, &val->ead, sizeof(struct ble_store_value_ead)); #endif @@ -490,8 +505,13 @@ populate_db_from_nvs(int obj_type, void *dst, int *db_num) memcpy(db_item, &cur.cccd, sizeof(struct ble_store_value_cccd)); db_item += sizeof(struct ble_store_value_cccd); (*db_num)++; + } else if (obj_type == BLE_STORE_OBJ_TYPE_CSFC) { + ESP_LOGD(LOG_TAG, "CSFC in RAM is filled up from NVS index = %d", i); + memcpy(db_item, &cur.csfc, sizeof(struct ble_store_value_csfc)); + db_item += sizeof(struct ble_store_value_csfc); + (*db_num)++; #if MYNEWT_VAL(ENC_ADV_DATA) - } if (obj_type == BLE_STORE_OBJ_TYPE_EAD) { + } else if (obj_type == BLE_STORE_OBJ_TYPE_ENC_ADV_DATA) { ESP_LOGD(LOG_TAG, "EAD in RAM is filled up from NVS index = %d", i); memcpy(db_item, &cur.ead, sizeof(struct ble_store_value_ead)); db_item += sizeof(struct ble_store_value_ead); @@ -582,8 +602,19 @@ ble_nvs_restore_sec_keys(void) ble_store_config_num_cccds); #endif +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_CSFC, ble_store_config_csfcs, + &ble_store_config_num_csfcs); + if (err != ESP_OK) { + ESP_LOGE(LOG_TAG, "NVS operation failed for 'CSFC'"); + return err; + } + ESP_LOGD(LOG_TAG, "ble_store_config_csfcs restored %d bonds", + ble_store_config_num_csfcs); +#endif + #if MYNEWT_VAL(ENC_ADV_DATA) - err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_EAD, ble_store_config_eads, + err = populate_db_from_nvs(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, ble_store_config_eads, &ble_store_config_num_eads); if (err != ESP_OK) { ESP_LOGE(LOG_TAG, "NVS operation failed for 'EAD'"); @@ -668,6 +699,38 @@ int ble_store_config_persist_cccds(void) } #endif +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) +int ble_store_config_persist_csfcs(void) +{ + int nvs_count, nvs_idx; + union ble_store_value val; + + nvs_count = get_nvs_db_attribute(BLE_STORE_OBJ_TYPE_CSFC, 0, NULL, 0); + if (nvs_count == -1) { + ESP_LOGE(LOG_TAG, "NVS operation failed while persisting CSFC"); + return BLE_HS_ESTORE_FAIL; + } + + if (nvs_count < ble_store_config_num_csfcs) { + /* NVS db count less than RAM count, write operation */ + ESP_LOGD(LOG_TAG, "Persisting CSFC value in NVS..."); + val.csfc = ble_store_config_csfcs[ble_store_config_num_csfcs - 1]; + return ble_store_nvs_write(BLE_STORE_OBJ_TYPE_CSFC, &val); + } else if (nvs_count > ble_store_config_num_csfcs) { + /* NVS db count more than RAM count, delete operation */ + nvs_idx = get_nvs_db_attribute(BLE_STORE_OBJ_TYPE_CSFC, 0, + ble_store_config_csfcs, ble_store_config_num_csfcs); + if (nvs_idx == -1) { + ESP_LOGE(LOG_TAG, "NVS delete operation failed for CSFC"); + return BLE_HS_ESTORE_FAIL; + } + ESP_LOGD(LOG_TAG, "Deleting CSFC, nvs idx = %d", nvs_idx); + return ble_nvs_delete_value(BLE_STORE_OBJ_TYPE_CSFC, nvs_idx); + } + return 0; +} +#endif + #if MYNEWT_VAL(ENC_ADV_DATA) int ble_store_config_persist_eads(void) { @@ -694,7 +757,7 @@ int ble_store_config_persist_eads(void) return BLE_HS_ESTORE_FAIL; } ESP_LOGD(LOG_TAG, "Deleting EAD, nvs idx = %d", nvs_idx); - return ble_nvs_delete_value(BLE_STORE_OBJ_TYPE_EAD, nvs_idx); + return ble_nvs_delete_value(BLE_STORE_OBJ_TYPE_ENC_ADV_DATA, nvs_idx); } return 0; } @@ -874,4 +937,4 @@ void ble_store_config_conf_init(void) /***************************************************************************************/ #endif /* MYNEWT_VAL(BLE_STORE_CONFIG_PERSIST) */ -#endif /* ESP_PLATFORM */ \ No newline at end of file +#endif /* ESP_PLATFORM */ diff --git a/src/nimble/nimble/controller/include/controller/ble_ll_plna.h b/src/nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h similarity index 62% rename from src/nimble/nimble/controller/include/controller/ble_ll_plna.h rename to src/nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h index 1dbb5ee8..19372f17 100644 --- a/src/nimble/nimble/controller/include/controller/ble_ll_plna.h +++ b/src/nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h @@ -17,29 +17,28 @@ * under the License. */ -#ifndef H_BLE_LL_PLNA_ -#define H_BLE_LL_PLNA_ +/* This package has been deprecated and you should + * use the store/config package. For a RAM-only BLE store, + * use store/config and set BLE_STORE_CONFIG_PERSIST to 0. + */ + +#ifndef H_BLE_STORE_RAM_ +#define H_BLE_STORE_RAM_ #ifdef __cplusplus extern "C" { #endif -#include "nimble/porting/nimble/include/syscfg/syscfg.h" - -#if MYNEWT_VAL(BLE_LL_PA) -void ble_ll_plna_pa_init(void); -void ble_ll_plna_pa_enable(void); -void ble_ll_plna_pa_disable(void); -#endif +union ble_store_key; +union ble_store_value; -#if MYNEWT_VAL(BLE_LL_LNA) -void ble_ll_plna_lna_init(void); -void ble_ll_plna_lna_enable(void); -void ble_ll_plna_lna_disable(void); -#endif +int ble_store_ram_read(int obj_type, const union ble_store_key *key, + union ble_store_value *value); +int ble_store_ram_write(int obj_type, const union ble_store_value *val); +int ble_store_ram_delete(int obj_type, const union ble_store_key *key); #ifdef __cplusplus } #endif -#endif /* H_BLE_LL_PLNA_ */ +#endif diff --git a/src/nimble/nimble/host/store/ram/src/ble_store_ram.c b/src/nimble/nimble/host/store/ram/src/ble_store_ram.c new file mode 100644 index 00000000..d0fbc3fe --- /dev/null +++ b/src/nimble/nimble/host/store/ram/src/ble_store_ram.c @@ -0,0 +1,789 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * This file implements a simple in-RAM key database for BLE host security + * material and CCCDs. As this database is only ble_store_ramd in RAM, its + * contents are lost when the application terminates. + */ + +/* This package has been deprecated and you should + * use the store/config package. For a RAM-only BLE store, + * use store/config and set BLE_STORE_CONFIG_PERSIST to 0. + */ + +#include +#include + +#include "nimble/porting/nimble/include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/nimble/host/include/host/ble_hs.h" +#include "nimble/nimble/host/store/ram/include/store/ram/ble_store_ram.h" + +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) +static struct ble_store_value_sec + ble_store_ram_our_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; +#endif + +static int ble_store_ram_num_our_secs; + +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) +static struct ble_store_value_sec + ble_store_ram_peer_secs[MYNEWT_VAL(BLE_STORE_MAX_BONDS)]; +#endif + +static int ble_store_ram_num_peer_secs; + +#if MYNEWT_VAL(BLE_STORE_MAX_CCCDS) +static struct ble_store_value_cccd + ble_store_ram_cccds[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)]; +#endif + +static int ble_store_ram_num_cccds; + +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) +static struct ble_store_value_csfc + ble_store_ram_csfcs[MYNEWT_VAL(BLE_STORE_MAX_CSFCS)]; +#endif + +static int ble_store_ram_num_csfcs; + +#if MYNEWT_VAL(ENC_ADV_DATA) +static struct ble_store_value_ead + ble_store_ram_eads[MYNEWT_VAL(BLE_STORE_MAX_EADS)]; +static int ble_store_ram_num_eads; +#endif + +/***************************************************************************** + * $sec * + *****************************************************************************/ + +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) +static void +ble_store_ram_print_value_sec(const struct ble_store_value_sec *sec) +{ + if (sec->ltk_present) { + BLE_HS_LOG(DEBUG, "ediv=%u rand=%llu authenticated=%d ltk=", + sec->ediv, sec->rand_num, sec->authenticated); + ble_hs_log_flat_buf(sec->ltk, 16); + BLE_HS_LOG(DEBUG, " "); + } + if (sec->irk_present) { + BLE_HS_LOG(DEBUG, "irk="); + ble_hs_log_flat_buf(sec->irk, 16); + BLE_HS_LOG(DEBUG, " "); + } + if (sec->csrk_present) { + BLE_HS_LOG(DEBUG, "csrk="); + ble_hs_log_flat_buf(sec->csrk, 16); + BLE_HS_LOG(DEBUG, " "); + } + + BLE_HS_LOG(DEBUG, "\n"); +} +#endif + +static void +ble_store_ram_print_key_sec(const struct ble_store_key_sec *key_sec) +{ + if (ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) { + BLE_HS_LOG(DEBUG, "peer_addr_type=%d peer_addr=", + key_sec->peer_addr.type); + ble_hs_log_flat_buf(key_sec->peer_addr.val, 6); + BLE_HS_LOG(DEBUG, " "); + } +} + +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) +static int +ble_store_ram_find_sec(const struct ble_store_key_sec *key_sec, + const struct ble_store_value_sec *value_secs, + int num_value_secs) +{ + const struct ble_store_value_sec *cur; + int i; + + if (!ble_addr_cmp(&key_sec->peer_addr, BLE_ADDR_ANY)) { + if (key_sec->idx < num_value_secs) { + return key_sec->idx; + } + } else if (key_sec->idx == 0) { + for (i = 0; i < num_value_secs; i++) { + cur = &value_secs[i]; + + if (!ble_addr_cmp(&cur->peer_addr, &key_sec->peer_addr)) { + return i; + } + } + } + + return -1; +} +#endif + +static int +ble_store_ram_read_our_sec(const struct ble_store_key_sec *key_sec, + struct ble_store_value_sec *value_sec) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) + int idx; + + idx = ble_store_ram_find_sec(key_sec, ble_store_ram_our_secs, + ble_store_ram_num_our_secs); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_sec = ble_store_ram_our_secs[idx]; + return 0; +#else + return BLE_HS_ENOENT; +#endif + +} + +static int +ble_store_ram_write_our_sec(const struct ble_store_value_sec *value_sec) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) + struct ble_store_key_sec key_sec; + int idx; + + BLE_HS_LOG(DEBUG, "persisting our sec; "); + ble_store_ram_print_value_sec(value_sec); + + ble_store_key_from_value_sec(&key_sec, value_sec); + idx = ble_store_ram_find_sec(&key_sec, ble_store_ram_our_secs, + ble_store_ram_num_our_secs); + if (idx == -1) { + if (ble_store_ram_num_our_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) { + BLE_HS_LOG(DEBUG, "error persisting our sec; too many entries " + "(%d)\n", ble_store_ram_num_our_secs); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_ram_num_our_secs; + ble_store_ram_num_our_secs++; + } + + ble_store_ram_our_secs[idx] = *value_sec; + + return 0; +#else + return BLE_HS_ENOENT; +#endif + +} + +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) || MYNEWT_VAL(BLE_STORE_MAX_CCCDS) +static int +ble_store_ram_delete_obj(void *values, int value_size, int idx, + int *num_values) +{ + uint8_t *dst; + uint8_t *src; + uint8_t move_count; + + (*num_values)--; + if (idx < *num_values) { + dst = values; + dst += idx * value_size; + src = dst + value_size; + + move_count = *num_values - idx; + memmove(dst, src, move_count); + } + + return 0; +} +#endif + +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) +static int +ble_store_ram_delete_sec(const struct ble_store_key_sec *key_sec, + struct ble_store_value_sec *value_secs, + int *num_value_secs) +{ + int idx; + int rc; + + idx = ble_store_ram_find_sec(key_sec, value_secs, *num_value_secs); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + rc = ble_store_ram_delete_obj(value_secs, sizeof *value_secs, idx, + num_value_secs); + if (rc != 0) { + return rc; + } + + return 0; +} +#endif + +static int +ble_store_ram_delete_our_sec(const struct ble_store_key_sec *key_sec) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) + int rc; + + rc = ble_store_ram_delete_sec(key_sec, ble_store_ram_our_secs, + &ble_store_ram_num_our_secs); + if (rc != 0) { + return rc; + } + return 0; +#else + return BLE_HS_ENOENT; +#endif + +} + +static int +ble_store_ram_delete_peer_sec(const struct ble_store_key_sec *key_sec) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) + int rc; + + rc = ble_store_ram_delete_sec(key_sec, ble_store_ram_peer_secs, + &ble_store_ram_num_peer_secs); + if (rc != 0) { + return rc; + } + return 0; +#else + return BLE_HS_ENOENT; +#endif + +} + +static int +ble_store_ram_read_peer_sec(const struct ble_store_key_sec *key_sec, + struct ble_store_value_sec *value_sec) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) + int idx; + + idx = ble_store_ram_find_sec(key_sec, ble_store_ram_peer_secs, + ble_store_ram_num_peer_secs); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_sec = ble_store_ram_peer_secs[idx]; + return 0; +#else + return BLE_HS_ENOENT; +#endif + +} + +static int +ble_store_ram_write_peer_sec(const struct ble_store_value_sec *value_sec) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_BONDS) + struct ble_store_key_sec key_sec; + int idx; + + BLE_HS_LOG(DEBUG, "persisting peer sec; "); + ble_store_ram_print_value_sec(value_sec); + + ble_store_key_from_value_sec(&key_sec, value_sec); + idx = ble_store_ram_find_sec(&key_sec, ble_store_ram_peer_secs, + ble_store_ram_num_peer_secs); + if (idx == -1) { + if (ble_store_ram_num_peer_secs >= MYNEWT_VAL(BLE_STORE_MAX_BONDS)) { + BLE_HS_LOG(DEBUG, "error persisting peer sec; too many entries " + "(%d)\n", ble_store_ram_num_peer_secs); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_ram_num_peer_secs; + ble_store_ram_num_peer_secs++; + } + + ble_store_ram_peer_secs[idx] = *value_sec; + return 0; +#else + return BLE_HS_ENOENT; +#endif + +} + +/***************************************************************************** + * $cccd * + *****************************************************************************/ + +#if MYNEWT_VAL(BLE_STORE_MAX_CCCDS) +static int +ble_store_ram_find_cccd(const struct ble_store_key_cccd *key) +{ + struct ble_store_value_cccd *cccd; + int skipped; + int i; + + skipped = 0; + for (i = 0; i < ble_store_ram_num_cccds; i++) { + cccd = ble_store_ram_cccds + i; + + if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) { + if (ble_addr_cmp(&cccd->peer_addr, &key->peer_addr)) { + continue; + } + } + + if (key->chr_val_handle != 0) { + if (cccd->chr_val_handle != key->chr_val_handle) { + continue; + } + } + + if (key->idx > skipped) { + skipped++; + continue; + } + + return i; + } + + return -1; +} +#endif + +static int +ble_store_ram_delete_cccd(const struct ble_store_key_cccd *key_cccd) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CCCDS) + int idx; + int rc; + + idx = ble_store_ram_find_cccd(key_cccd); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + rc = ble_store_ram_delete_obj(ble_store_ram_cccds, + sizeof *ble_store_ram_cccds, + idx, + &ble_store_ram_num_cccds); + if (rc != 0) { + return rc; + } + return 0; +#else + return BLE_HS_ENOENT; +#endif + +} + +static int +ble_store_ram_read_cccd(const struct ble_store_key_cccd *key_cccd, + struct ble_store_value_cccd *value_cccd) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CCCDS) + int idx; + + idx = ble_store_ram_find_cccd(key_cccd); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_cccd = ble_store_ram_cccds[idx]; + + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +static int +ble_store_ram_write_cccd(const struct ble_store_value_cccd *value_cccd) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CCCDS) + struct ble_store_key_cccd key_cccd; + int idx; + + ble_store_key_from_value_cccd(&key_cccd, value_cccd); + idx = ble_store_ram_find_cccd(&key_cccd); + if (idx == -1) { + if (ble_store_ram_num_cccds >= MYNEWT_VAL(BLE_STORE_MAX_CCCDS)) { + BLE_HS_LOG(DEBUG, "error persisting cccd; too many entries (%d)\n", + ble_store_ram_num_cccds); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_ram_num_cccds; + ble_store_ram_num_cccds++; + } + + ble_store_ram_cccds[idx] = *value_cccd; + return 0; +#else + return BLE_HS_ENOENT; +#endif + +} + +/***************************************************************************** + * $csfc * + *****************************************************************************/ + +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) +static int +ble_store_ram_find_csfc(const struct ble_store_key_csfc *key) +{ + struct ble_store_value_csfc *csfc; + int skipped; + int i; + + skipped = 0; + for (i = 0; i < ble_store_ram_num_csfcs; i++) { + csfc = ble_store_ram_csfcs + i; + + if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) { + if (ble_addr_cmp(&csfc->peer_addr, &key->peer_addr)) { + continue; + } + } + + if (key->idx > skipped) { + skipped++; + continue; + } + + return i; + } + + return -1; +} +#endif + +static int +ble_store_ram_delete_csfc(const struct ble_store_key_csfc *key_csfc) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + int idx; + int rc; + + idx = ble_store_ram_find_csfc(key_csfc); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + rc = ble_store_ram_delete_obj(ble_store_ram_csfcs, + sizeof *ble_store_ram_csfcs, + idx, + &ble_store_ram_num_csfcs); + if (rc != 0) { + return rc; + } + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +static int +ble_store_ram_read_csfc(const struct ble_store_key_csfc *key_csfc, + struct ble_store_value_csfc *value_csfc) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + int idx; + + idx = ble_store_ram_find_csfc(key_csfc); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_csfc = ble_store_ram_csfcs[idx]; + + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +static int +ble_store_ram_write_csfc(const struct ble_store_value_csfc *value_csfc) +{ +#if MYNEWT_VAL(BLE_STORE_MAX_CSFCS) + struct ble_store_key_csfc key_csfc; + int idx; + + ble_store_key_from_value_csfc(&key_csfc, value_csfc); + idx = ble_store_ram_find_csfc(&key_csfc); + if (idx == -1) { + if (ble_store_ram_num_csfcs >= MYNEWT_VAL(BLE_STORE_MAX_CSFCS)) { + BLE_HS_LOG(DEBUG, "error persisting csfc; too many entries (%d)\n", + ble_store_ram_num_csfcs); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_ram_num_csfcs; + ble_store_ram_num_csfcs++; + } + + ble_store_ram_csfcs[idx] = *value_csfc; + return 0; +#else + return BLE_HS_ENOENT; +#endif +} + +/***************************************************************************** + * $ead * + *****************************************************************************/ +#if MYNEWT_VAL(ENC_ADV_DATA) +static int +ble_store_ram_find_ead(const struct ble_store_key_ead *key) +{ + struct ble_store_value_ead *ead; + int skipped; + int i; + + skipped = 0; + for (i = 0; i < ble_store_ram_num_eads; i++) { + ead = ble_store_ram_eads + i; + + if (ble_addr_cmp(&key->peer_addr, BLE_ADDR_ANY)) { + if (ble_addr_cmp(&ead->peer_addr, &key->peer_addr)) { + continue; + } + } + + if (key->idx > skipped) { + skipped++; + continue; + } + + return i; + } + + return -1; +} + +static int +ble_store_ram_delete_ead(const struct ble_store_key_ead *key_ead) +{ + int idx; + int rc; + + idx = ble_store_ram_find_ead(key_ead); + if (idx == -1) { + return BLE_HS_ENOENT; + } + rc = ble_store_ram_delete_obj(ble_store_ram_eads, + sizeof *ble_store_ram_eads, + idx, + &ble_store_ram_num_eads); + if (rc != 0) { + return rc; + } + + return 0; +} + +static int +ble_store_ram_read_ead(const struct ble_store_key_ead *key_ead, + struct ble_store_value_ead *value_ead) +{ + int idx; + + idx = ble_store_ram_find_ead(key_ead); + if (idx == -1) { + return BLE_HS_ENOENT; + } + + *value_ead = ble_store_ram_eads[idx]; + return 0; +} + +static int +ble_store_ram_write_ead(const struct ble_store_value_ead *value_ead) +{ + struct ble_store_key_ead key_ead; + int idx; + + ble_store_key_from_value_ead(&key_ead, value_ead); + idx = ble_store_ram_find_ead(&key_ead); + if (idx == -1) { + if (ble_store_ram_num_eads >= MYNEWT_VAL(BLE_STORE_MAX_EADS)) { + BLE_HS_LOG(DEBUG, "error persisting ead; too many entries (%d)\n", + ble_store_ram_num_eads); + return BLE_HS_ESTORE_CAP; + } + + idx = ble_store_ram_num_eads; + ble_store_ram_num_eads++; + } + + ble_store_ram_eads[idx] = *value_ead; + return 0; +} +#endif + +/***************************************************************************** + * $api * + *****************************************************************************/ + +/** + * Searches the database for an object matching the specified criteria. + * + * @return 0 if a key was found; else BLE_HS_ENOENT. + */ +int +ble_store_ram_read(int obj_type, const union ble_store_key *key, + union ble_store_value *value) +{ + int rc; + + switch (obj_type) { + case BLE_STORE_OBJ_TYPE_PEER_SEC: + /* An encryption procedure (bonding) is being attempted. The nimble + * stack is asking us to look in our key database for a long-term key + * corresponding to the specified ediv and random number. + * + * Perform a key lookup and populate the context object with the + * result. The nimble stack will use this key if this function returns + * success. + */ + BLE_HS_LOG(DEBUG, "looking up peer sec; "); + ble_store_ram_print_key_sec(&key->sec); + BLE_HS_LOG(DEBUG, "\n"); + rc = ble_store_ram_read_peer_sec(&key->sec, &value->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_OUR_SEC: + BLE_HS_LOG(DEBUG, "looking up our sec; "); + ble_store_ram_print_key_sec(&key->sec); + BLE_HS_LOG(DEBUG, "\n"); + rc = ble_store_ram_read_our_sec(&key->sec, &value->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_CCCD: + rc = ble_store_ram_read_cccd(&key->cccd, &value->cccd); + return rc; + + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_ram_read_csfc(&key->csfc, &value->csfc); + return rc; + +#if MYNEWT_VAL(ENC_ADV_DATA) + case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: + rc = ble_store_ram_read_ead(&key->ead, &value->ead); + return rc; +#endif + + default: + return BLE_HS_ENOTSUP; + } +} + +/** + * Adds the specified object to the database. + * + * @return 0 on success; BLE_HS_ESTORE_CAP if the database + * is full. + */ +int +ble_store_ram_write(int obj_type, const union ble_store_value *val) +{ + int rc; + + switch (obj_type) { + case BLE_STORE_OBJ_TYPE_PEER_SEC: + rc = ble_store_ram_write_peer_sec(&val->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_OUR_SEC: + rc = ble_store_ram_write_our_sec(&val->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_CCCD: + rc = ble_store_ram_write_cccd(&val->cccd); + return rc; + + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_ram_write_csfc(&val->csfc); + return rc; + +#if MYNEWT_VAL(ENC_ADV_DATA) + case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: + rc = ble_store_ram_write_ead(&val->ead); + return rc; +#endif + + default: + return BLE_HS_ENOTSUP; + } +} + +int +ble_store_ram_delete(int obj_type, const union ble_store_key *key) +{ + int rc; + + switch (obj_type) { + case BLE_STORE_OBJ_TYPE_PEER_SEC: + rc = ble_store_ram_delete_peer_sec(&key->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_OUR_SEC: + rc = ble_store_ram_delete_our_sec(&key->sec); + return rc; + + case BLE_STORE_OBJ_TYPE_CCCD: + rc = ble_store_ram_delete_cccd(&key->cccd); + return rc; + + case BLE_STORE_OBJ_TYPE_CSFC: + rc = ble_store_ram_delete_csfc(&key->csfc); + return rc; + +#if MYNEWT_VAL(ENC_ADV_DATA) + case BLE_STORE_OBJ_TYPE_ENC_ADV_DATA: + rc = ble_store_ram_delete_ead(&key->ead); + return rc; +#endif + + default: + return BLE_HS_ENOTSUP; + } +} + +void +ble_store_ram_init(void) +{ + /* Ensure this function only gets called by sysinit. */ + SYSINIT_ASSERT_ACTIVE(); + + ble_hs_cfg.store_read_cb = ble_store_ram_read; + ble_hs_cfg.store_write_cb = ble_store_ram_write; + ble_hs_cfg.store_delete_cb = ble_store_ram_delete; + + /* Re-initialize BSS values in case of unit tests. */ + ble_store_ram_num_our_secs = 0; + ble_store_ram_num_peer_secs = 0; + ble_store_ram_num_cccds = 0; + ble_store_ram_num_csfcs = 0; +#if MYNEWT_VAL(ENC_ADV_DATA) + ble_store_ram_num_eads = 0; +#endif +} diff --git a/src/nimble/nimble/host/util/src/addr.c b/src/nimble/nimble/host/util/src/addr.c index b0081aee..2f6695b0 100644 --- a/src/nimble/nimble/host/util/src/addr.c +++ b/src/nimble/nimble/host/util/src/addr.c @@ -18,8 +18,8 @@ */ #include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/host/util/util.h" -#include "../../src/ble_hs_hci_priv.h" +#include "nimble/nimble/host/util/include/host/util/util.h" +#include "nimble/nimble/host/src/ble_hs_hci_priv.h" #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED #include "esp_bt.h" diff --git a/src/nimble/nimble/include/nimble/ble.h b/src/nimble/nimble/include/nimble/ble.h index 19988da1..3de02a7b 100644 --- a/src/nimble/nimble/include/nimble/ble.h +++ b/src/nimble/nimble/include/nimble/ble.h @@ -101,7 +101,7 @@ struct ble_mbuf_hdr_rxinfo #define BLE_MBUF_HDR_F_EXT_ADV (0x0800) #define BLE_MBUF_HDR_F_RESOLVED (0x0400) #define BLE_MBUF_HDR_F_AUX_PTR_WAIT (0x0200) -#define BLE_MBUF_HDR_F_AUX_INVALID (0x0100) +#define BLE_MBUF_HDR_F_AUX_PTR_FAILED (0x0100) #define BLE_MBUF_HDR_F_CRC_OK (0x0080) #define BLE_MBUF_HDR_F_DEVMATCH (0x0040) #define BLE_MBUF_HDR_F_MIC_FAILURE (0x0020) @@ -118,11 +118,16 @@ struct ble_mbuf_hdr_txinfo uint16_t pyld_len; }; +struct ble_mbuf_hdr_txiso { + uint16_t packet_seq_num; +}; + struct ble_mbuf_hdr { union { struct ble_mbuf_hdr_rxinfo rxinfo; struct ble_mbuf_hdr_txinfo txinfo; + struct ble_mbuf_hdr_txiso txiso; }; uint32_t beg_cputime; uint32_t rem_usecs; @@ -146,9 +151,6 @@ struct ble_mbuf_hdr #define BLE_MBUF_HDR_SCAN_RSP_RXD(hdr) \ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_SCAN_RSP_RXD)) -#define BLE_MBUF_HDR_AUX_INVALID(hdr) \ - (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_INVALID)) - #define BLE_MBUF_HDR_WAIT_AUX(hdr) \ (!!((hdr)->rxinfo.flags & BLE_MBUF_HDR_F_AUX_PTR_WAIT)) diff --git a/src/nimble/nimble/include/nimble/hci_common.h b/src/nimble/nimble/include/nimble/hci_common.h index 3bfb5e62..479e4144 100644 --- a/src/nimble/nimble/include/nimble/hci_common.h +++ b/src/nimble/nimble/include/nimble/hci_common.h @@ -27,7 +27,7 @@ #ifndef H_BLE_HCI_COMMON_ #define H_BLE_HCI_COMMON_ -#include "nimble/nimble/include/nimble/ble.h" +#include "ble.h" #include "nimble/nimble/transport/include/nimble/transport.h" #ifdef __cplusplus @@ -600,6 +600,7 @@ struct ble_hci_le_set_ext_adv_params_cp { uint8_t sid; uint8_t scan_req_notif; } __attribute__((packed)); + struct ble_hci_le_set_ext_adv_params_rp { int8_t tx_power; } __attribute__((packed)); @@ -714,6 +715,18 @@ struct ble_hci_le_ext_create_conn_cp { struct conn_params conn_params[0]; } __attribute__((packed)); +#define BLE_HCI_LE_EXT_CREATE_CONN_V2 (0x0085) +struct ble_hci_le_ext_create_conn_v2_cp { + uint8_t adv_handle; + uint8_t subevent; + uint8_t filter_policy; + uint8_t own_addr_type; + uint8_t peer_addr_type; + uint8_t peer_addr[6]; + uint8_t init_phy_mask; + struct conn_params conn_params[0]; +} __attribute__((packed)); + #define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_FILTER 0x01 #define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DISABLED 0x02 #define BLE_HCI_LE_PERIODIC_ADV_CREATE_SYNC_OPT_DUPLICATES 0x04 @@ -784,14 +797,88 @@ struct ble_hci_le_set_privacy_mode_cp { #define BLE_HCI_OCF_LE_RX_TEST_V3 (0x004F) #define BLE_HCI_OCF_LE_TX_TEST_V3 (0x0050) + #define BLE_HCI_OCF_LE_SET_CONNLESS_CTE_TX_PARAMS (0x0051) +struct ble_hci_le_set_connless_cte_tx_params_cp { + uint8_t adv_handle; + uint8_t cte_length; + uint8_t cte_type; + uint8_t cte_count; + uint8_t switching_pattern_len; + uint8_t switching_pattern[0]; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONNLESS_CTE_TX_ENABLE (0x0052) +struct ble_hci_le_set_connless_cte_tx_enable_cp { + uint8_t adv_handle; + uint8_t cte_enable; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONNLESS_IQ_SAMPLING_ENABLE (0x0053) +struct ble_hci_le_set_connless_iq_sampling_enable_cp { + uint16_t sync_handle; + uint8_t sampling_enable; + uint8_t slot_durations; + uint8_t max_sampled_ctes; + uint8_t switching_pattern_len; + uint8_t antenna_ids[0]; +} __attribute__((packed)); + +struct ble_hci_le_set_connless_iq_sampling_enable_rp { + uint16_t sync_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONN_CTE_RX_PARAMS (0x0054) +struct ble_hci_le_set_conn_cte_rx_params_cp { + uint16_t conn_handle; + uint8_t sampling_enable; + uint8_t slot_durations; + uint8_t switching_pattern_len; + uint8_t antenna_ids[0]; +} __attribute__((packed)); +struct ble_hci_le_set_conn_cte_rx_params_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONN_CTE_TX_PARAMS (0x0055) +struct ble_hci_le_set_conn_cte_tx_params_cp { + uint16_t conn_handle; + uint8_t cte_types; + uint8_t switching_pattern_len; + uint8_t antenna_ids[0]; +} __attribute__((packed)); +struct ble_hci_le_set_conn_cte_tx_params_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONN_CTE_REQ_ENABLE (0x0056) +struct ble_gap_conn_cte_req_enable_cp { + uint16_t conn_handle; + uint8_t enable; + uint16_t cte_request_interval; + uint8_t requested_cte_length; + uint8_t requested_cte_type; +} __attribute__((packed)); +struct ble_gap_conn_cte_req_enable_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_SET_CONN_CTE_RESP_ENABLE (0x0057) +struct ble_hci_le_set_conn_cte_rsp_enable_cp { + uint16_t conn_handle; + uint8_t enable; +} __attribute__((packed)); +struct ble_hci_le_set_conn_cte_rsp_enable_rp { + uint16_t conn_handle; +} __attribute__((packed)); + #define BLE_HCI_OCF_LE_RD_ANTENNA_INFO (0x0058) +struct ble_hci_le_rd_antenna_info_rp { + uint8_t switch_sampling_rates; + uint8_t num_antennae; + uint8_t max_switch_pattern_len; + uint8_t max_cte_len; +} __attribute__((packed)); #define BLE_HCI_OCF_LE_PERIODIC_ADV_RECEIVE_ENABLE (0x0059) struct ble_hci_le_periodic_adv_receive_enable_cp { @@ -842,112 +929,105 @@ struct ble_hci_le_set_default_periodic_sync_transfer_params_cp { #define BLE_HCI_OCF_LE_GENERATE_DHKEY_V2 (0x005E) #define BLE_HCI_OCF_LE_MODIFY_SCA (0x005F) -#if MYNEWT_VAL(BLE_ISO) #define BLE_HCI_OCF_LE_READ_ISO_TX_SYNC (0x0061) struct ble_hci_le_read_iso_tx_sync_cp { uint16_t conn_handle; } __attribute__((packed)); - struct ble_hci_le_read_iso_tx_sync_rp { uint16_t conn_handle; uint16_t packet_seq_num; - uint32_t timestamp; - uint8_t timeoffset[3]; + uint32_t tx_timestamp; + uint8_t time_offset[3]; } __attribute__((packed)); -#define BLE_HCI_LE_SET_CIG_CIS_MAX_NUM (0x1F) -#define BLE_HCI_OCF_LE_SET_CIG_PARAM (0x0062) +#define BLE_HCI_OCF_LE_SET_CIG_PARAMS (0x0062) struct ble_hci_le_cis_params { uint8_t cis_id; - uint16_t max_sdu_mtos; - uint16_t max_sdu_stom; - uint8_t phy_mtos; - uint8_t phy_stom; - uint8_t rnt_mtos; - uint8_t rnt_stom; + uint16_t max_sdu_c_to_p; + uint16_t max_sdu_p_to_c; + uint8_t phy_c_to_p; + uint8_t phy_p_to_c; + uint8_t rnt_c_to_p; + uint8_t rnt_p_to_c; } __attribute__((packed)); - struct ble_hci_le_set_cig_params_cp { uint8_t cig_id; - uint8_t sdu_interval_mtos[3]; - uint8_t sdu_interval_stom[3]; - uint8_t sca; + uint8_t sdu_interval_c_to_p[3]; + uint8_t sdu_interval_p_to_c[3]; + uint8_t worst_sca; uint8_t packing; uint8_t framing; - uint16_t max_latency_mtos; - uint16_t max_latency_stom; - uint8_t cis_cnt; - struct ble_hci_le_cis_params cis_params[0]; + uint16_t max_latency_c_to_p; + uint16_t max_latency_p_to_c; + uint8_t cis_count; + struct ble_hci_le_cis_params cis[0]; } __attribute__((packed)); - struct ble_hci_le_set_cig_params_rp { uint8_t cig_id; - uint8_t cis_cnt; - uint16_t cis_handle[0]; + uint8_t cis_count; + uint16_t conn_handle[0]; } __attribute__((packed)); -#if MYNEWT_VAL(BLE_ISO_TEST) -#define BLE_HCI_OCF_LE_SET_CIG_PARAM_TEST (0x0063) +#define BLE_HCI_OCF_LE_SET_CIG_PARAMS_TEST (0x0063) struct ble_hci_le_cis_params_test { uint8_t cis_id; uint8_t nse; - uint16_t max_sdu_mtos; - uint16_t max_sdu_stom; - uint16_t max_pdu_mtos; - uint16_t max_pdu_stom; - uint8_t phy_mtos; - uint8_t phy_stom; - uint8_t bn_mtos; - uint8_t bn_stom; + uint16_t max_sdu_c_to_p; + uint16_t max_sdu_p_to_c; + uint16_t max_pdu_c_to_p; + uint16_t max_pdu_p_to_c; + uint8_t phy_c_to_p; + uint8_t phy_p_to_c; + uint8_t bn_c_to_p; + uint8_t bn_p_to_c; } __attribute__((packed)); - struct ble_hci_le_set_cig_params_test_cp { uint8_t cig_id; - uint8_t sdu_interval_mtos[3]; - uint8_t sdu_interval_stom[3]; - uint8_t ft_mtos; - uint8_t ft_stom; + uint8_t sdu_interval_c_to_p[3]; + uint8_t sdu_interval_p_to_c[3]; + uint8_t ft_c_to_p; + uint8_t ft_p_to_c; uint16_t iso_interval; - uint8_t sca; + uint8_t worst_sca; uint8_t packing; uint8_t framing; - uint8_t cis_cnt; - struct ble_hci_le_cis_params_test cis_params[0]; + uint8_t cis_count; + struct ble_hci_le_cis_params_test cis[0]; +} __attribute__((packed)); +struct ble_hci_le_set_cig_params_test_rp { + uint8_t cig_id; + uint8_t cis_count; + uint16_t conn_handle[0]; } __attribute__((packed)); -#endif -#define BLE_HCI_LE_CREATE_CIS_MAX_CIS_NUM (0x1F) #define BLE_HCI_OCF_LE_CREATE_CIS (0x0064) struct ble_hci_le_create_cis_params { uint16_t cis_handle; uint16_t conn_handle; } __attribute__((packed)); - struct ble_hci_le_create_cis_cp { - uint8_t cis_cnt; - struct ble_hci_le_create_cis_params params[0]; + uint8_t cis_count; + struct ble_hci_le_create_cis_params cis[0]; } __attribute__((packed)); #define BLE_HCI_OCF_LE_REMOVE_CIG (0x0065) struct ble_hci_le_remove_cig_cp { uint8_t cig_id; } __attribute__((packed)); - struct ble_hci_le_remove_cig_rp { uint8_t cig_id; } __attribute__((packed)); #define BLE_HCI_OCF_LE_ACCEPT_CIS_REQ (0x0066) struct ble_hci_le_accept_cis_request_cp { - uint16_t cis_handle; + uint16_t conn_handle; } __attribute__((packed)); #define BLE_HCI_OCF_LE_REJECT_CIS_REQ (0x0067) struct ble_hci_le_reject_cis_request_cp { - uint16_t cis_handle; + uint16_t conn_handle; uint8_t reason; } __attribute__((packed)); - struct ble_hci_le_reject_cis_request_rp { uint16_t conn_handle; } __attribute__((packed)); @@ -956,11 +1036,11 @@ struct ble_hci_le_reject_cis_request_rp { struct ble_hci_le_create_big_cp { uint8_t big_handle; uint8_t adv_handle; - uint8_t bis_cnt; + uint8_t num_bis; uint8_t sdu_interval[3]; uint16_t max_sdu; uint16_t max_transport_latency; - uint8_t rnt; + uint8_t rtn; uint8_t phy; uint8_t packing; uint8_t framing; @@ -968,12 +1048,11 @@ struct ble_hci_le_create_big_cp { uint8_t broadcast_code[16]; } __attribute__((packed)); -#if MYNEWT_VAL(BLE_ISO_TEST) #define BLE_HCI_OCF_LE_CREATE_BIG_TEST (0x0069) struct ble_hci_le_create_big_test_cp { uint8_t big_handle; uint8_t adv_handle; - uint8_t bis_cnt; + uint8_t num_bis; uint8_t sdu_interval[3]; uint16_t iso_interval; uint8_t nse; @@ -988,7 +1067,6 @@ struct ble_hci_le_create_big_test_cp { uint8_t encryption; uint8_t broadcast_code[16]; } __attribute__((packed)); -#endif #define BLE_HCI_OCF_LE_TERMINATE_BIG (0x006a) struct ble_hci_le_terminate_big_cp { @@ -996,78 +1074,113 @@ struct ble_hci_le_terminate_big_cp { uint8_t reason; } __attribute__((packed)); -#define BLE_HCI_LE_BIG_CREATE_SYNC_LEN_MIN (25) #define BLE_HCI_OCF_LE_BIG_CREATE_SYNC (0x006b) struct ble_hci_le_big_create_sync_cp { uint8_t big_handle; uint16_t sync_handle; - uint8_t big_cnt; uint8_t encryption; uint8_t broadcast_code[16]; uint8_t mse; - uint16_t timeout; + uint16_t sync_timeout; + uint8_t num_bis; uint8_t bis[0]; } __attribute__((packed)); #define BLE_HCI_OCF_LE_BIG_TERMINATE_SYNC (0x006c) -struct ble_hci_le_terminate_big_sync_cp { +struct ble_hci_le_big_terminate_sync_cp { + uint8_t big_handle; +} __attribute__((packed)); +struct ble_hci_le_big_terminate_sync_rp { uint8_t big_handle; } __attribute__((packed)); -#endif #define BLE_HCI_OCF_LE_REQ_PEER_SCA (0x006d) struct ble_hci_le_request_peer_sca_cp { uint16_t conn_handle; } __attribute__((packed)); -#if MYNEWT_VAL(BLE_ISO) #define BLE_HCI_OCF_LE_SETUP_ISO_DATA_PATH (0x006e) -struct ble_hci_le_iso_setup_data_path_cp { - uint16_t iso_handle; - uint8_t direction; - uint8_t id; +struct ble_hci_le_setup_iso_data_path_cp { + uint16_t conn_handle; + uint8_t data_path_dir; + uint8_t data_path_id; uint8_t codec_id[5]; uint8_t controller_delay[3]; - uint8_t codec_conf_len; - uint8_t codec_conf[0]; + uint8_t codec_config_len; + uint8_t codec_config[0]; +} __attribute__((packed)); +struct ble_hci_le_setup_iso_data_path_rp { + uint16_t conn_handle; } __attribute__((packed)); -#define BLE_HCI_LE_REMOVE_INPUT_DATA_PATH_BIT (0x01) -#define BLE_HCI_LE_REMOVE_OUTPUT_DATA_PATH_BIT (0x02) #define BLE_HCI_OCF_LE_REMOVE_ISO_DATA_PATH (0x006f) -struct ble_hci_le_iso_remove_data_path_cp { - uint16_t iso_handle; - uint8_t direction; +struct ble_hci_le_remove_iso_data_path_cp { + uint16_t conn_handle; + uint8_t data_path_dir; +} __attribute__((packed)); +struct ble_hci_le_remove_iso_data_path_rp { + uint16_t conn_handle; } __attribute__((packed)); -#if MYNEWT_VAL(BLE_ISO_TEST) #define BLE_HCI_OCF_LE_ISO_TRANSMIT_TEST (0x0070) struct ble_hci_le_iso_transmit_test_cp { - uint16_t iso_handle; + uint16_t conn_handle; uint8_t payload_type; } __attribute__((packed)); +struct ble_hci_le_iso_transmit_test_rp { + uint16_t conn_handle; +} __attribute__((packed)); #define BLE_HCI_OCF_LE_ISO_RECEIVE_TEST (0x0071) struct ble_hci_le_iso_receive_test_cp { - uint16_t iso_handle; + uint16_t conn_handle; + uint8_t payload_type; +} __attribute__((packed)); +struct ble_hci_le_iso_receive_test_rp { + uint16_t conn_handle; } __attribute__((packed)); #define BLE_HCI_OCF_LE_ISO_READ_TEST_COUNTERS (0x0072) struct ble_hci_le_iso_read_test_counters_cp { - uint16_t iso_handle; + uint16_t conn_handle; +} __attribute__((packed)); +struct ble_hci_le_iso_read_test_counters_rp { + uint16_t conn_handle; + uint32_t received_sdu_count; + uint32_t missed_sdu_count; + uint32_t failed_sdu_count; } __attribute__((packed)); #define BLE_HCI_OCF_LE_ISO_TEST_END (0x0073) struct ble_hci_le_iso_test_end_cp { - uint16_t iso_handle; + uint16_t conn_handle; +} __attribute__((packed)); +struct ble_hci_le_iso_test_end_rp { + uint16_t conn_handle; + uint32_t received_sdu_count; + uint32_t missed_sdu_count; + uint32_t failed_sdu_count; } __attribute__((packed)); -#endif -#endif -#define BLE_HCI_OCF_LE_SET_HOST_FEAT (0x0074) -struct ble_hci_le_set_host_feat_cp { +#define BLE_HCI_OCF_LE_SET_HOST_FEATURE (0x0074) +struct ble_hci_le_set_host_feature_cp { uint8_t bit_num; - uint8_t val; + uint8_t bit_val; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_READ_ISO_LINK_QUALITY (0x0075) +struct ble_hci_le_read_iso_link_quality_cp { + uint16_t conn_handle; +} __attribute__((packed)); +struct ble_hci_le_read_iso_link_quality_rp { + uint16_t conn_handle; + uint32_t tx_unacked_pkts; + uint32_t tx_flushed_pkts; + uint32_t tx_last_subevent_pkts; + uint32_t retransmitted_pkts; + uint32_t crc_error_pkts; + uint32_t rx_unreceived_pkts; + uint32_t duplicate_pkts; } __attribute__((packed)); #define BLE_HCI_OCF_LE_ENH_READ_TRANSMIT_POWER_LEVEL (0x0076) @@ -1111,7 +1224,7 @@ struct ble_hci_le_set_transmit_power_report_enable_cp { uint8_t remote_enable; } __attribute__((packed)); -#define BLE_HCI_OCF_LE_SET_DATA_ADDR_CHANGE (0x007C) +#define BLE_HCI_OCF_LE_SET_DATA_ADDR_CHANGE (0x007C) struct ble_hci_le_set_data_addr_change_cp { uint8_t adv_handle; uint8_t change_reason; @@ -1136,6 +1249,63 @@ struct ble_hci_le_subrate_req_cp { uint16_t supervision_tmo; } __attribute__((packed)); +#define BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM_V2 (0x007F) +struct ble_hci_le_set_ext_adv_params_v2_cp { + struct ble_hci_le_set_ext_adv_params_cp cmd; + uint8_t pri_phy_opt; + uint8_t sec_phy_opt; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SUBEV_DATA (0x0082) +struct periodic_adv_subevents { + uint8_t subevent; + uint8_t response_slot_start; + uint8_t response_slot_count; + uint8_t subevent_data_length; + uint8_t subevent_data[0]; +} __attribute__((packed)); + +struct ble_hci_le_set_periodic_adv_subev_data_cp { + uint8_t adv_handle; + uint8_t num_subevents; + struct periodic_adv_subevents subevents[0]; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_RESPONSE_DATA (0x0083) +struct ble_hci_le_set_periodic_adv_response_data { + uint16_t sync_handle; + uint16_t request_event; + uint8_t request_subevent; + uint8_t response_subevent; + uint8_t response_slot; + uint8_t response_data_length; + uint8_t response_data[0]; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_SYNC_SUBEVENT (0x0084) +struct ble_hci_le_set_periodic_adv_sync_subevent { + uint16_t sync_handle; + uint16_t periodic_adv_properties; + uint8_t num_subevents; + uint8_t subevents[0]; +} __attribute__((packed)); +struct ble_hci_le_set_periodic_adv_sync_subevent_rp { + uint16_t sync_handle; +} __attribute__((packed)); + +#define BLE_HCI_OCF_LE_SET_PERIODIC_ADV_PARAMS_V2 (0x0086) +struct ble_hci_le_set_periodic_adv_params_v2 { + uint8_t adv_handle; + uint16_t min_itvl; + uint16_t max_itvl; + uint16_t props; + uint8_t num_subevents; + uint8_t subevent_interval; + uint8_t response_slot_delay; + uint8_t response_slot_spacing; + uint8_t num_response_slots; +} __attribute__((packed)); + /* --- Vendor specific commands (OGF 0x003F) */ /* Read Random Static Address */ #define BLE_HCI_OCF_VS_RD_STATIC_ADDR (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0001)) @@ -1154,27 +1324,49 @@ struct ble_hci_vs_set_tx_pwr_rp { int8_t tx_power; } __attribute__((packed)); -#define BLE_HCI_OCF_VS_CSS (0x0003) -struct ble_hci_vs_css_cp { - uint8_t opcode; -} __attribute__((packed)); -#define BLE_HCI_VS_CSS_OP_CONFIGURE 0x01 +#define BLE_HCI_OCF_VS_CSS_CONFIGURE (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0003)) struct ble_hci_vs_css_configure_cp { - uint8_t opcode; uint32_t slot_us; uint32_t period_slots; } __attribute__((packed)); -#define BLE_HCI_VS_CSS_OP_SET_NEXT_SLOT 0x02 +#define BLE_HCI_OCF_VS_CSS_ENABLE (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0004)) +struct ble_hci_vs_css_enable_cp { + uint8_t enable; +} __attribute__((packed)); +#define BLE_HCI_OCF_VS_CSS_SET_NEXT_SLOT (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0005)) struct ble_hci_vs_css_set_next_slot_cp { - uint8_t opcode; uint16_t slot_idx; } __attribute__((packed)); -#define BLE_HCI_VS_CSS_OP_SET_CONN_SLOT 0x03 +#define BLE_HCI_OCF_VS_CSS_SET_CONN_SLOT (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0006)) struct ble_hci_vs_css_set_conn_slot_cp { - uint8_t opcode; uint16_t conn_handle; uint16_t slot_idx; } __attribute__((packed)); +#define BLE_HCI_OCF_VS_CSS_READ_CONN_SLOT (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0007)) +struct ble_hci_vs_css_read_conn_slot_cp { + uint16_t conn_handle; +} __attribute__((packed)); +struct ble_hci_vs_css_read_conn_slot_rp { + uint16_t conn_handle; + uint16_t slot_idx; +} __attribute__((packed)); +#define BLE_HCI_OCF_VS_SET_DATA_LEN (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0008)) +struct ble_hci_vs_set_data_len_cp { + uint16_t conn_handle; + uint16_t tx_octets; + uint16_t tx_time; + uint16_t rx_octets; + uint16_t rx_time; +} __attribute__((packed)); +struct ble_hci_vs_set_data_len_rp { + uint16_t conn_handle; +} __attribute__((packed)); +#define BLE_HCI_OCF_VS_SET_ANTENNA (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0009)) +struct ble_hci_vs_set_antenna_cp { + uint8_t antenna; +} __attribute__((packed)); + + #define BLE_HCI_OCF_VS_DUPLICATE_EXCEPTION_LIST (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0108)) struct ble_hci_vs_duplicate_exception_list_cp { @@ -1191,6 +1383,11 @@ struct ble_hci_vs_duplicate_exception_list_cp { #define BLE_HCI_OCF_VS_SET_CHAN_SELECT (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0112)) +#define BLE_HCI_OCF_VS_SET_EVT_MASK (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0116)) +struct ble_hci_vs_set_event_mask_cp { + uint32_t event_mask; +} __attribute__((packed)); + /* Command Specific Definitions */ /* --- Set controller to host flow control (OGF 0x03, OCF 0x0031) --- */ #define BLE_HCI_CTLR_TO_HOST_FC_OFF (0) @@ -1231,8 +1428,17 @@ struct ble_hci_vs_duplicate_exception_list_cp { #define BLE_HCI_ADV_PEER_ADDR_MAX (1) /* --- LE advertising channel tx power (OCF 0x0007) */ -#define BLE_HCI_ADV_CHAN_TXPWR_MIN (-20) -#define BLE_HCI_ADV_CHAN_TXPWR_MAX (10) +#if MYNEWT_VAL(BLE_VERSION) == 50 +#define BLE_HCI_ADV_CHAN_TXPWR_MIN (-20) +#define BLE_HCI_ADV_CHAN_TXPWR_MAX (10) +#elif MYNEWT_VAL(BLE_VERSION) == 51 +#define BLE_HCI_ADV_CHAN_TXPWR_MIN (-20) +#define BLE_HCI_ADV_CHAN_TXPWR_MAX (20) +#elif MYNEWT_VAL(BLE_VERSION) >= 52 +#define BLE_HCI_ADV_CHAN_TXPWR_MIN (-127) +#define BLE_HCI_ADV_CHAN_TXPWR_MAX (20) +#endif + /* --- LE set scan enable (OCF 0x000c) */ @@ -1246,8 +1452,6 @@ struct ble_hci_vs_duplicate_exception_list_cp { /* * Advertising filter policy * - * Determines how an advertiser filters scan and connection requests. - * * NONE: no filtering (default value). No whitelist used. * SCAN: process all connection requests but only scans from white list. * CONN: process all scan request but only connection requests from white list @@ -1344,10 +1548,14 @@ struct ble_hci_vs_duplicate_exception_list_cp { #define BLE_HCI_SET_DATALEN_TX_TIME_MAX (0x4290) /* --- LE read/write suggested default data length (OCF 0x0023 and 0x0024) */ -#define BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MIN (0x001b) -#define BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX (0x00fb) -#define BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MIN (0x0148) -#define BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX (0x4290) +#define BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MIN (0x001b) +#define BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX (0x00fb) +#define BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MIN (0x0148) +#if BLE_50_FEATURE_SUPPORT +#define BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX (0x4290) +#else +#define BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX (0x0848) +#endif /* --- LE read maximum default PHY (OCF 0x0030) */ #define BLE_HCI_LE_PHY_1M (1) @@ -1418,11 +1626,22 @@ struct ble_hci_vs_duplicate_exception_list_cp { #define BLE_HCI_PERIODIC_DATA_STATUS_COMPLETE 0x00 #define BLE_HCI_PERIODIC_DATA_STATUS_INCOMPLETE 0x01 #define BLE_HCI_PERIODIC_DATA_STATUS_TRUNCATED 0x02 +#define BLE_HCI_PERIODIC_DATA_STATUS_RX_FAILED 0xFF /* --- LE set privacy mode (OCF 0x004E) */ #define BLE_HCI_PRIVACY_NETWORK (0) #define BLE_HCI_PRIVACY_DEVICE (1) +/* --- LE set cte type (OCF 0x0051) */ +#define BLE_HCI_CTE_TYPE_AOA (0) +#define BLE_HCI_CTE_TYPE_AOD_1US (1) +#define BLE_HCI_CTE_TYPE_AOD_2US (2) + +/* --- LE set allow cte rsp types (OCF 0x0055) */ +#define BLE_HCI_CTE_RSP_ALLOW_AOA_MASK (0x01) +#define BLE_HCI_CTE_RSP_ALLOW_AOD_1US_MASK (0x02) +#define BLE_HCI_CTE_RSP_ALLOW_AOD_2US_MASK (0x04) + /* Event Codes */ #define BLE_HCI_EVCODE_INQUIRY_CMP (0x01) #define BLE_HCI_EVCODE_INQUIRY_RESULT (0x02) @@ -1578,12 +1797,23 @@ struct ble_hci_ev_auth_pyld_tmo { #define BLE_HCI_EVCODE_SAM_STATUS_CHG (0x58) -#define BLE_HCI_EVCODE_VS_DEBUG (0xFF) -struct ble_hci_ev_vs_debug { +#define BLE_HCI_EVCODE_VS (0xff) +struct ble_hci_ev_vs { uint8_t id; uint8_t data[0]; } __attribute__((packed)); +#define BLE_HCI_VS_SUBEV_ID_ASSERT (0x01) +#define BLE_HCI_VS_SUBEV_ID_CSS_SLOT_CHANGED (0x02) +struct ble_hci_ev_vs_css_slot_changed { + uint16_t conn_handle; + uint16_t slot_idx; +}; + +#define BLE_HCI_VS_SUBEV_ID_LLCP_TRACE (0x17) + +#define BLE_HCI_VS_SUBEV_LE_SLEEP_WAKE_UP (0xC3) + /* LE sub-event codes */ #define BLE_HCI_LE_SUBEV_CONN_COMPLETE (0x01) struct ble_hci_ev_le_subev_conn_complete { @@ -1674,6 +1904,7 @@ struct ble_hci_ev_le_subev_gen_dhkey_complete { } __attribute__((packed)); #define BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE (0x0A) +#define BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE_V2 (0x29) struct ble_hci_ev_le_subev_enh_conn_complete { uint8_t subev_code; uint8_t status; @@ -1687,6 +1918,10 @@ struct ble_hci_ev_le_subev_enh_conn_complete { uint16_t conn_latency; uint16_t supervision_timeout; uint8_t mca; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint8_t adv_handle; + uint16_t sync_handle; +#endif } __attribute__((packed)); #define BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT (0x0B) @@ -1735,7 +1970,8 @@ struct ble_hci_ev_le_subev_ext_adv_rpt { struct ext_adv_report reports[0]; } __attribute__((packed)); -#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB (0x0E) +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB (0x0E) +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_ESTAB_V2 (0x24) struct ble_hci_ev_le_subev_periodic_adv_sync_estab { uint8_t subev_code; uint8_t status; @@ -1746,15 +1982,41 @@ struct ble_hci_ev_le_subev_periodic_adv_sync_estab { uint8_t phy; uint16_t interval; uint8_t aca; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint8_t num_subevents; + uint8_t subevent_interval; + uint8_t response_slot_delay; + uint8_t response_slot_spacing; +#endif } __attribute__((packed)); #define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT (0x0F) +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RPT_V2 (0x25) struct ble_hci_ev_le_subev_periodic_adv_rpt { uint8_t subev_code; uint16_t sync_handle; int8_t tx_power; int8_t rssi; uint8_t cte_type; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint16_t event_counter; + uint8_t subevent; +#endif + uint8_t data_status; + uint8_t data_len; + uint8_t data[0]; +} __attribute__((packed)); + +struct ble_hci_ev_le_subev_periodic_adv_rpt_v2 { + uint8_t subev_code; + uint16_t sync_handle; + int8_t tx_power; + int8_t rssi; + uint8_t cte_type; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint16_t event_counter; + uint8_t subevent; +#endif // MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) uint8_t data_status; uint8_t data_len; uint8_t data[0]; @@ -1795,11 +2057,47 @@ struct ble_hci_ev_le_subev_chan_sel_alg { uint8_t csa; } __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_CONNLESS_IQ_RPT (0x15) +struct ble_hci_ev_le_subev_connless_iq_rpt { + uint8_t subev_code; + uint16_t sync_handle; + uint8_t channel_index; + int16_t rssi; + uint8_t rssi_antenna_id; + uint8_t cte_type; + uint8_t slot_durations; + uint8_t packet_status; + uint16_t periodic_event_counter; + uint8_t sample_count; + int8_t iq_samples[0]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_CONN_IQ_RPT (0x16) +struct ble_hci_ev_le_subev_conn_iq_rpt { + uint8_t subev_code; + uint16_t conn_handle; + uint8_t rx_phy; + uint8_t data_channel_index; + int16_t rssi; + uint8_t rssi_antenna_id; + uint8_t cte_type; + uint8_t slot_durations; + uint8_t packet_status; + uint16_t conn_event_counter; + uint8_t sample_count; + int8_t iq_samples[0]; +} __attribute__((packed)); + #define BLE_HCI_LE_SUBEV_CTE_REQ_FAILED (0x17) +struct ble_hci_ev_le_subev_cte_req_failed { + uint8_t subev_code; + uint8_t status; + uint16_t conn_handle; +} __attribute__((packed)); -#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER (0x18) +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER (0x18) +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SYNC_TRANSFER_V2 (0x26) struct ble_hci_ev_le_subev_periodic_adv_sync_transfer { uint8_t subev_code; uint8_t status; @@ -1812,45 +2110,51 @@ struct ble_hci_ev_le_subev_periodic_adv_sync_transfer { uint8_t phy; uint16_t interval; uint8_t aca; +#if MYNEWT_VAL(BLE_PERIODIC_ADV_WITH_RESPONSES) + uint8_t num_subevents; + uint8_t subevent_interval; + uint8_t response_slot_delay; + uint8_t response_slot_spacing; +#endif } __attribute__((packed)); -#define BLE_HCI_LE_SUBEV_CIS_ESTAB (0x19) +#define BLE_HCI_LE_SUBEV_CIS_ESTABLISHED (0x19) struct ble_hci_ev_le_subev_cis_established { uint8_t subev_code; uint8_t status; - uint16_t cis_handle; + uint16_t conn_handle; uint8_t cig_sync_delay[3]; uint8_t cis_sync_delay[3]; - uint8_t trans_latency_mtos[3]; - uint8_t trans_latency_stom[3]; - uint8_t phy_mtos; - uint8_t phy_stom; + uint8_t transport_latency_c_to_p[3]; + uint8_t transport_latency_p_to_c[3]; + uint8_t phy_c_to_p; + uint8_t phy_p_to_c; uint8_t nse; - uint8_t bn_mtos; - uint8_t bn_stom; - uint8_t ft_mtos; - uint8_t ft_stom; - uint16_t max_pdu_mtos; - uint16_t max_pdu_stom; + uint8_t bn_c_to_p; + uint8_t bn_p_to_c; + uint8_t ft_c_to_p; + uint8_t ft_p_to_c; + uint16_t max_pdu_c_to_p; + uint16_t max_pdu_p_to_c; uint16_t iso_interval; } __attribute__((packed)); #define BLE_HCI_LE_SUBEV_CIS_REQUEST (0x1A) struct ble_hci_ev_le_subev_cis_request { uint8_t subev_code; - uint16_t conn_handle; - uint16_t cis_handle; + uint16_t acl_conn_handle; + uint16_t cis_conn_handle; uint8_t cig_id; uint8_t cis_id; } __attribute__((packed)); -#define BLE_HCI_LE_SUBEV_BIG_COMP (0x1B) -struct ble_hci_ev_le_subev_big_complete { +#define BLE_HCI_LE_SUBEV_CREATE_BIG_COMPLETE (0x1B) +struct ble_hci_ev_le_subev_create_big_complete { uint8_t subev_code; uint8_t status; uint8_t big_handle; uint8_t big_sync_delay[3]; - uint8_t transport_latency[3]; + uint8_t transport_latency_big[3]; uint8_t phy; uint8_t nse; uint8_t bn; @@ -1858,31 +2162,31 @@ struct ble_hci_ev_le_subev_big_complete { uint8_t irc; uint16_t max_pdu; uint16_t iso_interval; - uint8_t bis_cnt; - uint16_t bis[0]; + uint8_t num_bis; + uint16_t conn_handle[0]; } __attribute__((packed)); -#define BLE_HCI_LE_SUBEV_BIG_TERMINATE_COMP (0x1C) -struct ble_hci_ev_le_subev_big_terminate_complete { +#define BLE_HCI_LE_SUBEV_TERMINATE_BIG_COMPLETE (0x1C) +struct ble_hci_ev_le_subev_terminate_big_complete { uint8_t subev_code; uint8_t big_handle; uint8_t reason; } __attribute__((packed)); -#define BLE_HCI_LE_SUBEV_BIG_SYNC_ESTAB (0x1D) +#define BLE_HCI_LE_SUBEV_BIG_SYNC_ESTABLISHED (0x1D) struct ble_hci_ev_le_subev_big_sync_established { uint8_t subev_code; uint8_t status; uint8_t big_handle; - uint8_t transport_latency[3]; + uint8_t transport_latency_big[3]; uint8_t nse; uint8_t bn; uint8_t pto; uint8_t irc; uint16_t max_pdu; uint16_t iso_interval; - uint8_t bis_cnt; - uint16_t bis_handles[0]; + uint8_t num_bis; + uint16_t conn_handle[0]; } __attribute__((packed)); #define BLE_HCI_LE_SUBEV_BIG_SYNC_LOST (0x1E) @@ -1910,13 +2214,13 @@ struct ble_hci_ev_le_subev_path_loss_threshold { #define BLE_HCI_LE_SUBEV_TRANSMIT_POWER_REPORT (0x21) struct ble_hci_ev_le_subev_transmit_power_report { - uint8_t subev_code; - uint8_t status; + uint8_t subev_code; + uint8_t status; uint16_t conn_handle; - uint8_t reason; - uint8_t phy; - int8_t transmit_power_level; - uint8_t transmit_power_level_flag; + uint8_t reason; + uint8_t phy; + int8_t transmit_power_level; + uint8_t transmit_power_level_flag; int8_t delta; } __attribute__((packed)); @@ -1949,6 +2253,34 @@ struct ble_hci_ev_le_subev_subrate_change { uint16_t supervision_tmo; } __attribute__((packed)); +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_SUBEV_DATA_REQ (0x27) +struct ble_hci_ev_le_subev_periodic_adv_subev_data_req { + uint8_t subev_code; + uint8_t adv_handle; + uint8_t subevent_start; + uint8_t subevent_data_count; +} __attribute__((packed)); + +#define BLE_HCI_LE_SUBEV_PERIODIC_ADV_RESP_REPORT (0x28) +struct periodic_adv_response { + int8_t tx_power; + int8_t rssi; + uint8_t cte_type; + uint8_t response_slot; + uint8_t data_status; + uint8_t data_length; + uint8_t data[0]; +} __attribute__((packed)); + +struct ble_hci_ev_le_subev_periodic_adv_resp_rep { + uint8_t subev_code; + uint8_t adv_handle; + uint8_t subevent; + uint8_t tx_status; + uint8_t num_responses; + struct periodic_adv_response responses[0]; +} __attribute__((packed)); + #if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE) // LE vendor hci event #define BLE_HCI_LE_SUBEV_DISCARD_REPORT_EVT 0XF0 @@ -1997,6 +2329,7 @@ struct ble_hci_ev_le_subev_subrate_change { #define BLE_HCI_VER_BCS_5_1 (10) #define BLE_HCI_VER_BCS_5_2 (11) #define BLE_HCI_VER_BCS_5_3 (12) +#define BLE_HCI_VER_BCS_5_4 (13) #define BLE_LMP_VER_BCS_1_0b (0) #define BLE_LMP_VER_BCS_1_1 (1) @@ -2011,6 +2344,7 @@ struct ble_hci_ev_le_subev_subrate_change { #define BLE_LMP_VER_BCS_5_1 (10) #define BLE_LMP_VER_BCS_5_2 (11) #define BLE_LMP_VER_BCS_5_3 (12) +#define BLE_LMP_VER_BCS_5_4 (13) /* selected HCI and LMP version */ #if MYNEWT_VAL(BLE_VERSION) == 50 @@ -2025,6 +2359,9 @@ struct ble_hci_ev_le_subev_subrate_change { #elif MYNEWT_VAL(BLE_VERSION) == 53 #define BLE_HCI_VER_BCS BLE_HCI_VER_BCS_5_3 #define BLE_LMP_VER_BCS BLE_LMP_VER_BCS_5_3 +#elif MYNEWT_VAL(BLE_VERSION) == 54 +#define BLE_HCI_VER_BCS BLE_HCI_VER_BCS_5_4 +#define BLE_LMP_VER_BCS BLE_LMP_VER_BCS_5_4 #endif #define BLE_HCI_DATA_HDR_SZ 4 @@ -2043,6 +2380,37 @@ struct hci_data_hdr #define BLE_HCI_PB_FIRST_FLUSH 2 #define BLE_HCI_PB_FULL 3 +#define BLE_HCI_ISO_CONN_HANDLE_MASK (0x07ff) +#define BLE_HCI_ISO_PB_FLAG_MASK (0x3000) +#define BLE_HCI_ISO_TS_FLAG_MASK (0x4000) +#define BLE_HCI_ISO_LENGTH_MASK (0x7fff) + +#define BLE_HCI_ISO_HANDLE(ch, pb, ts) ((ch) | ((pb) << 12) | ((ts) << 14)) + +#define BLE_HCI_ISO_CONN_HANDLE(h) ((h) & BLE_HCI_ISO_CONN_HANDLE_MASK) +#define BLE_HCI_ISO_PB_FLAG(h) (((h) & BLE_HCI_ISO_PB_FLAG_MASK) >> 12) +#define BLE_HCI_ISO_TS_FLAG(h) ((h) & BLE_HCI_ISO_TS_FLAG_MASK) +#define BLE_HCI_ISO_LENGTH(l) ((l) & BLE_HCI_ISO_LENGTH_MASK) + +#define BLE_HCI_ISO_PB_FIRST (0) +#define BLE_HCI_ISO_PB_CONTINUATION (1) +#define BLE_HCI_ISO_PB_COMPLETE (2) +#define BLE_HCI_ISO_PB_LAST (3) + +struct ble_hci_iso { + uint16_t handle; + uint16_t length; + uint8_t data[0]; +}; + +#define BLE_HCI_ISO_HDR_SDU_LENGTH_MASK (0x07ff) + +struct ble_hci_iso_data { + uint16_t packet_seq_num; + uint16_t sdu_len; + uint8_t data[0]; +}; + #ifdef __cplusplus } #endif diff --git a/src/nimble/nimble/include/nimble/nimble_npl.h b/src/nimble/nimble/include/nimble/nimble_npl.h index 5e50110c..be9cd020 100644 --- a/src/nimble/nimble/include/nimble/nimble_npl.h +++ b/src/nimble/nimble/include/nimble/nimble_npl.h @@ -163,7 +163,11 @@ void ble_npl_time_delay(ble_npl_time_t ticks); #if NIMBLE_CFG_CONTROLLER +#ifdef ESP_PLATFORM +void ble_npl_hw_set_isr(int irqn, uint32_t addr); +#else void ble_npl_hw_set_isr(int irqn, void (*addr)(void)); +#endif #endif diff --git a/src/nimble/nimble/include/nimble/nimble_opt.h b/src/nimble/nimble/include/nimble/nimble_opt.h index 7de55d66..6a4fc4f4 100644 --- a/src/nimble/nimble/include/nimble/nimble_opt.h +++ b/src/nimble/nimble/include/nimble/nimble_opt.h @@ -25,7 +25,7 @@ extern "C" { #endif /* Include automatically-generated settings. */ -#include "nimble_opt_auto.h" +#include "nimble/nimble/include/nimble/nimble_opt_auto.h" #ifdef __cplusplus } diff --git a/src/nimble/nimble/include/nimble/nimble_opt_auto.h b/src/nimble/nimble/include/nimble/nimble_opt_auto.h index 0abb28c8..803575ed 100644 --- a/src/nimble/nimble/include/nimble/nimble_opt_auto.h +++ b/src/nimble/nimble/include/nimble/nimble_opt_auto.h @@ -113,6 +113,10 @@ extern "C" { #define NIMBLE_BLE_ATT_CLT_INDICATE \ (MYNEWT_VAL(BLE_GATT_INDICATE)) +#undef NIMBLE_BLE_ATT_CLT_NOTIFY_MULT +#define NIMBLE_BLE_ATT_CLT_NOTIFY_MULT \ + (MYNEWT_VAL(BLE_GATT_NOTIFY_MULTIPLE)) + /** Security manager settings. */ #undef NIMBLE_BLE_SM diff --git a/src/nimble/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h b/src/nimble/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h new file mode 100644 index 00000000..6ad083a0 --- /dev/null +++ b/src/nimble/nimble/transport/common/hci_h4/include/nimble/transport/hci_h4.h @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _HCI_H4_H_ +#define _HCI_H4_H_ + +#include + +#define HCI_H4_NONE 0x00 +#define HCI_H4_CMD 0x01 +#define HCI_H4_ACL 0x02 +#define HCI_H4_EVT 0x04 +#define HCI_H4_ISO 0x05 + +typedef void *(hci_h4_alloc_cmd)(void); +typedef void *(hci_h4_alloc_evt)(int); +typedef struct os_mbuf *(hci_h4_alloc_acl)(void); +typedef struct os_mbuf *(hci_h4_alloc_iso)(void); + +struct hci_h4_allocators { + hci_h4_alloc_cmd *cmd; + hci_h4_alloc_acl *acl; + hci_h4_alloc_evt *evt; + hci_h4_alloc_iso *iso; +}; + +extern const struct hci_h4_allocators hci_h4_allocs_from_ll; +extern const struct hci_h4_allocators hci_h4_allocs_from_hs; + +typedef int (hci_h4_frame_cb)(uint8_t pkt_type, void *data); + +struct hci_h4_sm { + uint8_t state; + uint8_t pkt_type; + uint8_t min_len; + uint16_t len; + uint16_t exp_len; + uint8_t hdr[4]; + union { + uint8_t *buf; + struct os_mbuf *om; + }; + + const struct hci_h4_allocators *allocs; + hci_h4_frame_cb *frame_cb; +}; + +void hci_h4_sm_init(struct hci_h4_sm *h4sm, + const struct hci_h4_allocators *allocs, + hci_h4_frame_cb *frame_cb); + +int hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len); + +#endif /* _HCI_H4_H_ */ diff --git a/src/nimble/nimble/transport/common/hci_h4/src/hci_h4.c b/src/nimble/nimble/transport/common/hci_h4/src/hci_h4.c new file mode 100644 index 00000000..459729b2 --- /dev/null +++ b/src/nimble/nimble/transport/common/hci_h4/src/hci_h4.c @@ -0,0 +1,332 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#define HCI_H4_SM_W4_PKT_TYPE 0 +#define HCI_H4_SM_W4_HEADER 1 +#define HCI_H4_SM_W4_PAYLOAD 2 +#define HCI_H4_SM_COMPLETED 3 + +const struct hci_h4_allocators hci_h4_allocs_from_ll = { + .acl = ble_transport_alloc_acl_from_ll, + .evt = ble_transport_alloc_evt, +}; +const struct hci_h4_allocators hci_h4_allocs_from_hs = { + .cmd = ble_transport_alloc_cmd, + .acl = ble_transport_alloc_acl_from_hs, + .iso = ble_transport_alloc_iso_from_hs, +}; + +struct hci_h4_input_buffer { + const uint8_t *buf; + uint16_t len; +}; + +static void +hci_h4_frame_start(struct hci_h4_sm *rxs, uint8_t pkt_type) +{ + rxs->pkt_type = pkt_type; + rxs->len = 0; + rxs->exp_len = 0; + + switch (rxs->pkt_type) { + case HCI_H4_CMD: + rxs->min_len = 3; + break; + case HCI_H4_ACL: + case HCI_H4_ISO: + rxs->min_len = 4; + break; + case HCI_H4_EVT: + rxs->min_len = 2; + break; + default: + /* XXX sync loss */ + assert(0); + break; + } +} + +static int +hci_h4_ib_consume(struct hci_h4_input_buffer *ib, uint16_t len) +{ + assert(ib->len >= len); + + ib->buf += len; + ib->len -= len; + + return len; +} + +static int +hci_h4_ib_pull_min_len(struct hci_h4_sm *rxs, + struct hci_h4_input_buffer *ib) +{ + uint16_t len; + + len = min(ib->len, rxs->min_len - rxs->len); + memcpy(&rxs->hdr[rxs->len], ib->buf, len); + + rxs->len += len; + hci_h4_ib_consume(ib, len); + + return rxs->len != rxs->min_len; +} + +static int +hci_h4_sm_w4_header(struct hci_h4_sm *h4sm, struct hci_h4_input_buffer *ib) +{ + int rc; + + rc = hci_h4_ib_pull_min_len(h4sm, ib); + if (rc) { + /* need more data */ + return 1; + } + + switch (h4sm->pkt_type) { + case HCI_H4_CMD: + assert(h4sm->allocs && h4sm->allocs->cmd); + h4sm->buf = h4sm->allocs->cmd(); + if (!h4sm->buf) { + return -1; + } + + memcpy(h4sm->buf, h4sm->hdr, h4sm->len); + h4sm->exp_len = h4sm->hdr[2] + 3; + break; + case HCI_H4_ACL: + assert(h4sm->allocs && h4sm->allocs->acl); + h4sm->om = h4sm->allocs->acl(); + if (!h4sm->om) { + return -1; + } + + os_mbuf_append(h4sm->om, h4sm->hdr, h4sm->len); + h4sm->exp_len = get_le16(&h4sm->hdr[2]) + 4; + break; + case HCI_H4_EVT: + if (h4sm->hdr[0] == BLE_HCI_EVCODE_LE_META) { + /* For LE Meta event we need 3 bytes to parse header */ + h4sm->min_len = 3; + rc = hci_h4_ib_pull_min_len(h4sm, ib); + if (rc) { + /* need more data */ + return 1; + } + } + + assert(h4sm->allocs && h4sm->allocs->evt); + + /* We can drop legacy advertising events if there's no free buffer in + * discardable pool. + */ + if (h4sm->hdr[2] == BLE_HCI_LE_SUBEV_ADV_RPT) { + h4sm->buf = h4sm->allocs->evt(1); + } else { + h4sm->buf = h4sm->allocs->evt(0); + if (!h4sm->buf) { + return -1; + } + } + + if (h4sm->buf) { + memcpy(h4sm->buf, h4sm->hdr, h4sm->len); + } + + h4sm->exp_len = h4sm->hdr[1] + 2; + break; + case HCI_H4_ISO: + assert(h4sm->allocs && h4sm->allocs->iso); + h4sm->om = h4sm->allocs->iso(); + if (!h4sm->om) { + return -1; + } + + os_mbuf_append(h4sm->om, h4sm->hdr, h4sm->len); + h4sm->exp_len = (get_le16(&h4sm->hdr[2]) & 0x7fff) + 4; + break; + default: + assert(0); + break; + } + + return 0; +} + +static int +hci_h4_sm_w4_payload(struct hci_h4_sm *h4sm, + struct hci_h4_input_buffer *ib) +{ + uint16_t mbuf_len; + uint16_t len; + int rc; + + len = min(ib->len, h4sm->exp_len - h4sm->len); + + switch (h4sm->pkt_type) { + case HCI_H4_CMD: + case HCI_H4_EVT: + if (h4sm->buf) { + memcpy(&h4sm->buf[h4sm->len], ib->buf, len); + } + break; + case HCI_H4_ACL: + case HCI_H4_ISO: + assert(h4sm->om); + + mbuf_len = OS_MBUF_PKTLEN(h4sm->om); + rc = os_mbuf_append(h4sm->om, ib->buf, len); + if (rc) { + /* Some data may already be appended so need to adjust h4sm only by + * the size of appended data. + */ + len = OS_MBUF_PKTLEN(h4sm->om) - mbuf_len; + h4sm->len += len; + hci_h4_ib_consume(ib, len); + + return -1; + } + break; + default: + assert(0); + break; + } + + h4sm->len += len; + hci_h4_ib_consume(ib, len); + + /* return 1 if need more data */ + return h4sm->len != h4sm->exp_len; +} + +static void +hci_h4_sm_completed(struct hci_h4_sm *h4sm) +{ + int rc; + + switch (h4sm->pkt_type) { + case HCI_H4_CMD: + case HCI_H4_EVT: + if (h4sm->buf) { + assert(h4sm->frame_cb); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->buf); + if (rc != 0) { + ble_transport_free(h4sm->buf); + } + h4sm->buf = NULL; + } + break; + case HCI_H4_ACL: + case HCI_H4_ISO: + if (h4sm->om) { + assert(h4sm->frame_cb); + rc = h4sm->frame_cb(h4sm->pkt_type, h4sm->om); + if (rc != 0) { + os_mbuf_free_chain(h4sm->om); + } + h4sm->om = NULL; + } + break; + default: + assert(0); + break; + } +} + +int +hci_h4_sm_rx(struct hci_h4_sm *h4sm, const uint8_t *buf, uint16_t len) +{ + struct hci_h4_input_buffer ib = { + .buf = buf, + .len = len, + }; + + int rc = 0; + while (ib.len && (rc >= 0)) { + rc = 0; + switch (h4sm->state) { + case HCI_H4_SM_W4_PKT_TYPE: + hci_h4_frame_start(h4sm, ib.buf[0]); + hci_h4_ib_consume(&ib, 1); + h4sm->state = HCI_H4_SM_W4_HEADER; + /* fall through */ + case HCI_H4_SM_W4_HEADER: + rc = hci_h4_sm_w4_header(h4sm, &ib); + assert(rc >= 0); + if (rc) { + break; + } + h4sm->state = HCI_H4_SM_W4_PAYLOAD; + /* fall through */ + case HCI_H4_SM_W4_PAYLOAD: + rc = hci_h4_sm_w4_payload(h4sm, &ib); + assert(rc >= 0); + if (rc) { + break; + } + h4sm->state = HCI_H4_SM_COMPLETED; + /* fall through */ + case HCI_H4_SM_COMPLETED: + hci_h4_sm_completed(h4sm); + h4sm->state = HCI_H4_SM_W4_PKT_TYPE; + break; + default: + assert(0); + break; + } + } + + /* Calculate consumed bytes + * + * Note: we should always consume some bytes unless there is an oom error. + * It's also possible that we have an oom error but already consumed some + * data, in such case just return success and error will be returned on next + * pass. + */ + len = len - ib.len; + if (len == 0) { + assert(rc < 0); + return -1; + } + + return len; +} + +void +hci_h4_sm_init(struct hci_h4_sm *h4sm, const struct hci_h4_allocators *allocs, + hci_h4_frame_cb *frame_cb) +{ + memset(h4sm, 0, sizeof(*h4sm)); + h4sm->allocs = allocs; + h4sm->frame_cb = frame_cb; +} diff --git a/src/nimble/nimble/transport/common/hci_ipc/include/nimble/transport/hci_ipc.h b/src/nimble/nimble/transport/common/hci_ipc/include/nimble/transport/hci_ipc.h new file mode 100644 index 00000000..551fb93d --- /dev/null +++ b/src/nimble/nimble/transport/common/hci_ipc/include/nimble/transport/hci_ipc.h @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _HCI_IPC_H_ +#define _HCI_IPC_H_ + +#include + +#define HCI_IPC_TYPE_CMD 0x01 +#define HCI_IPC_TYPE_ACL 0x02 +#define HCI_IPC_TYPE_EVT 0x04 +#define HCI_IPC_TYPE_EVT_DISCARDABLE 0x05 +#define HCI_IPC_TYPE_EVT_IN_CMD 0x06 +#define HCI_IPC_TYPE_ISO 0x07 + +struct __attribute__((packed)) hci_ipc_hdr { + uint8_t type; + uint16_t length; +}; + +struct hci_ipc_sm { + struct hci_ipc_hdr hdr; + uint8_t hdr_len; + uint16_t rem_len; + uint16_t buf_len; + + union { + uint8_t *buf; + struct os_mbuf *om; + }; +}; + +struct hci_ipc_shm { + uint16_t n2a_num_acl; + uint16_t n2a_num_evt; + uint16_t n2a_num_evt_disc; +}; + +void hci_ipc_init(volatile struct hci_ipc_shm *shm, struct hci_ipc_sm *sm); +int hci_ipc_rx(struct hci_ipc_sm *sm, const uint8_t *buf, uint16_t len); + +extern void hci_ipc_atomic_put(volatile uint16_t *num); +extern uint16_t hci_ipc_atomic_get(volatile uint16_t *num); + +/* Just to optimize static inlines below, do not use directly! */ +extern volatile struct hci_ipc_shm *g_ipc_shm; + +static inline int +hci_ipc_get(uint8_t type) +{ + volatile struct hci_ipc_shm *shm = g_ipc_shm; + + switch (type) { + case HCI_IPC_TYPE_ACL: + return hci_ipc_atomic_get(&shm->n2a_num_acl); + case HCI_IPC_TYPE_EVT: + return hci_ipc_atomic_get(&shm->n2a_num_evt); + case HCI_IPC_TYPE_EVT_DISCARDABLE: + return hci_ipc_atomic_get(&shm->n2a_num_evt_disc); + } + + return 0; +} + +static inline void +hci_ipc_put(uint8_t type) +{ + volatile struct hci_ipc_shm *shm = g_ipc_shm; + + switch (type) { + case HCI_IPC_TYPE_ACL: + hci_ipc_atomic_put(&shm->n2a_num_acl); + break; + case HCI_IPC_TYPE_EVT: + hci_ipc_atomic_put(&shm->n2a_num_evt); + break; + case HCI_IPC_TYPE_EVT_DISCARDABLE: + hci_ipc_atomic_put(&shm->n2a_num_evt_disc); + break; + } +} + +#endif /* _HCI_IPC_H_ */ diff --git a/src/nimble/nimble/transport/common/hci_ipc/src/hci_ipc.c b/src/nimble/nimble/transport/common/hci_ipc/src/hci_ipc.c new file mode 100644 index 00000000..421399c9 --- /dev/null +++ b/src/nimble/nimble/transport/common/hci_ipc/src/hci_ipc.c @@ -0,0 +1,238 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef min +#define min(a, b) ((a) < (b) ? (a) : (b)) +#endif + +volatile struct hci_ipc_shm *g_ipc_shm; + +static void +hci_ipc_alloc(struct hci_ipc_sm *sm) +{ + assert(sm->hdr.type); + assert(sm->buf == NULL); + + switch (sm->hdr.type) { +#if MYNEWT_VAL(BLE_CONTROLLER) + case HCI_IPC_TYPE_CMD: + sm->buf = ble_transport_alloc_cmd(); + break; +#endif + case HCI_IPC_TYPE_ACL: +#if MYNEWT_VAL(BLE_CONTROLLER) + sm->om = ble_transport_alloc_acl_from_hs(); +#else + sm->om = ble_transport_alloc_acl_from_ll(); +#endif + break; +#if !MYNEWT_VAL(BLE_CONTROLLER) + case HCI_IPC_TYPE_EVT: + sm->buf = ble_transport_alloc_evt(0); + break; + case HCI_IPC_TYPE_EVT_DISCARDABLE: + sm->buf = ble_transport_alloc_evt(1); + break; + case HCI_IPC_TYPE_EVT_IN_CMD: + sm->buf = ble_transport_alloc_cmd(); + break; +#endif + case HCI_IPC_TYPE_ISO: +#if MYNEWT_VAL(BLE_CONTROLLER) + sm->om = ble_transport_alloc_iso_from_hs(); +#else + sm->om = ble_transport_alloc_iso_from_ll(); +#endif + break; + default: + assert(0); + break; + } + + assert(sm->buf); + + sm->rem_len = sm->hdr.length; + sm->buf_len = 0; +} + +static bool +hci_ipc_has_hdr(struct hci_ipc_sm *sm) +{ + return sm->hdr_len == sizeof(sm->hdr); +} + +static void +hci_ipc_frame(struct hci_ipc_sm *sm) +{ + assert(sm->hdr.type); + assert(sm->buf); + assert(sm->rem_len == 0); + + switch (sm->hdr.type) { +#if MYNEWT_VAL(BLE_CONTROLLER) + case HCI_IPC_TYPE_CMD: + ble_transport_to_ll_cmd(sm->buf); + break; +#endif + case HCI_IPC_TYPE_ACL: +#if MYNEWT_VAL(BLE_CONTROLLER) + ble_transport_to_ll_acl(sm->om); +#else + ble_transport_to_hs_acl(sm->om); +#endif + break; +#if !MYNEWT_VAL(BLE_CONTROLLER) + case HCI_IPC_TYPE_EVT: + case HCI_IPC_TYPE_EVT_DISCARDABLE: + case HCI_IPC_TYPE_EVT_IN_CMD: + ble_transport_to_hs_evt(sm->buf); + break; +#endif + case HCI_IPC_TYPE_ISO: +#if MYNEWT_VAL(BLE_CONTROLLER) + ble_transport_to_ll_iso(sm->om); +#else + ble_transport_to_hs_iso(sm->om); +#endif + break; + default: + assert(0); + break; + } + + sm->hdr.type = 0; + sm->hdr.length = 0; + sm->hdr_len = 0; + sm->buf_len = 0; + sm->rem_len = 0; + sm->buf = NULL; +} + +static uint16_t +hci_ipc_copy_to_hdr(struct hci_ipc_sm *sm, const uint8_t *buf, uint16_t len) +{ + uint16_t rem_hdr_len; + uint8_t *p; + + if (hci_ipc_has_hdr(sm)) { + return 0; + } + + rem_hdr_len = sizeof(sm->hdr) - sm->hdr_len; + len = min(len, rem_hdr_len); + + p = (void *)&sm->hdr; + memcpy(p + sm->hdr_len, buf, len); + + sm->hdr_len += len; + + if (hci_ipc_has_hdr(sm)) { + hci_ipc_alloc(sm); + } + + return len; +} + +static uint16_t +hci_ipc_copy_to_buf(struct hci_ipc_sm *sm, const uint8_t *buf, uint16_t len) +{ + int rc; + + assert(sm->hdr.type); + assert(sm->buf); + + len = min(len, sm->rem_len); + + switch (sm->hdr.type) { +#if MYNEWT_VAL(BLE_CONTROLLER) + case HCI_IPC_TYPE_CMD: +#else + case HCI_IPC_TYPE_EVT: + case HCI_IPC_TYPE_EVT_DISCARDABLE: + case HCI_IPC_TYPE_EVT_IN_CMD: +#endif + memcpy(sm->buf + sm->buf_len, buf, len); + break; + case HCI_IPC_TYPE_ACL: + case HCI_IPC_TYPE_ISO: + rc = os_mbuf_append(sm->om, buf, len); + assert(rc == 0); + break; + default: + assert(0); + break; + } + + sm->rem_len -= len; + sm->buf_len += len; + + if (sm->rem_len == 0) { + hci_ipc_frame(sm); + } + + return len; +} + +int +hci_ipc_rx(struct hci_ipc_sm *sm, const uint8_t *buf, uint16_t len) +{ + uint16_t rem_len = len; + uint16_t copy_len; + + while (rem_len) { + if (hci_ipc_has_hdr(sm)) { + copy_len = hci_ipc_copy_to_buf(sm, buf, rem_len); + } else { + copy_len = hci_ipc_copy_to_hdr(sm, buf, rem_len); + } + + rem_len -= copy_len; + buf += copy_len; + } + + return len; +} + +void +hci_ipc_init(volatile struct hci_ipc_shm *shm, struct hci_ipc_sm *sm) +{ + assert(g_ipc_shm == NULL); + + g_ipc_shm = shm; + memset(sm, 0, sizeof(*sm)); + +#if MYNEWT_VAL(BLE_CONTROLLER) + while (shm->n2a_num_evt_disc == 0) { + /* Wait until app side initializes credits */ + } +#else + shm->n2a_num_acl = MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT); + shm->n2a_num_evt = MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT); + shm->n2a_num_evt_disc = MYNEWT_VAL(BLE_TRANSPORT_EVT_DISCARDABLE_COUNT); +#endif +} diff --git a/src/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c b/src/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c new file mode 100644 index 00000000..bc0305ec --- /dev/null +++ b/src/nimble/nimble/transport/esp_ipc/src/hci_esp_ipc.c @@ -0,0 +1,78 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#ifdef ESP_PLATFORM +#if !defined(CONFIG_IDF_TARGET_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) + +#include +#include +#include +#include +#include +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "nimble/nimble/transport/include/nimble/transport.h" +#include "nimble/esp_port/port/transport/include/esp_hci_transport.h" +#include "nimble/esp_port/port/transport/include/esp_hci_internal.h" + +static int +ble_transport_dummy_host_recv_cb(hci_trans_pkt_ind_t type, uint8_t *data, uint16_t len) +{ + /* Dummy function */ + return 0; +} + +static int +ble_transport_host_recv_cb(hci_trans_pkt_ind_t type, uint8_t *data, uint16_t len) +{ + int rc; + + if (type == HCI_ACL_IND) { + rc = ble_transport_to_hs_acl((struct os_mbuf *)data); + } else { + rc = ble_transport_to_hs_evt(data); + } + return rc; +} + +int +ble_transport_to_ll_cmd_impl(void *buf) +{ + return hci_transport_host_cmd_tx(buf, 0); +} + +int +ble_transport_to_ll_acl_impl(struct os_mbuf *om) +{ + return hci_transport_host_acl_tx((uint8_t *)om, 0); +} + +void +ble_transport_ll_init(void) +{ + hci_transport_host_callback_register(ble_transport_host_recv_cb); +} + +void +ble_transport_ll_deinit(void) +{ + hci_transport_host_callback_register(ble_transport_dummy_host_recv_cb); +} + +void * +ble_transport_alloc_cmd(void) +{ + return r_ble_hci_trans_buf_alloc(ESP_HCI_INTERNAL_BUF_CMD); +} + +void +ble_transport_free(void *buf) +{ + r_ble_hci_trans_buf_free(buf); +} + +#endif /* !CONFIG_IDF_TARGET_ESP32 && !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32S3 */ +#endif /* ESP_PLATFORM */ \ No newline at end of file diff --git a/src/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c b/src/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c new file mode 100644 index 00000000..0b0ecd95 --- /dev/null +++ b/src/nimble/nimble/transport/esp_ipc_legacy/src/hci_esp_ipc_legacy.c @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3) + +#include +#include +#include +#include +#include +#include "nimble/nimble/transport/include/nimble/transport.h" +#include "nimble/esp_port/esp-hci/include/esp_nimble_hci.h" + +/* This file is only used by ESP32, ESP32C3 and ESP32S3. */ +int +ble_transport_to_ll_cmd_impl(void *buf) +{ + return ble_hci_trans_hs_cmd_tx(buf); +} + +int +ble_transport_to_ll_acl_impl(struct os_mbuf *om) +{ + return ble_hci_trans_hs_acl_tx(om); +} + +void +ble_transport_ll_init(void) +{ + +} + +void +ble_transport_ll_deinit(void) +{ + +} + +#endif /* CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 */ diff --git a/src/nimble/nimble/transport/include/nimble/transport.h b/src/nimble/nimble/transport/include/nimble/transport.h index 1bc45495..0a4b39c5 100644 --- a/src/nimble/nimble/transport/include/nimble/transport.h +++ b/src/nimble/nimble/transport/include/nimble/transport.h @@ -24,8 +24,11 @@ extern "C" { #endif -#include "transport_impl.h" -#include "transport/monitor.h" +#include +#include +#if MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc +#include +#endif #ifdef ESP_PLATFORM @@ -76,154 +79,6 @@ void ble_transport_deinit(void); typedef int ble_hci_trans_rx_cmd_fn(uint8_t *cmd, void *arg); typedef int ble_hci_trans_rx_acl_fn(struct os_mbuf *om, void *arg); -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED -#define ble_transport_alloc_cmd() ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD) -#define ble_transport_alloc_event(X) ble_hci_trans_buf_alloc(X ? BLE_HCI_TRANS_BUF_EVT_LO : BLE_HCI_TRANS_BUF_EVT_HI) -#define ble_transport_free ble_hci_trans_buf_free - -struct ble_hci_trans_funcs_t { - int(*_ble_hci_trans_hs_acl_tx)(struct os_mbuf *om); - int(*_ble_hci_trans_hs_cmd_tx)(uint8_t *cmd); - int(*_ble_hci_trans_ll_acl_tx)(struct os_mbuf *om); - int(*_ble_hci_trans_ll_evt_tx)(uint8_t *hci_ev); - int(*_ble_hci_trans_reset)(void); - int(*_ble_hci_trans_set_acl_free_cb)(os_mempool_put_fn *cb,void *arg); -}; - -extern struct ble_hci_trans_funcs_t *ble_hci_trans_funcs_ptr; - -/** - * Sends an HCI event from the controller to the host. - * - * @param cmd The HCI event to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_ll_evt_tx(uint8_t *hci_ev); -#define ble_hci_trans_ll_evt_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_evt_tx - -/** - * Sends ACL data from controller to host. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_ll_acl_tx(struct os_mbuf *om); -#define ble_hci_trans_ll_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_ll_acl_tx - -/** - * Sends an HCI command from the host to the controller. - * - * @param cmd The HCI command to send. This buffer must be - * allocated via ble_hci_trans_buf_alloc(). - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_hs_cmd_tx(uint8_t *cmd); -#define ble_hci_trans_hs_cmd_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_cmd_tx - -/** - * Sends ACL data from host to controller. - * - * @param om The ACL data packet to send. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_hs_acl_tx(struct os_mbuf *om); -#define ble_hci_trans_hs_acl_tx ble_hci_trans_funcs_ptr->_ble_hci_trans_hs_acl_tx - -/** - * Allocates a flat buffer of the specified type. - * - * @param type The type of buffer to allocate; one of the - * BLE_HCI_TRANS_BUF_[...] constants. - * - * @return The allocated buffer on success; - * NULL on buffer exhaustion. - */ -extern uint8_t *r_ble_hci_trans_buf_alloc(int type); -#define ble_hci_trans_buf_alloc r_ble_hci_trans_buf_alloc - -/** - * Frees the specified flat buffer. The buffer must have been allocated via - * ble_hci_trans_buf_alloc(). - * - * @param buf The buffer to free. - */ -extern void r_ble_hci_trans_buf_free(uint8_t *buf); -#define ble_hci_trans_buf_free r_ble_hci_trans_buf_free - -/** - * Configures a callback to get executed whenever an ACL data packet is freed. - * The function is called immediately before the free occurs. - * - * @param cb The callback to configure. - * @param arg An optional argument to pass to the callback. - * - * @return 0 on success; - * BLE_ERR_UNSUPPORTED if the transport does not - * support this operation. - */ -extern int r_ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg); -#define ble_hci_trans_set_acl_free_cb ble_hci_trans_funcs_ptr->_ble_hci_trans_set_acl_free_cb - -/** - * Configures the HCI transport to operate with a controller. The transport - * will execute specified callbacks upon receiving HCI packets from the host. - * - * @param cmd_cb The callback to execute upon receiving an HCI - * command. - * @param cmd_arg Optional argument to pass to the command - * callback. - * @param acl_cb The callback to execute upon receiving ACL - * data. - * @param acl_arg Optional argument to pass to the ACL - * callback. - */ -extern void r_ble_hci_trans_cfg_ll(ble_hci_trans_rx_cmd_fn *cmd_cb, - void *cmd_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); -#define ble_hci_trans_cfg_ll r_ble_hci_trans_cfg_ll - -/** - * Configures the HCI transport to operate with a host. The transport will - * execute specified callbacks upon receiving HCI packets from the controller. - * - * @param evt_cb The callback to execute upon receiving an HCI - * event. - * @param evt_arg Optional argument to pass to the event - * callback. - * @param acl_cb The callback to execute upon receiving ACL - * data. - * @param acl_arg Optional argument to pass to the ACL - * callback. - */ -extern void r_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, - void *evt_arg, - ble_hci_trans_rx_acl_fn *acl_cb, - void *acl_arg); -#define ble_hci_trans_cfg_hs r_ble_hci_trans_cfg_hs - -/** - * Resets the HCI module to a clean state. Frees all buffers and reinitializes - * the underlying transport. - * - * @return 0 on success; - * A BLE_ERR_[...] error code on failure. - */ -extern int r_ble_hci_trans_reset(void); -#define ble_hci_trans_reset ble_hci_trans_funcs_ptr->_ble_hci_trans_reset - -void esp_ble_hci_trans_init(uint8_t); - -#else /** * Sends an HCI event from the controller to the host. * @@ -332,44 +187,21 @@ void esp_ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *evt_cb, * A BLE_ERR_[...] error code on failure. */ int esp_ble_hci_trans_reset(void); -#endif -struct os_mbuf; - -/* Allocators for supported data types */ -#if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED -void *ble_transport_alloc_cmd(void); -void *ble_transport_alloc_evt(int discardable); -struct os_mbuf *ble_transport_alloc_acl_from_hs(void); -struct os_mbuf *ble_transport_alloc_acl_from_ll(void); - -/* Generic deallocator for cmd/evt buffers */ -void ble_transport_free(void *buf); -#endif - -/* Register put callback on acl_from_ll mbufs (for ll-hs flow control) */ -int ble_transport_register_put_acl_from_ll_cb(os_mempool_put_fn *cb); - -/* Send data to hs/ll side */ -#if CONFIG_BT_CONTROLLER_ENABLED -#define ble_transport_to_ll_acl ble_hci_trans_hs_acl_tx -#define ble_transport_to_ll_cmd ble_hci_trans_hs_cmd_tx -#endif - -int ble_transport_to_hs_evt(void *buf); -int ble_transport_to_hs_acl(struct os_mbuf *om); -#else // ESP_PLATFORM +#endif /* ESP_PLATFORM */ struct os_mbuf; +/* Initialization */ void ble_transport_init(void); -void ble_transport_deinit(void); /* Allocators for supported data types */ void *ble_transport_alloc_cmd(void); void *ble_transport_alloc_evt(int discardable); struct os_mbuf *ble_transport_alloc_acl_from_hs(void); +struct os_mbuf *ble_transport_alloc_iso_from_hs(void); struct os_mbuf *ble_transport_alloc_acl_from_ll(void); +struct os_mbuf *ble_transport_alloc_iso_from_ll(void); /* Generic deallocator for cmd/evt buffers */ void ble_transport_free(void *buf); @@ -377,13 +209,15 @@ void ble_transport_free(void *buf); /* Register put callback on acl_from_ll mbufs (for ll-hs flow control) */ int ble_transport_register_put_acl_from_ll_cb(os_mempool_put_fn *cb); -/* Send data to hs/ll side */ + int ble_transport_to_ll_cmd(void *buf); int ble_transport_to_ll_acl(struct os_mbuf *om); + +/* Send data to hs/ll side */ +int ble_transport_to_ll_iso(struct os_mbuf *om); int ble_transport_to_hs_evt(void *buf); int ble_transport_to_hs_acl(struct os_mbuf *om); - -#endif // ESP_PLATFORM +int ble_transport_to_hs_iso(struct os_mbuf *om); #ifdef __cplusplus } diff --git a/src/nimble/nimble/transport/include/nimble/transport/monitor.h b/src/nimble/nimble/transport/include/nimble/transport/monitor.h index 695f71da..2bc90fed 100644 --- a/src/nimble/nimble/transport/include/nimble/transport/monitor.h +++ b/src/nimble/nimble/transport/include/nimble/transport/monitor.h @@ -20,7 +20,7 @@ #ifndef H_BLE_MONITOR_ #define H_BLE_MONITOR_ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include #ifdef __cplusplus extern "C" { @@ -30,11 +30,20 @@ extern "C" { MYNEWT_VAL(BLE_MONITOR_UART)) #if BLE_MONITOR +int ble_monitor_out(int c); int ble_monitor_log(int level, const char *fmt, ...); #else static inline int +ble_monitor_out(int c) +{ + (void)c; + return 0; +} +static inline int ble_monitor_log(int level, const char *fmt, ...) { + (void)level; + (void)fmt; return 0; } @@ -50,6 +59,12 @@ ble_transport_to_ll_acl(struct os_mbuf *om) return ble_transport_to_ll_acl_impl(om); } +static inline int +ble_transport_to_ll_iso(struct os_mbuf *om) +{ + return ble_transport_to_ll_iso_impl(om); +} + static inline int ble_transport_to_hs_evt(void *buf) { @@ -61,6 +76,12 @@ ble_transport_to_hs_acl(struct os_mbuf *om) { return ble_transport_to_hs_acl_impl(om); } + +static inline int +ble_transport_to_hs_iso(struct os_mbuf *om) +{ + return ble_transport_to_hs_iso_impl(om); +} #endif /* BLE_MONITOR */ #ifdef __cplusplus diff --git a/src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h b/src/nimble/nimble/transport/include/nimble/transport/transport_ipc.h similarity index 52% rename from src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h rename to src/nimble/nimble/transport/include/nimble/transport/transport_ipc.h index 24b9a26c..c421420e 100644 --- a/src/nimble/nimble/host/services/bas/include/services/bas/ble_svc_bas.h +++ b/src/nimble/nimble/transport/include/nimble/transport/transport_ipc.h @@ -1,4 +1,4 @@ -/** +/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -17,17 +17,33 @@ * under the License. */ -#ifndef H_BLE_SVC_BAS_ -#define H_BLE_SVC_BAS_ +#ifndef H_NIMBLE_TRANSPORT_IPC_ +#define H_NIMBLE_TRANSPORT_IPC_ -/* 16 Bit Battery Service UUID */ -#define BLE_SVC_BAS_UUID16 0x180F +#include -/* 16 Bit Battery Service Characteristic UUIDs */ -#define BLE_SVC_BAS_CHR_UUID16_BATTERY_LEVEL 0x2A19 +#ifdef __cplusplus +extern "C" { +#endif + + +/* NOTE: These APIs shall only be used by IPC transports */ -int ble_svc_bas_battery_level_set(uint8_t level); +#define BLE_TRANSPORT_IPC \ + MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_common_hci_ipc +#define BLE_TRANSPORT_IPC_ON_HS \ + (BLE_TRANSPORT_IPC && !MYNEWT_VAL(BLE_CONTROLLER)) +#define BLE_TRANSPORT_IPC_ON_LL \ + (BLE_TRANSPORT_IPC && MYNEWT_VAL(BLE_CONTROLLER)) -void ble_svc_bas_init(void); +/* Free cmd/evt buffer sent over IPC */ +void ble_transport_ipc_free(void *buf); +/* Get IPC type for cmd/evt buffer */ +uint8_t ble_transport_ipc_buf_evt_type_get(void *buf); + +#ifdef __cplusplus +} #endif + +#endif /* H_NIMBLE_TRANSPORT_IPC_ */ diff --git a/src/nimble/nimble/transport/include/nimble/transport_impl.h b/src/nimble/nimble/transport/include/nimble/transport_impl.h index 97f4cbe1..26259b18 100644 --- a/src/nimble/nimble/transport/include/nimble/transport_impl.h +++ b/src/nimble/nimble/transport/include/nimble/transport_impl.h @@ -31,17 +31,15 @@ extern "C" { extern void ble_transport_ll_init(void); extern void ble_transport_hs_init(void); +extern void ble_transport_ll_deinit(void); + /* APIs to be implemented by HS/LL side of transports */ extern int ble_transport_to_ll_cmd_impl(void *buf); extern int ble_transport_to_ll_acl_impl(struct os_mbuf *om); +extern int ble_transport_to_ll_iso_impl(struct os_mbuf *om); extern int ble_transport_to_hs_evt_impl(void *buf); extern int ble_transport_to_hs_acl_impl(struct os_mbuf *om); - -#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL) -/* To be implemented if transport supports internal flow control between cores */ -extern int ble_transport_int_flow_ctl_get(void); -extern void ble_transport_int_flow_ctl_put(void); -#endif +extern int ble_transport_to_hs_iso_impl(struct os_mbuf *om); #ifdef __cplusplus } diff --git a/src/nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c b/src/nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c new file mode 100644 index 00000000..6f2d31ef --- /dev/null +++ b/src/nimble/nimble/transport/nrf5340/src/nrf5340_ble_hci.c @@ -0,0 +1,235 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#if defined(ARDUINO_ARCH_NRF5) && defined(NRF53) + +#include +#include +#include +#include +#include +#include +#include +#include + +#if MYNEWT_VAL(BLE_CONTROLLER) +#define IPC_TX_CHANNEL 0 +#define IPC_RX_CHANNEL 1 +#else +#define IPC_TX_CHANNEL 1 +#define IPC_RX_CHANNEL 0 +#endif + +static struct hci_ipc_sm g_hci_ipc_sm; + +static int +nrf5340_ble_hci_acl_tx(struct os_mbuf *om) +{ + struct hci_ipc_hdr hdr; + struct os_mbuf *x; + int rc; + + hdr.type = HCI_IPC_TYPE_ACL; + hdr.length = 4 + get_le16(&om->om_data[2]); + + rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &hdr, sizeof(hdr), false); + if (rc == 0) { + x = om; + while (x) { + rc = ipc_nrf5340_write(IPC_TX_CHANNEL, x->om_data, x->om_len, true); + if (rc < 0) { + break; + } + x = SLIST_NEXT(x, om_next); + } + } + + os_mbuf_free_chain(om); + + return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0; +} + +#if !MYNEWT_VAL(BLE_CONTROLLER) +static int +nrf5340_ble_hci_iso_tx(struct os_mbuf *om) +{ + struct hci_ipc_hdr hdr; + struct os_mbuf *x; + int rc; + + hdr.type = HCI_IPC_TYPE_ISO; + hdr.length = 4 + get_le16(&om->om_data[2]); + + rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &hdr, sizeof(hdr), false); + if (rc == 0) { + x = om; + while (x) { + rc = ipc_nrf5340_write(IPC_TX_CHANNEL, x->om_data, x->om_len, true); + if (rc < 0) { + break; + } + x = SLIST_NEXT(x, om_next); + } + } + + os_mbuf_free_chain(om); + + return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0; +} +#endif + +static void +nrf5340_ble_hci_trans_rx(int channel, void *user_data) +{ + uint8_t *buf; + int len; + + len = ipc_nrf5340_available_buf(channel, (void **)&buf); + while (len > 0) { + len = hci_ipc_rx(&g_hci_ipc_sm, buf, len); + ipc_nrf5340_consume(channel, len); + len = ipc_nrf5340_available_buf(channel, (void **)&buf); + } +} + +static void +nrf5340_ble_hci_init(void) +{ + SYSINIT_ASSERT_ACTIVE(); + + ipc_nrf5340_recv(IPC_RX_CHANNEL, nrf5340_ble_hci_trans_rx, NULL); +} + +#if MYNEWT_VAL(BLE_CONTROLLER) +int +ble_transport_to_hs_evt_impl(void *buf) +{ + struct hci_ipc_hdr hdr; + uint8_t *hci_ev = buf; + int rc; + + hdr.type = ble_transport_ipc_buf_evt_type_get(buf); + hdr.length = 2 + hci_ev[1]; + + rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &hdr, sizeof(hdr), false); + if (rc == 0) { + rc = ipc_nrf5340_write(IPC_TX_CHANNEL, hci_ev, hdr.length, true); + } + + ble_transport_ipc_free(buf); + + return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0; +} + +int +ble_transport_to_hs_acl_impl(struct os_mbuf *om) +{ + return nrf5340_ble_hci_acl_tx(om); +} + +void +ble_transport_hs_init(void) +{ + volatile struct hci_ipc_shm *shm = ipc_nrf5340_hci_shm_get(); + + hci_ipc_init(shm, &g_hci_ipc_sm); + nrf5340_ble_hci_init(); +} +#endif /* BLE_CONTROLLER */ + +#if !MYNEWT_VAL(BLE_CONTROLLER) +int +ble_transport_to_ll_cmd_impl(void *buf) +{ + struct hci_ipc_hdr hdr; + uint8_t *cmd = buf; + int rc; + + hdr.type = HCI_IPC_TYPE_CMD; + hdr.length = 3 + cmd[2]; + + rc = ipc_nrf5340_write(IPC_TX_CHANNEL, &hdr, sizeof(hdr), false); + if (rc == 0) { + rc = ipc_nrf5340_write(IPC_TX_CHANNEL, cmd, hdr.length, true); + } + + ble_transport_ipc_free(buf); + + return (rc < 0) ? BLE_ERR_MEM_CAPACITY : 0; +} + +int +ble_transport_to_ll_acl_impl(struct os_mbuf *om) +{ + return nrf5340_ble_hci_acl_tx(om); +} + +int +ble_transport_to_ll_iso_impl(struct os_mbuf *om) +{ + return nrf5340_ble_hci_iso_tx(om); +} + +void +ble_transport_ll_init(void) +{ + volatile struct hci_ipc_shm *shm = ipc_nrf5340_hci_shm_get(); + + hci_ipc_init(shm, &g_hci_ipc_sm); + nrf5340_ble_hci_init(); +} +#endif /* !BLE_CONTROLLER */ + +uint16_t +hci_ipc_atomic_get(volatile uint16_t *num) +{ + int ret; + + __asm__ volatile (".syntax unified \n" + "1: ldrexh r1, [%[addr]] \n" + " mov %[ret], r1 \n" + " cmp r1, #0 \n" + " itte ne \n" + " subne r2, r1, #1 \n" + " strexhne r1, r2, [%[addr]] \n" + " clrexeq \n" + " cmp r1, #0 \n" + " bne 1b \n" + : [ret] "=&r" (ret) + : [addr] "r" (num) + : "r1", "r2", "memory"); + + return ret; +} + +void +hci_ipc_atomic_put(volatile uint16_t *num) +{ + __asm__ volatile (".syntax unified \n" + "1: ldrexh r1, [%[addr]] \n" + " add r1, r1, #1 \n" + " strexh r2, r1, [%[addr]] \n" + " cmp r2, #0 \n" + " bne 1b \n" + : + : [addr] "r" (num) + : "r1", "r2", "memory"); +} + +#endif /* ARDUINO_ARCH_NRF5 && NRF53 */ diff --git a/src/nimble/nimble/transport/src/monitor.c b/src/nimble/nimble/transport/src/monitor.c deleted file mode 100644 index b6eaf597..00000000 --- a/src/nimble/nimble/transport/src/monitor.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "nimble/porting/nimble/include/syscfg/syscfg.h" - -#if MYNEWT_VAL(BLE_MONITOR_RTT) || MYNEWT_VAL(BLE_MONITOR_UART) - -#ifdef BABBLESIM -#define _GNU_SOURCE -#include -#endif - -#include -#include -#include -#include "nimble/porting/nimble/include/os/os.h" -#include "nimble/porting/nimble/include/log/log.h" -#if MYNEWT_VAL(BLE_MONITOR_UART) -#include "nimble/porting/nimble/include/uart/uart.h" -#endif -#if MYNEWT_VAL(BLE_MONITOR_RTT) -#include "rtt/SEGGER_RTT.h" -#endif -#include -#include -#include -#include "monitor_priv.h" - -struct ble_npl_mutex lock; - -#if MYNEWT_VAL(BLE_MONITOR_UART) -struct uart_dev *uart; - -static uint8_t tx_ringbuf[MYNEWT_VAL(BLE_MONITOR_UART_BUFFER_SIZE)]; -static uint8_t tx_ringbuf_head; -static uint8_t tx_ringbuf_tail; -#endif - -#if MYNEWT_VAL(BLE_MONITOR_RTT) -static uint8_t rtt_buf[MYNEWT_VAL(BLE_MONITOR_RTT_BUFFER_SIZE)]; -static int rtt_index; -#if MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED) -static uint8_t rtt_pktbuf[MYNEWT_VAL(BLE_MONITOR_RTT_BUFFER_SIZE)]; -static size_t rtt_pktbuf_pos; -static struct { - bool dropped; - struct ble_npl_callout tmo; - struct ble_monitor_drops_hdr drops_hdr; -} rtt_drops; - -#endif -#endif - -#if MYNEWT_VAL(BLE_MONITOR_UART) -static inline int -inc_and_wrap(int i, int max) -{ - return (i + 1) & (max - 1); -} - -static int -monitor_uart_rx_discard(void *arg, uint8_t ch) -{ - return 0; -} - -static int -monitor_uart_tx_char(void *arg) -{ - uint8_t ch; - - /* No more data */ - if (tx_ringbuf_head == tx_ringbuf_tail) { - return -1; - } - - ch = tx_ringbuf[tx_ringbuf_tail]; - tx_ringbuf_tail = inc_and_wrap(tx_ringbuf_tail, sizeof(tx_ringbuf)); - - return ch; -} - -static void -monitor_uart_queue_char(uint8_t ch) -{ - int sr; - - OS_ENTER_CRITICAL(sr); - - /* We need to try flush some data from ringbuffer if full */ - while (inc_and_wrap(tx_ringbuf_head, sizeof(tx_ringbuf)) == - tx_ringbuf_tail) { - uart_start_tx(uart); - OS_EXIT_CRITICAL(sr); - if (os_started()) { - os_time_delay(1); - } - OS_ENTER_CRITICAL(sr); - } - - tx_ringbuf[tx_ringbuf_head] = ch; - tx_ringbuf_head = inc_and_wrap(tx_ringbuf_head, sizeof(tx_ringbuf)); - - OS_EXIT_CRITICAL(sr); -} - -static void -monitor_write(const void *buf, size_t len) -{ - const uint8_t *ch = buf; - - while (len--) { - monitor_uart_queue_char(*ch++); - } - - uart_start_tx(uart); -} -#endif - -#if MYNEWT_VAL(BLE_MONITOR_RTT) - -#if MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED) -static void -update_drop_counters(struct ble_monitor_hdr *failed_hdr) -{ - uint8_t *cnt; - - rtt_drops.dropped = true; - - switch (failed_hdr->opcode) { - case BLE_MONITOR_OPCODE_COMMAND_PKT: - cnt = &rtt_drops.drops_hdr.cmd; - break; - case BLE_MONITOR_OPCODE_EVENT_PKT: - cnt = &rtt_drops.drops_hdr.evt; - break; - case BLE_MONITOR_OPCODE_ACL_TX_PKT: - cnt = &rtt_drops.drops_hdr.acl_tx; - break; - case BLE_MONITOR_OPCODE_ACL_RX_PKT: - cnt = &rtt_drops.drops_hdr.acl_rx; - break; - default: - cnt = &rtt_drops.drops_hdr.other; - break; - } - - if (*cnt < UINT8_MAX) { - (*cnt)++; - ble_npl_callout_reset(&rtt_drops.tmo, OS_TICKS_PER_SEC); - } -} - -static void -reset_drop_counters(void) -{ - rtt_drops.dropped = false; - rtt_drops.drops_hdr.cmd = 0; - rtt_drops.drops_hdr.evt = 0; - rtt_drops.drops_hdr.acl_tx = 0; - rtt_drops.drops_hdr.acl_rx = 0; - rtt_drops.drops_hdr.other = 0; - - ble_npl_callout_stop(&rtt_drops.tmo); -} -#endif - -static void -monitor_write(const void *buf, size_t len) -{ -#if MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED) - struct ble_monitor_hdr *hdr = (struct ble_monitor_hdr *) rtt_pktbuf; - bool discard; - unsigned ret = 0; - - /* We will discard any packet which exceeds length of intermediate buffer */ - discard = rtt_pktbuf_pos + len > sizeof(rtt_pktbuf); - - if (!discard) { - memcpy(rtt_pktbuf + rtt_pktbuf_pos, buf, len); - } - - rtt_pktbuf_pos += len; - if (rtt_pktbuf_pos < sizeof(hdr->data_len) + hdr->data_len) { - return; - } - - if (!discard) { - ret = SEGGER_RTT_WriteNoLock(rtt_index, rtt_pktbuf, rtt_pktbuf_pos); - } - - if (ret > 0) { - reset_drop_counters(); - } else { - update_drop_counters(hdr); - } - - rtt_pktbuf_pos = 0; -#else - SEGGER_RTT_WriteNoLock(rtt_index, buf, len); -#endif -} -#endif - -static void -monitor_write_header(uint16_t opcode, uint16_t len) -{ - struct ble_monitor_hdr hdr; - struct ble_monitor_ts_hdr ts_hdr; - uint8_t hdr_len; - int64_t ts; - - hdr_len = sizeof(ts_hdr); -#if MYNEWT_VAL(BLE_MONITOR_RTT) && MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED) - if (rtt_drops.dropped) { - hdr_len += sizeof(rtt_drops.drops_hdr); - } -#endif - - hdr.data_len = htole16(4 + hdr_len + len); - hdr.hdr_len = hdr_len; - hdr.opcode = htole16(opcode); - hdr.flags = 0; - - /* Use uptime for timestamp */ - ts = os_get_uptime_usec(); - - /* - * btsnoop specification states that fields of extended header must be - * sorted in increasing order so we will send drops (if any) headers before - * timestamp header. - */ - - monitor_write(&hdr, sizeof(hdr)); - -#if MYNEWT_VAL(BLE_MONITOR_RTT) && MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED) - if (rtt_drops.dropped) { - monitor_write(&rtt_drops.drops_hdr, sizeof(rtt_drops.drops_hdr)); - } -#endif - - ts_hdr.type = BLE_MONITOR_EXTHDR_TS32; - ts_hdr.ts32 = htole32(ts / 100); - - monitor_write(&ts_hdr, sizeof(ts_hdr)); -} - -#ifndef BABBLESIM -static size_t -btmon_write(FILE *instance, const char *bp, size_t n) -{ - monitor_write(bp, n); - - return n; -} - -static FILE *btmon = (FILE *) &(struct File) { - .vmt = &(struct File_methods) { - .write = btmon_write, - }, -}; -#endif - -#if MYNEWT_VAL(BLE_MONITOR_RTT) && MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED) -static void -drops_tmp_cb(struct ble_npl_event *ev) -{ - ble_npl_mutex_pend(&lock, OS_TIMEOUT_NEVER); - - /* - * There's no "nop" in btsnoop protocol so we just send empty system note - * to indicate drops. - */ - - monitor_write_header(BLE_MONITOR_OPCODE_SYSTEM_NOTE, 1); - monitor_write("", 1); - - ble_npl_mutex_release(&lock); -} -#endif - -void -ble_monitor_init(void) -{ - SYSINIT_ASSERT_ACTIVE(); - ble_npl_error_t rc; - -#if MYNEWT_VAL(BLE_MONITOR_UART) - struct uart_conf uc = { - .uc_speed = MYNEWT_VAL(BLE_MONITOR_UART_BAUDRATE), - .uc_databits = 8, - .uc_stopbits = 1, - .uc_parity = UART_PARITY_NONE, - .uc_flow_ctl = UART_FLOW_CTL_NONE, - .uc_tx_char = monitor_uart_tx_char, - .uc_rx_char = monitor_uart_rx_discard, - .uc_cb_arg = NULL, - }; - - uart = (struct uart_dev *)os_dev_open(MYNEWT_VAL(BLE_MONITOR_UART_DEV), - OS_TIMEOUT_NEVER, &uc); - SYSINIT_PANIC_ASSERT(uart); -#endif - -#if MYNEWT_VAL(BLE_MONITOR_RTT) -#if MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED) - ble_npl_callout_init(&rtt_drops.tmo, ble_npl_eventq_dflt_get(), drops_tmp_cb, NULL); - - /* Initialize types in header (we won't touch them later) */ - rtt_drops.drops_hdr.type_cmd = BLE_MONITOR_EXTHDR_COMMAND_DROPS; - rtt_drops.drops_hdr.type_evt = BLE_MONITOR_EXTHDR_EVENT_DROPS; - rtt_drops.drops_hdr.type_acl_tx = BLE_MONITOR_EXTHDR_ACL_TX_DROPS; - rtt_drops.drops_hdr.type_acl_rx = BLE_MONITOR_EXTHDR_ACL_RX_DROPS; - rtt_drops.drops_hdr.type_other = BLE_MONITOR_EXTHDR_OTHER_DROPS; - - rtt_index = SEGGER_RTT_AllocUpBuffer(MYNEWT_VAL(BLE_MONITOR_RTT_BUFFER_NAME), - rtt_buf, sizeof(rtt_buf), - SEGGER_RTT_MODE_NO_BLOCK_SKIP); -#else - rtt_index = SEGGER_RTT_AllocUpBuffer(MYNEWT_VAL(BLE_MONITOR_RTT_BUFFER_NAME), - rtt_buf, sizeof(rtt_buf), - SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); -#endif - - SYSINIT_PANIC_ASSERT(rtt_index >= 0); -#endif - - rc = ble_npl_mutex_init(&lock); - SYSINIT_PANIC_ASSERT(rc == 0); - -#if BLE_MONITOR - ble_monitor_new_index(0, (uint8_t[6]){ }, "nimble0"); -#endif -} - -void -ble_monitor_deinit(void) -{ -#if MYNEWT_VAL(BLE_MONITOR_RTT) && MYNEWT_VAL(BLE_MONITOR_RTT_BUFFERED) - ble_npl_callout_deinit(&rtt_drops.tmo); -#endif - ble_npl_mutex_deinit(&lock); -} - -int -ble_monitor_send(uint16_t opcode, const void *data, size_t len) -{ - ble_npl_mutex_pend(&lock, OS_TIMEOUT_NEVER); - - monitor_write_header(opcode, len); - monitor_write(data, len); - - ble_npl_mutex_release(&lock); - - return 0; -} - -int -ble_monitor_send_om(uint16_t opcode, const struct os_mbuf *om) -{ - const struct os_mbuf *om_tmp; - uint16_t length = 0; - - om_tmp = om; - while (om_tmp) { - length += om_tmp->om_len; - om_tmp = SLIST_NEXT(om_tmp, om_next); - } - - ble_npl_mutex_pend(&lock, OS_TIMEOUT_NEVER); - - monitor_write_header(opcode, length); - - while (om) { - monitor_write(om->om_data, om->om_len); - om = SLIST_NEXT(om, om_next); - } - - ble_npl_mutex_release(&lock); - - return 0; -} - -int -ble_monitor_new_index(uint8_t bus, uint8_t *addr, const char *name) -{ - struct ble_monitor_new_index pkt; - - pkt.type = 0; /* Primary controller, we don't support other */ - pkt.bus = bus; - memcpy(pkt.bdaddr, addr, 6); - strncpy(pkt.name, name, sizeof(pkt.name) - 1); - pkt.name[sizeof(pkt.name) - 1] = '\0'; - - ble_monitor_send(BLE_MONITOR_OPCODE_NEW_INDEX, &pkt, sizeof(pkt)); - - return 0; -} - -int -ble_monitor_log(int level, const char *fmt, ...) -{ - static const char id[] = "nimble"; - struct ble_monitor_user_logging ulog; - va_list va; - int len; - - va_start(va, fmt); - len = vsnprintf(NULL, 0, fmt, va); - va_end(va); - - switch (level) { - case LOG_LEVEL_ERROR: - ulog.priority = 3; - break; - case LOG_LEVEL_WARN: - ulog.priority = 4; - break; - case LOG_LEVEL_INFO: - ulog.priority = 6; - break; - case LOG_LEVEL_DEBUG: - ulog.priority = 7; - break; - default: - ulog.priority = 8; - break; - } - - ulog.ident_len = sizeof(id); - - ble_npl_mutex_pend(&lock, OS_TIMEOUT_NEVER); - - monitor_write_header(BLE_MONITOR_OPCODE_USER_LOGGING, - sizeof(ulog) + sizeof(id) + len + 1); - monitor_write(&ulog, sizeof(ulog)); - monitor_write(id, sizeof(id)); - -#ifdef BABBLESIM - do { - char *tmp; - int len; - - va_start(va, fmt); - len = vasprintf(&tmp, fmt, va); - assert(len >= 0); - va_end(va); - - monitor_write(tmp, len); - free(tmp); - } while (0); -#else - va_start(va, fmt); - vfprintf(btmon, fmt, va); - va_end(va); -#endif - - /* null-terminate string */ - monitor_write("", 1); - - ble_npl_mutex_release(&lock); - - return 0; -} - -int -ble_monitor_out(int c) -{ - static char buf[MYNEWT_VAL(BLE_MONITOR_CONSOLE_BUFFER_SIZE)]; - static size_t len; - - if (c != '\n') { - buf[len++] = c; - - if (len < sizeof(buf) - 1) { - return c; - } - } - - buf[len++] = '\0'; - - ble_monitor_send(BLE_MONITOR_OPCODE_SYSTEM_NOTE, buf, len); - len = 0; - - return c; -} - -int -ble_transport_to_ll_cmd(void *buf) -{ - struct ble_hci_cmd *cmd = buf; - - ble_monitor_send(BLE_MONITOR_OPCODE_COMMAND_PKT, buf, cmd->length + - sizeof(*cmd)); - - return ble_transport_to_ll_cmd_impl(buf); -} - -int -ble_transport_to_ll_acl(struct os_mbuf *om) -{ - ble_monitor_send_om(BLE_MONITOR_OPCODE_ACL_TX_PKT, om); - - return ble_transport_to_ll_acl_impl(om); -} - -int -ble_transport_to_hs_acl(struct os_mbuf *om) -{ - ble_monitor_send_om(BLE_MONITOR_OPCODE_ACL_RX_PKT, om); - - return ble_transport_to_hs_acl_impl(om); -} - -int -ble_transport_to_hs_evt(void *buf) -{ - struct ble_hci_ev *ev = buf; - - ble_monitor_send(BLE_MONITOR_OPCODE_EVENT_PKT, buf, ev->length + - sizeof(*ev)); - - return ble_transport_to_hs_evt_impl(buf); -} - -#endif /* MYNEWT_VAL(BLE_MONITOR_RTT) || MYNEWT_VAL(BLE_MONITOR_UART) */ diff --git a/src/nimble/nimble/transport/src/monitor_priv.h b/src/nimble/nimble/transport/src/monitor_priv.h deleted file mode 100644 index 0fb96509..00000000 --- a/src/nimble/nimble/transport/src/monitor_priv.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more 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 - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef H_BLE_MONITOR_PRIV_ -#define H_BLE_MONITOR_PRIV_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_MONITOR_OPCODE_NEW_INDEX 0 -#define BLE_MONITOR_OPCODE_DEL_INDEX 1 -#define BLE_MONITOR_OPCODE_COMMAND_PKT 2 -#define BLE_MONITOR_OPCODE_EVENT_PKT 3 -#define BLE_MONITOR_OPCODE_ACL_TX_PKT 4 -#define BLE_MONITOR_OPCODE_ACL_RX_PKT 5 -#define BLE_MONITOR_OPCODE_SCO_TX_PKT 6 -#define BLE_MONITOR_OPCODE_SCO_RX_PKT 7 -#define BLE_MONITOR_OPCODE_OPEN_INDEX 8 -#define BLE_MONITOR_OPCODE_CLOSE_INDEX 9 -#define BLE_MONITOR_OPCODE_INDEX_INFO 10 -#define BLE_MONITOR_OPCODE_VENDOR_DIAG 11 -#define BLE_MONITOR_OPCODE_SYSTEM_NOTE 12 -#define BLE_MONITOR_OPCODE_USER_LOGGING 13 - -#define BLE_MONITOR_EXTHDR_COMMAND_DROPS 1 -#define BLE_MONITOR_EXTHDR_EVENT_DROPS 2 -#define BLE_MONITOR_EXTHDR_ACL_RX_DROPS 3 -#define BLE_MONITOR_EXTHDR_ACL_TX_DROPS 4 -#define BLE_MONITOR_EXTHDR_SCO_RX_DROPS 5 -#define BLE_MONITOR_EXTHDR_SCO_TX_DROPS 6 -#define BLE_MONITOR_EXTHDR_OTHER_DROPS 7 -#define BLE_MONITOR_EXTHDR_TS32 8 - -struct ble_monitor_hdr { - uint16_t data_len; - uint16_t opcode; - uint8_t flags; - uint8_t hdr_len; -} __attribute__((packed)); - -struct ble_monitor_drops_hdr { - uint8_t type_cmd; - uint8_t cmd; - uint8_t type_evt; - uint8_t evt; - uint8_t type_acl_tx; - uint8_t acl_tx; - uint8_t type_acl_rx; - uint8_t acl_rx; - uint8_t type_other; - uint8_t other; -} __attribute__((packed)); - -struct ble_monitor_ts_hdr { - uint8_t type; - uint32_t ts32; -} __attribute__((packed)); - -struct ble_monitor_new_index { - uint8_t type; - uint8_t bus; - uint8_t bdaddr[6]; - char name[8]; -} __attribute__((packed)); - -struct ble_monitor_user_logging { - uint8_t priority; - uint8_t ident_len; -} __attribute__((packed)); - -int ble_monitor_send(uint16_t opcode, const void *data, size_t len); - -int ble_monitor_send_om(uint16_t opcode, const struct os_mbuf *om); - -int ble_monitor_new_index(uint8_t bus, uint8_t *addr, const char *name); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/nimble/nimble/transport/src/transport.c b/src/nimble/nimble/transport/src/transport.c index 0a464a8e..4e538591 100644 --- a/src/nimble/nimble/transport/src/transport.c +++ b/src/nimble/nimble/transport/src/transport.c @@ -18,14 +18,19 @@ */ #include -#include "nimble/porting/nimble/include/syscfg/syscfg.h" -#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/porting/nimble/include/os/os_mbuf.h" -#include "nimble/porting/nimble/include/os/os_mempool.h" -#include "nimble/nimble/include/nimble/ble.h" -#include "nimble/nimble/include/nimble/hci_common.h" -#include "nimble/nimble/transport/include/nimble/transport.h" +#include +#include +#include +#include +#include +#include +#include +#if BLE_TRANSPORT_IPC +#include +#endif +#ifdef ESP_PLATFORM #include "nimble/esp_port/port/include/esp_nimble_mem.h" +#endif int os_msys_buf_alloc(void); void os_msys_buf_free(void); @@ -35,7 +40,8 @@ void os_msys_buf_free(void); #define OMP_FLAG_FROM_MASK (0x03) #if MYNEWT_VAL(BLE_HS_FLOW_CTRL) || \ - MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) + MYNEWT_VAL(BLE_LL_CFG_FEAT_CTRL_TO_HOST_FLOW_CONTROL) || \ + (!MYNEWT_VAL(BLE_HOST) && BLE_TRANSPORT_IPC_ON_HS) #define POOL_CMD_COUNT (2) #else #define POOL_CMD_COUNT (1) @@ -49,18 +55,26 @@ void os_msys_buf_free(void); #if MYNEWT_VAL_CHOICE(BLE_TRANSPORT_LL, native) && \ MYNEWT_VAL_CHOICE(BLE_TRANSPORT_HS, native) #define POOL_ACL_COUNT (0) +#define POOL_ISO_COUNT (0) #elif !MYNEWT_VAL_CHOICE(BLE_TRANSPORT_LL, native) && \ !MYNEWT_VAL_CHOICE(BLE_TRANSPORT_HS, native) #define POOL_ACL_COUNT ((MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_HS_COUNT)) + \ (MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT))) +#define POOL_ISO_COUNT ((MYNEWT_VAL(BLE_TRANSPORT_ISO_FROM_HS_COUNT)) + \ + (MYNEWT_VAL(BLE_TRANSPORT_ISO_FROM_LL_COUNT))) #elif MYNEWT_VAL_CHOICE(BLE_TRANSPORT_LL, native) #define POOL_ACL_COUNT (MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_HS_COUNT)) +#define POOL_ISO_COUNT (MYNEWT_VAL(BLE_TRANSPORT_ISO_FROM_HS_COUNT)) #else #define POOL_ACL_COUNT (MYNEWT_VAL(BLE_TRANSPORT_ACL_FROM_LL_COUNT)) +#define POOL_ISO_COUNT (MYNEWT_VAL(BLE_TRANSPORT_ISO_FROM_LL_COUNT)) #endif #define POOL_ACL_SIZE (OS_ALIGN( MYNEWT_VAL(BLE_TRANSPORT_ACL_SIZE) + \ BLE_MBUF_MEMBLOCK_OVERHEAD + \ BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)) +#define POOL_ISO_SIZE (OS_ALIGN(MYNEWT_VAL(BLE_TRANSPORT_ISO_SIZE) + \ + BLE_MBUF_MEMBLOCK_OVERHEAD + \ + BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)) #if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED @@ -74,11 +88,19 @@ static struct os_mempool pool_evt; static os_membuf_t *pool_evt_lo_buf; static struct os_mempool pool_evt_lo; +#if POOL_ACL_COUNT > 0 static os_membuf_t *pool_acl_buf; static struct os_mempool_ext pool_acl; static struct os_mbuf_pool mpool_acl; +#endif -#else +#if POOL_ISO_COUNT > 0 +static os_membuf_t *pool_iso_buf; +static struct os_mempool_ext pool_iso; +static struct os_mbuf_pool mpool_iso; +#endif + +#else // !ESP_PLATFORM static uint8_t pool_cmd_buf[ OS_MEMPOOL_BYTES(POOL_CMD_COUNT, POOL_CMD_SIZE) ]; static struct os_mempool pool_cmd; @@ -89,9 +111,17 @@ static struct os_mempool pool_evt; static uint8_t pool_evt_lo_buf[ OS_MEMPOOL_BYTES(POOL_EVT_LO_COUNT, POOL_EVT_SIZE) ]; static struct os_mempool pool_evt_lo; +#if POOL_ACL_COUNT > 0 static uint8_t pool_acl_buf[ OS_MEMPOOL_BYTES(POOL_ACL_COUNT, POOL_ACL_SIZE) ]; static struct os_mempool_ext pool_acl; static struct os_mbuf_pool mpool_acl; +#endif + +#if POOL_ISO_COUNT > 0 +static uint8_t pool_iso_buf[ OS_MEMPOOL_BYTES(POOL_ISO_COUNT, POOL_ISO_SIZE) ]; +static struct os_mempool_ext pool_iso; +static struct os_mbuf_pool mpool_iso; +#endif #endif // ESP_PLATFORM @@ -103,17 +133,48 @@ ble_transport_alloc_cmd(void) return os_memblock_get(&pool_cmd); } +static void * +try_alloc_evt(struct os_mempool *mp) +{ +#if BLE_TRANSPORT_IPC_ON_LL + uint8_t type; +#endif + void *buf; + +#if BLE_TRANSPORT_IPC_ON_LL + if (mp == &pool_evt) { + type = HCI_IPC_TYPE_EVT; + } else { + type = HCI_IPC_TYPE_EVT_DISCARDABLE; + } + + if (!hci_ipc_get(type)) { + return NULL; + } +#endif + + buf = os_memblock_get(mp); + +#if BLE_TRANSPORT_IPC_ON_LL + if (!buf) { + hci_ipc_put(type); + } +#endif + + return buf; +} + void * ble_transport_alloc_evt(int discardable) { void *buf; if (discardable) { - buf = os_memblock_get(&pool_evt_lo); + buf = try_alloc_evt(&pool_evt_lo); } else { - buf = os_memblock_get(&pool_evt); + buf = try_alloc_evt(&pool_evt); if (!buf) { - buf = os_memblock_get(&pool_evt_lo); + buf = try_alloc_evt(&pool_evt_lo); } } @@ -123,6 +184,7 @@ ble_transport_alloc_evt(int discardable) struct os_mbuf * ble_transport_alloc_acl_from_hs(void) { +#if POOL_ACL_COUNT > 0 struct os_mbuf *om; struct os_mbuf_pkthdr *pkthdr; uint16_t usrhdr_len; @@ -140,11 +202,41 @@ ble_transport_alloc_acl_from_hs(void) } return om; +#else + return NULL; +#endif +} + +struct os_mbuf * +ble_transport_alloc_iso_from_hs(void) +{ +#if POOL_ISO_COUNT > 0 + struct os_mbuf *om; + struct os_mbuf_pkthdr *pkthdr; + uint16_t usrhdr_len; + +#if MYNEWT_VAL_CHOICE(BLE_TRANSPORT_LL, native) + usrhdr_len = sizeof(struct ble_mbuf_hdr); +#else + usrhdr_len = 0; +#endif + + om = os_mbuf_get_pkthdr(&mpool_iso, usrhdr_len); + if (om) { + pkthdr = OS_MBUF_PKTHDR(om); + pkthdr->omp_flags = OMP_FLAG_FROM_HS; + } + + return om; +#else + return NULL; +#endif } struct os_mbuf * ble_transport_alloc_acl_from_ll(void) { +#if POOL_ACL_COUNT > 0 struct os_mbuf *om; struct os_mbuf_pkthdr *pkthdr; @@ -155,10 +247,52 @@ ble_transport_alloc_acl_from_ll(void) } return om; +#else + return NULL; +#endif +} + +struct os_mbuf * +ble_transport_alloc_iso_from_ll(void) +{ +#if POOL_ISO_COUNT > 0 + struct os_mbuf *om; + struct os_mbuf_pkthdr *pkthdr; + + om = os_mbuf_get_pkthdr(&mpool_iso, 0); + if (om) { + pkthdr = OS_MBUF_PKTHDR(om); + pkthdr->omp_flags = OMP_FLAG_FROM_LL; + } + + return om; +#else + return NULL; +#endif } void ble_transport_free(void *buf) +{ + if (os_memblock_from(&pool_cmd, buf)) { + os_memblock_put(&pool_cmd, buf); + } else if (os_memblock_from(&pool_evt, buf)) { + os_memblock_put(&pool_evt, buf); +#if BLE_TRANSPORT_IPC + hci_ipc_put(HCI_IPC_TYPE_EVT); +#endif + } else if (os_memblock_from(&pool_evt_lo, buf)) { + os_memblock_put(&pool_evt_lo, buf); +#if BLE_TRANSPORT_IPC + hci_ipc_put(HCI_IPC_TYPE_EVT_DISCARDABLE); +#endif + } else { + assert(0); + } +} + +void +ble_transport_ipc_free(void *buf) { if (os_memblock_from(&pool_cmd, buf)) { os_memblock_put(&pool_cmd, buf); @@ -172,6 +306,8 @@ ble_transport_free(void *buf) } #ifdef ESP_PLATFORM + +#if POOL_ACL_COUNT > 0 static os_error_t ble_transport_acl_put(struct os_mempool_ext *mpe, void *data, void *arg) { @@ -199,13 +335,13 @@ ble_transport_acl_put(struct os_mempool_ext *mpe, void *data, void *arg) from_ll = (pkthdr->omp_flags & OMP_FLAG_FROM_MASK) == OMP_FLAG_FROM_LL; if (from_ll && !err) { - ble_transport_int_flow_ctl_put(); + hci_ipc_put(HCI_IPC_TYPE_ACL); } #endif return err; } - +#endif void ble_buf_free(void) { @@ -217,8 +353,14 @@ void ble_buf_free(void) pool_evt_lo_buf = NULL; nimble_platform_mem_free(pool_cmd_buf); pool_cmd_buf = NULL; +#if POOL_ACL_COUNT > 0 nimble_platform_mem_free(pool_acl_buf); pool_acl_buf = NULL; +#endif +#if POOL_ISO_COUNT > 0 + nimble_platform_mem_free(pool_iso_buf); + pool_iso_buf = NULL; +#endif } esp_err_t ble_buf_alloc(void) @@ -238,19 +380,34 @@ esp_err_t ble_buf_alloc(void) pool_cmd_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, (sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(POOL_CMD_COUNT, POOL_CMD_SIZE))); +#if POOL_ACL_COUNT > 0 pool_acl_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, (sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(POOL_ACL_COUNT, POOL_ACL_SIZE))); - - if (!pool_evt_buf || !pool_evt_lo_buf || !pool_cmd_buf || !pool_acl_buf) { + if(!pool_acl_buf) { + ble_buf_free(); + return ESP_ERR_NO_MEM; + } +#endif +#if POOL_ISO_COUNT > 0 + pool_iso_buf = (os_membuf_t *) nimble_platform_mem_calloc(1, + sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(POOL_ISO_COUNT, + POOL_ISO_SIZE)); + if(!pool_iso_buf) { + ble_buf_free(); + return ESP_ERR_NO_MEM; + } +#endif + if (!pool_evt_buf || !pool_evt_lo_buf || !pool_cmd_buf ) { ble_buf_free(); return ESP_ERR_NO_MEM; } return ESP_OK; } -#else // ESP_PLATFORM +#else /* !ESP_PLATFORM */ +#if POOL_ACL_COUNT > 0 static os_error_t ble_transport_acl_put(struct os_mempool_ext *mpe, void *data, void *arg) { @@ -276,16 +433,16 @@ ble_transport_acl_put(struct os_mempool_ext *mpe, void *data, void *arg) err = os_memblock_put_from_cb(&mpe->mpe_mp, data); } -#if MYNEWT_VAL(BLE_TRANSPORT_INT_FLOW_CTL) +#if BLE_TRANSPORT_IPC_ON_HS if (from_ll && !err) { - ble_transport_int_flow_ctl_put(); + hci_ipc_put(HCI_IPC_TYPE_ACL); } #endif return err; } - -#endif // ESP_PLATFORM +#endif +#endif /* ESP_PLATFORM */ void ble_transport_init(void) @@ -306,6 +463,7 @@ ble_transport_init(void) pool_evt_lo_buf, "transport_pool_evt_lo"); SYSINIT_PANIC_ASSERT(rc == 0); +#if POOL_ACL_COUNT > 0 rc = os_mempool_ext_init(&pool_acl, POOL_ACL_COUNT, POOL_ACL_SIZE, pool_acl_buf, "transport_pool_acl"); SYSINIT_PANIC_ASSERT(rc == 0); @@ -315,15 +473,27 @@ ble_transport_init(void) SYSINIT_PANIC_ASSERT(rc == 0); pool_acl.mpe_put_cb = ble_transport_acl_put; +#endif + +#if POOL_ISO_COUNT > 0 + rc = os_mempool_ext_init(&pool_iso, POOL_ISO_COUNT, POOL_ISO_SIZE, + pool_iso_buf, "transport_pool_iso"); + SYSINIT_PANIC_ASSERT(rc == 0); + + rc = os_mbuf_pool_init(&mpool_iso, &pool_iso.mpe_mp, + POOL_ISO_SIZE, POOL_ISO_COUNT); + SYSINIT_PANIC_ASSERT(rc == 0); +#endif } -#ifdef ESP_PLATFORM void ble_transport_deinit(void) { int rc = 0; +#if POOL_ISO_COUNT > 0 rc = os_mempool_ext_clear(&pool_acl); SYSINIT_PANIC_ASSERT(rc == 0); +#endif rc = os_mempool_clear(&pool_evt_lo); SYSINIT_PANIC_ASSERT(rc == 0); @@ -334,7 +504,6 @@ ble_transport_deinit(void) rc = os_mempool_clear(&pool_cmd); SYSINIT_PANIC_ASSERT(rc == 0); } -#endif // ESP_PLATFORM int ble_transport_register_put_acl_from_ll_cb(os_mempool_put_fn (*cb)) @@ -343,4 +512,21 @@ ble_transport_register_put_acl_from_ll_cb(os_mempool_put_fn (*cb)) return 0; } + +#if BLE_TRANSPORT_IPC +uint8_t +ble_transport_ipc_buf_evt_type_get(void *buf) +{ + if (os_memblock_from(&pool_cmd, buf)) { + return HCI_IPC_TYPE_EVT_IN_CMD; + } else if (os_memblock_from(&pool_evt, buf)) { + return HCI_IPC_TYPE_EVT; + } else if (os_memblock_from(&pool_evt_lo, buf)) { + return HCI_IPC_TYPE_EVT_DISCARDABLE; + } else { + assert(0); + } + return 0; +} #endif +#endif /* !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED */ diff --git a/src/nimble/porting/nimble/include/hal/hal_gpio.h b/src/nimble/porting/nimble/include/hal/hal_gpio.h new file mode 100644 index 00000000..0bc4db6c --- /dev/null +++ b/src/nimble/porting/nimble/include/hal/hal_gpio.h @@ -0,0 +1,170 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @addtogroup HAL + * @{ + * @defgroup HALGpio HAL GPIO + * @{ + */ + +#ifndef H_HAL_GPIO_ +#define H_HAL_GPIO_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The "mode" of the gpio. The gpio is either an input, output, or it is + * "not connected" (the pin specified is not functioning as a gpio) + */ +enum hal_gpio_mode_e { + /** Not connected */ + HAL_GPIO_MODE_NC = -1, + /** Input */ + HAL_GPIO_MODE_IN = 0, + /** Output */ + HAL_GPIO_MODE_OUT = 1 +}; +typedef enum hal_gpio_mode_e hal_gpio_mode_t; + +/* + * The "pull" of the gpio. This is either an input or an output. + */ +enum hal_gpio_pull { + /** Pull-up/down not enabled */ + HAL_GPIO_PULL_NONE = 0, + /** Pull-up enabled */ + HAL_GPIO_PULL_UP = 1, + /** Pull-down enabled */ + HAL_GPIO_PULL_DOWN = 2 +}; +typedef enum hal_gpio_pull hal_gpio_pull_t; + +/* + * IRQ trigger type. + */ +enum hal_gpio_irq_trigger { + HAL_GPIO_TRIG_NONE = 0, + /** IRQ occurs on rising edge */ + HAL_GPIO_TRIG_RISING = 1, + /** IRQ occurs on falling edge */ + HAL_GPIO_TRIG_FALLING = 2, + /** IRQ occurs on either edge */ + HAL_GPIO_TRIG_BOTH = 3, + /** IRQ occurs when line is low */ + HAL_GPIO_TRIG_LOW = 4, + /** IRQ occurs when line is high */ + HAL_GPIO_TRIG_HIGH = 5 +}; +typedef enum hal_gpio_irq_trigger hal_gpio_irq_trig_t; + +/* Function proto for GPIO irq handler functions */ +typedef void (*hal_gpio_irq_handler_t)(void *arg); + +/** + * Initializes the specified pin as an input + * + * @param pin Pin number to set as input + * @param pull pull type + * + * @return int 0: no error; -1 otherwise. + */ +int hal_gpio_init_in(int pin, hal_gpio_pull_t pull); + +/** + * Initialize the specified pin as an output, setting the pin to the specified + * value. + * + * @param pin Pin number to set as output + * @param val Value to set pin + * + * @return int 0: no error; -1 otherwise. + */ +int hal_gpio_init_out(int pin, int val); + +/** + * Deinitialize the specified pin to revert the previous initialization + * + * @param pin Pin number to unset + * + * @return int 0: no error; -1 otherwise. + */ +int hal_gpio_deinit(int pin); + +/** + * Write a value (either high or low) to the specified pin. + * + * @param pin Pin to set + * @param val Value to set pin (0:low 1:high) + */ +void hal_gpio_write(int pin, int val); + +/** + * Reads the specified pin. + * + * @param pin Pin number to read + * + * @return int 0: low, 1: high + */ +int hal_gpio_read(int pin); + +/** + * Toggles the specified pin + * + * @param pin Pin number to toggle + * + * @return current gpio state int 0: low, 1: high + */ +int hal_gpio_toggle(int pin); + +/** + * Initialize a given pin to trigger a GPIO IRQ callback. + * + * @param pin The pin to trigger GPIO interrupt on + * @param handler The handler function to call + * @param arg The argument to provide to the IRQ handler + * @param trig The trigger mode (e.g. rising, falling) + * @param pull The mode of the pin (e.g. pullup, pulldown) + * + * @return 0 on success, non-zero error code on failure. + */ +int hal_gpio_irq_init(int pin, hal_gpio_irq_handler_t handler, void *arg, + hal_gpio_irq_trig_t trig, hal_gpio_pull_t pull); + +/** + * Release a pin from being configured to trigger IRQ on state change. + * + * @param pin The pin to release + */ +void hal_gpio_irq_release(int pin); + +/** + * Enable IRQs on the passed pin + * + * @param pin The pin to enable IRQs on + */ +void hal_gpio_irq_enable(int pin); + +/** + * Disable IRQs on the passed pin + * + * @param pin The pin to disable IRQs on + */ +void hal_gpio_irq_disable(int pin); + + +#ifdef __cplusplus +} +#endif + +#endif /* H_HAL_GPIO_ */ + +/** + * @} HALGpio + * @} HAL + */ diff --git a/src/nimble/porting/nimble/include/hal/hal_os_tick.h b/src/nimble/porting/nimble/include/hal/hal_os_tick.h new file mode 100644 index 00000000..37d7c1d3 --- /dev/null +++ b/src/nimble/porting/nimble/include/hal/hal_os_tick.h @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @addtogroup HAL + * @{ + * @defgroup HALOsTick HAL OS Tick + * @{ + */ + +#ifndef H_HAL_OS_TICK_ +#define H_HAL_OS_TICK_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nimble/porting/nimble/include/os/os.h" + +typedef long os_time_t; + +void hal_rtc_intr_init(void); + +/** + * Set up the periodic timer to interrupt at a frequency of 'os_ticks_per_sec'. + * 'prio' is the cpu-specific priority of the periodic timer interrupt. + * + * @param os_ticks_per_sec Frequency of the OS tick timer + * @param prio Priority of the OS tick timer + */ +void bleonly_os_tick_init(uint32_t os_ticks_per_sec); + +/** + * Halt CPU for up to 'n' ticks. + * + * @param n The number of ticks to halt the CPU for + */ +void os_tick_idle(os_time_t n); + + +#ifdef __cplusplus +} +#endif + +#endif /* H_HAL_OS_TICK_ */ + +/** + * @} HALOsTick + * @} HAL + */ diff --git a/src/nimble/porting/nimble/include/hal/hal_system.h b/src/nimble/porting/nimble/include/hal/hal_system.h new file mode 100644 index 00000000..bf07da2c --- /dev/null +++ b/src/nimble/porting/nimble/include/hal/hal_system.h @@ -0,0 +1,96 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @addtogroup HAL + * @{ + * @defgroup HALSystem HAL System + * @{ + */ + +#ifndef H_HAL_SYSTEM_ +#define H_HAL_SYSTEM_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * System reset. + */ +void hal_system_reset(void) __attribute((noreturn)); + +/** + * Called by bootloader to start loaded program. + */ +void hal_system_start(void *img_start) __attribute((noreturn)); + +/** + * Called by split app loader to start the app program. + */ +void hal_system_restart(void *img_start) __attribute((noreturn)); + +/** + * Returns non-zero if there is a HW debugger attached. + */ +int hal_debugger_connected(void); + +/** + * Reboot reason + */ +enum hal_reset_reason { + /** Power on Reset */ + HAL_RESET_POR = 1, + /** Caused by Reset Pin */ + HAL_RESET_PIN = 2, + /** Caused by Watchdog */ + HAL_RESET_WATCHDOG = 3, + /** Soft reset, either system reset or crash */ + HAL_RESET_SOFT = 4, + /** Low supply voltage */ + HAL_RESET_BROWNOUT = 5, + /** Restart due to user request */ + HAL_RESET_REQUESTED = 6, + /** System Off, wakeup on external interrupt*/ + HAL_RESET_SYS_OFF_INT = 7, + /** Restart due to DFU */ + HAL_RESET_DFU = 8, +}; + +/** + * Return the reboot reason + * + * @return A reboot reason + */ +enum hal_reset_reason hal_reset_cause(void); + +/** + * Return the reboot reason as a string + * + * @return String describing previous reset reason + */ +const char *hal_reset_cause_str(void); + +/** + * Starts clocks needed by system + */ +void hal_system_clock_start(void); + +/** + * Reset callback to be called before an reset happens inside hal_system_reset() + */ +void hal_system_reset_cb(void); + +#ifdef __cplusplus +} +#endif + +#endif /* H_HAL_SYSTEM_ */ + +/** + * @} HALSystem + * @} HAL + */ diff --git a/src/nimble/porting/nimble/include/hal/hal_timer.h b/src/nimble/porting/nimble/include/hal/hal_timer.h index 936545d8..f7c0b896 100644 --- a/src/nimble/porting/nimble/include/hal/hal_timer.h +++ b/src/nimble/porting/nimble/include/hal/hal_timer.h @@ -29,7 +29,7 @@ #define H_HAL_TIMER_ #include -#include "../os/queue.h" +#include "nimble/porting/nimble/include/os/queue.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/porting/nimble/include/hal/hal_uart.h b/src/nimble/porting/nimble/include/hal/hal_uart.h new file mode 100644 index 00000000..8673c776 --- /dev/null +++ b/src/nimble/porting/nimble/include/hal/hal_uart.h @@ -0,0 +1,146 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @addtogroup HAL + * @{ + * @defgroup HALUart HAL UART + * @{ + */ + +#ifndef H_HAL_UART_H_ +#define H_HAL_UART_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "driver/uart.h" + +/** + * Function prototype for UART driver to ask for more data to send. + * Returns -1 if no more data is available for TX. + * Driver must call this with interrupts disabled. + */ +typedef int (*hal_uart_tx_char)(void *arg); + +/** + * Function prototype for UART driver to report that transmission is + * complete. This should be called when transmission of last byte is + * finished. + * Driver must call this with interrupts disabled. + */ +typedef void (*hal_uart_tx_done)(void *arg); + +/** + * Function prototype for UART driver to report incoming byte of data. + * Returns -1 if data was dropped. + * Driver must call this with interrupts disabled. + */ +typedef int (*hal_uart_rx_char)(void *arg, uint8_t byte); + +/** + * Initializes given uart. Mapping of logical UART number to physical + * UART/GPIO pins is in BSP. + */ +int hal_uart_init_cbs(int uart, hal_uart_tx_char tx_func, + hal_uart_tx_done tx_done, hal_uart_rx_char rx_func, void *arg); + +/** + * De Initialize already registerd callbacks + */ +void hal_uart_deinit_cbs(void); + +enum hal_uart_parity { + /** No Parity */ + HAL_UART_PARITY_NONE = 0, + /** Odd parity */ + HAL_UART_PARITY_ODD = 1, + /** Even parity */ + HAL_UART_PARITY_EVEN = 2 +}; + +enum hal_uart_flow_ctl { + /** No Flow Control */ + HAL_UART_FLOW_CTL_NONE = 0, + /** RTS/CTS */ + HAL_UART_FLOW_CTL_RTS_CTS = 1 +}; + +/** + * Initialize the HAL uart. + * + * @param uart The uart number to configure + * @param cfg Hardware specific uart configuration. This is passed from BSP + * directly to the MCU specific driver. + * + * @return 0 on success, non-zero error code on failure + */ +int hal_uart_init(int uart, void *cfg); + +/** + * Applies given configuration to UART. + * + * @param uart The UART number to configure + * @param speed The baudrate in bps to configure + * @param databits The number of databits to send per byte + * @param stopbits The number of stop bits to send + * @param parity The UART parity + * @param flow_ctl Flow control settings on the UART + * + * @return 0 on success, non-zero error code on failure + */ +int hal_uart_config(int uart, int32_t speed, uint8_t databits, uint8_t stopbits, + enum hal_uart_parity parity, enum hal_uart_flow_ctl flow_ctl); + +/** + * Close UART port. Can call hal_uart_config() with different settings after + * calling this. + * + * @param uart The UART number to close + */ +int hal_uart_close(int uart); + +/** + * More data queued for transmission. UART driver will start asking for that + * data. + * + * @param uart The UART number to start TX on + */ +void hal_uart_start_tx(int uart); + +/** + * Upper layers have consumed some data, and are now ready to receive more. + * This is meaningful after uart_rx_char callback has returned -1 telling + * that no more data can be accepted. + * + * @param uart The UART number to begin RX on + */ +void hal_uart_start_rx(int uart); + +/** + * This is type of write where UART has to block until character has been sent. + * Used when printing diag output from system crash. + * Must be called with interrupts disabled. + * + * @param uart The UART number to TX on + * @param byte The byte to TX on the UART + */ +void hal_uart_blocking_tx(int uart, uint8_t byte); + +#ifdef __cplusplus +} +#endif + + +#endif /* H_HAL_UART_H_ */ + + +/** + * @} HALUart + * @} HAL + */ diff --git a/src/nimble/porting/nimble/include/hal/hal_watchdog.h b/src/nimble/porting/nimble/include/hal/hal_watchdog.h new file mode 100644 index 00000000..d0658bf0 --- /dev/null +++ b/src/nimble/porting/nimble/include/hal/hal_watchdog.h @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @addtogroup HAL + * @{ + * @defgroup HALWatchdog HAL Watchdog + * @{ + */ + +#ifndef _HAL_WATCHDOG_H_ +#define _HAL_WATCHDOG_H_ + +#include +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Set a recurring watchdog timer to fire no sooner than in 'expire_secs' + * seconds. Watchdog should be tickled periodically with a frequency + * smaller than 'expire_secs'. Watchdog needs to be then started with + * a call to :c:func:`hal_watchdog_enable()`. + * + * @param expire_msecs Watchdog timer expiration time in msecs + * + * @return < 0 on failure; on success return the actual + * expiration time as positive value + */ +int hal_watchdog_init(uint32_t expire_msecs); + +/** + * Starts the watchdog. + */ +void hal_watchdog_enable(void); + +/** + * Tickles the watchdog. This needs to be done periodically, before + * the value configured in :c:func:`hal_watchdog_init()` expires. + */ +void hal_watchdog_tickle(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _HAL_WATCHDOG_H_ */ + +/** + * @} HALWatchdog + * @} HAL + */ diff --git a/src/nimble/porting/nimble/include/log_common/log_common.h b/src/nimble/porting/nimble/include/log_common/log_common.h index 5803a668..92daa595 100644 --- a/src/nimble/porting/nimble/include/log_common/log_common.h +++ b/src/nimble/porting/nimble/include/log_common/log_common.h @@ -21,7 +21,7 @@ #define H_LOG_COMMON_ #include -#include "ignore.h" +#include "nimble/porting/nimble/include/log_common/ignore.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/porting/nimble/include/logcfg/logcfg.h b/src/nimble/porting/nimble/include/logcfg/logcfg.h index 2676acef..d2025065 100644 --- a/src/nimble/porting/nimble/include/logcfg/logcfg.h +++ b/src/nimble/porting/nimble/include/logcfg/logcfg.h @@ -1,12 +1,12 @@ /** - * This file was generated by Apache newt version: 1.10.0-dev + * This file was generated by Apache newt version: 1.11.0-dev */ #ifndef H_LOGCFG_ #define H_LOGCFG_ -#include "../modlog/modlog.h" -#include "../log_common/log_common.h" +#include "nimble/porting/nimble/include/modlog/modlog.h" +#include "nimble/porting/nimble/include/log_common/log_common.h" #if (MYNEWT_VAL(BLE_HS_LOG_LVL) == LOG_LEVEL_DEBUG) #define BLE_HS_LOG_DEBUG(...) MODLOG_DEBUG(4, __VA_ARGS__) @@ -166,4 +166,11 @@ #define DFLT_LOG_CRITICAL(...) MODLOG_CRITICAL(0, __VA_ARGS__) #define DFLT_LOG_DISABLED(...) MODLOG_DISABLED(0, __VA_ARGS__) +#define BLE_EATT_LOG_DEBUG(...) IGNORE(__VA_ARGS__) +#define BLE_EATT_LOG_INFO(...) MODLOG_INFO(22, __VA_ARGS__) +#define BLE_EATT_LOG_WARN(...) MODLOG_WARN(22, __VA_ARGS__) +#define BLE_EATT_LOG_ERROR(...) MODLOG_ERROR(22, __VA_ARGS__) +#define BLE_EATT_LOG_CRITICAL(...) MODLOG_CRITICAL(22, __VA_ARGS__) +#define BLE_EATT_LOG_DISABLED(...) MODLOG_DISABLED(22, __VA_ARGS__) + #endif diff --git a/src/nimble/porting/nimble/include/mem/mem.h b/src/nimble/porting/nimble/include/mem/mem.h index 6f0656a0..348b3033 100644 --- a/src/nimble/porting/nimble/include/mem/mem.h +++ b/src/nimble/porting/nimble/include/mem/mem.h @@ -100,6 +100,13 @@ struct os_mbuf *mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz, void *mem_pullup_obj(struct os_mbuf **om, uint16_t len); #endif + +#ifndef ESP_PLATFORM +#define nimble_platform_mem_malloc malloc +#define nimble_platform_mem_calloc calloc +#define nimble_platform_mem_free free +#endif + #ifdef __cplusplus } #endif diff --git a/src/nimble/porting/nimble/include/modlog/modlog.h b/src/nimble/porting/nimble/include/modlog/modlog.h index 2d56be99..04287f43 100644 --- a/src/nimble/porting/nimble/include/modlog/modlog.h +++ b/src/nimble/porting/nimble/include/modlog/modlog.h @@ -22,9 +22,9 @@ #include -#include "../log_common/log_common.h" -#include "../log/log.h" -#include "../log_common/log_common.h" +#include "nimble/porting/nimble/include/log_common/log_common.h" +#include "nimble/porting/nimble/include/log/log.h" +#include "nimble/porting/nimble/include/log_common/log_common.h" #ifdef ESP_PLATFORM #include "esp_log.h" @@ -60,35 +60,35 @@ #define MODLOG_DEBUG(ml_mod_, ml_msg_, ...) \ printf((ml_msg_), ##__VA_ARGS__) #else -#define MODLOG_DEBUG(ml_mod_, ...) +#define MODLOG_DEBUG(ml_mod_, ...) IGNORE(__VA_ARGS__) #endif #if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_INFO || defined __DOXYGEN__ #define MODLOG_INFO(ml_mod_, ml_msg_, ...) \ printf((ml_msg_), ##__VA_ARGS__) #else -#define MODLOG_INFO(ml_mod_, ...) +#define MODLOG_INFO(ml_mod_, ...) IGNORE(__VA_ARGS__) #endif #if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_WARN || defined __DOXYGEN__ #define MODLOG_WARN(ml_mod_, ml_msg_, ...) \ printf((ml_msg_), ##__VA_ARGS__) #else -#define MODLOG_WARN(ml_mod_, ...) +#define MODLOG_WARN(ml_mod_, ...) IGNORE(__VA_ARGS__) #endif #if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_ERROR || defined __DOXYGEN__ #define MODLOG_ERROR(ml_mod_, ml_msg_, ...) \ printf((ml_msg_), ##__VA_ARGS__) #else -#define MODLOG_ERROR(ml_mod_, ...) +#define MODLOG_ERROR(ml_mod_, ...) IGNORE(__VA_ARGS__) #endif #if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_CRITICAL || defined __DOXYGEN__ #define MODLOG_CRITICAL(ml_mod_, ml_msg_, ...) \ printf((ml_msg_), ##__VA_ARGS__) #else -#define MODLOG_CRITICAL(ml_mod_, ...) +#define MODLOG_CRITICAL(ml_mod_, ...) IGNORE(__VA_ARGS__) #endif #endif diff --git a/src/nimble/porting/nimble/include/nimble/nimble_port.h b/src/nimble/porting/nimble/include/nimble/nimble_port.h index c4159d4c..6d77f6ea 100644 --- a/src/nimble/porting/nimble/include/nimble/nimble_port.h +++ b/src/nimble/porting/nimble/include/nimble/nimble_port.h @@ -21,14 +21,15 @@ #define _NIMBLE_PORT_H #include "nimble/nimble/include/nimble/nimble_npl.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #ifdef ESP_PLATFORM #include "esp_err.h" #include "nimconfig.h" #define NIMBLE_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY) + #define NIMBLE_HS_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE #else -#include "../syscfg/syscfg.h" #define NIMBLE_HS_STACK_SIZE (CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE / 4) #endif diff --git a/src/nimble/porting/nimble/include/os/os.h b/src/nimble/porting/nimble/include/os/os.h index c07f3cfc..34bd8d69 100644 --- a/src/nimble/porting/nimble/include/os/os.h +++ b/src/nimble/porting/nimble/include/os/os.h @@ -30,7 +30,7 @@ extern "C" { #define static_assert _Static_assert #endif -#include "../syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/nimble/include/nimble/nimble_npl.h" #define OS_ALIGN(__n, __a) ( \ @@ -46,11 +46,11 @@ typedef uint32_t os_sr_t; #define OS_ASSERT_CRITICAL() assert(ble_npl_hw_is_in_critical()) /* Mynewt components (not abstracted in NPL) */ -#include "endian.h" -#include "queue.h" -#include "os_error.h" -#include "os_mbuf.h" -#include "os_mempool.h" +#include "nimble/porting/nimble/include/os/endian.h" +#include "nimble/porting/nimble/include/os/queue.h" +#include "nimble/porting/nimble/include/os/os_error.h" +#include "nimble/porting/nimble/include/os/os_mbuf.h" +#include "nimble/porting/nimble/include/os/os_mempool.h" #ifdef __cplusplus } diff --git a/src/nimble/porting/nimble/include/os/os_cputime.h b/src/nimble/porting/nimble/include/os/os_cputime.h index 820bf5d1..de0aad83 100644 --- a/src/nimble/porting/nimble/include/os/os_cputime.h +++ b/src/nimble/porting/nimble/include/os/os_cputime.h @@ -31,8 +31,8 @@ extern "C" { #endif -#include "../syscfg/syscfg.h" -#include "../hal/hal_timer.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/hal/hal_timer.h" /* * NOTE: these definitions allow one to override the cputime frequency used. diff --git a/src/nimble/porting/nimble/include/os/os_error.h b/src/nimble/porting/nimble/include/os/os_error.h index 44f5d870..c330fcc2 100644 --- a/src/nimble/porting/nimble/include/os/os_error.h +++ b/src/nimble/porting/nimble/include/os/os_error.h @@ -20,7 +20,7 @@ #ifndef H_OS_ERROR_ #define H_OS_ERROR_ -#include "os.h" +#include "nimble/porting/nimble/include/os/os.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/porting/nimble/include/os/os_mbuf.h b/src/nimble/porting/nimble/include/os/os_mbuf.h index 2304bcad..31d5b86e 100644 --- a/src/nimble/porting/nimble/include/os/os_mbuf.h +++ b/src/nimble/porting/nimble/include/os/os_mbuf.h @@ -36,7 +36,7 @@ #ifndef _OS_MBUF_H #define _OS_MBUF_H -#include "os.h" +#include "nimble/porting/nimble/include/os/os.h" #ifdef __cplusplus extern "C" { @@ -139,12 +139,13 @@ struct os_mqueue { ((__om)->om_pkthdr_len >= sizeof (struct os_mbuf_pkthdr)) /** Get a packet header pointer given an mbuf pointer */ -#define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *) \ - (void *)((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf))) +#define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *)(uintptr_t) \ + (void *)((uint8_t *)&(__om)->om_data \ + + sizeof(struct os_mbuf))) /** Given a mbuf packet header pointer, return a pointer to the mbuf */ #define OS_MBUF_PKTHDR_TO_MBUF(__hdr) \ - (struct os_mbuf *)(void *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf)) + (struct os_mbuf *)(uintptr_t)((uint8_t *)(__hdr) - sizeof(struct os_mbuf)) /** * Gets the length of an entire mbuf chain. The specified mbuf must have a diff --git a/src/nimble/porting/nimble/include/os/os_mempool.h b/src/nimble/porting/nimble/include/os/os_mempool.h index d22d2b93..d1ed8726 100644 --- a/src/nimble/porting/nimble/include/os/os_mempool.h +++ b/src/nimble/porting/nimble/include/os/os_mempool.h @@ -29,8 +29,8 @@ #define _OS_MEMPOOL_H_ #include -#include "os.h" -#include "queue.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/os/queue.h" #ifdef __cplusplus extern "C" { diff --git a/src/nimble/porting/nimble/include/os/os_trace_api.h b/src/nimble/porting/nimble/include/os/os_trace_api.h index 70f88b69..005a098b 100644 --- a/src/nimble/porting/nimble/include/os/os_trace_api.h +++ b/src/nimble/porting/nimble/include/os/os_trace_api.h @@ -30,11 +30,11 @@ #include #include -#include "../syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #if MYNEWT_VAL(OS_SYSVIEW) #include "sysview/vendor/SEGGER_SYSVIEW.h" #endif -#include "os.h" +#include "nimble/porting/nimble/include/os/os.h" #define OS_TRACE_ID_EVENTQ_PUT (40) #define OS_TRACE_ID_EVENTQ_GET_NO_WAIT (41) diff --git a/src/nimble/porting/nimble/include/syscfg/syscfg.h b/src/nimble/porting/nimble/include/syscfg/syscfg.h index 53caee6c..6614a4b1 100644 --- a/src/nimble/porting/nimble/include/syscfg/syscfg.h +++ b/src/nimble/porting/nimble/include/syscfg/syscfg.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.10.0-dev + * This file was generated by Apache newt version: 1.11.0-dev */ #ifndef H_SYSCFG_ @@ -110,6 +110,152 @@ #define MYNEWT_VAL_BLE_LL_HCI_VS (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_CSFC_SIZE +#define MYNEWT_VAL_BLE_GATT_CSFC_SIZE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE +#define MYNEWT_VAL_BLE_MESH_NET_BUF_USER_DATA_SIZE (4) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_TX_PWR_MAX_DBM +#define MYNEWT_VAL_BLE_LL_TX_PWR_MAX_DBM (20) +#endif + +#ifndef MYNEWT_VAL_BLE_LL_CONN_EVENT_END_MARGIN +#define MYNEWT_VAL_BLE_LL_CONN_EVENT_END_MARGIN (0) +#endif + +#ifndef MYNEWT_VAL_BLE_FEM_LNA +#define MYNEWT_VAL_BLE_FEM_LNA (0) +#endif + +#ifndef MYNEWT_VAL_BLE_FEM_LNA_GAIN +#define MYNEWT_VAL_BLE_FEM_LNA_GAIN (0) +#endif + +#ifndef MYNEWT_VAL_BLE_FEM_PA +#define MYNEWT_VAL_BLE_FEM_PA (0) +#endif + +#ifndef MYNEWT_VAL_BLE_FEM_PA_GAIN +#define MYNEWT_VAL_BLE_FEM_PA_GAIN (0) +#endif + +#ifndef MYNEWT_VAL_BLE_L2CAP_COC_SDU_BUFF_COUNT +#define MYNEWT_VAL_BLE_L2CAP_COC_SDU_BUFF_COUNT (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + +#ifndef CONFIG_BT_NIMBLE_GATT_CACHING +#define MYNEWT_VAL_BLE_GATT_CACHING (0) +#else +#define MYNEWT_VAL_BLE_GATT_CACHING (CONFIG_BT_NIMBLE_GATT_CACHING) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE +#define MYNEWT_VAL_BLE_MESH_MODEL_VND_MSG_CID_FORCE (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG +#define MYNEWT_VAL_BLE_MESH_ACCESS_LAYER_MSG (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_CDB +#define MYNEWT_VAL_BLE_MESH_CDB (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT +#define MYNEWT_VAL_BLE_MESH_UNPROV_BEACON_INT (5) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_DEFAULT_TTL +#define MYNEWT_VAL_BLE_MESH_DEFAULT_TTL (7) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT +#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_COUNT (2) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL +#define MYNEWT_VAL_BLE_MESH_NETWORK_TRANSMIT_INTERVAL (20) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT +#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_COUNT (2) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL +#define MYNEWT_VAL_BLE_MESH_RELAY_RETRANSMIT_INTERVAL (20) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RELAY_ENABLED +#define MYNEWT_VAL_BLE_MESH_RELAY_ENABLED (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_BEACON_ENABLED +#define MYNEWT_VAL_BLE_MESH_BEACON_ENABLED (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED +#define MYNEWT_VAL_BLE_MESH_GATT_PROXY_ENABLED (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED +#define MYNEWT_VAL_BLE_MESH_FRIEND_ENABLED (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR +#define MYNEWT_VAL_BLE_MESH_LPN_SUB_ALL_NODES_ADDR (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS +#define MYNEWT_VAL_BLE_MESH_LOOPBACK_BUFS (3) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT +#define MYNEWT_VAL_BLE_MESH_IV_UPDATE_SEQ_LIMIT (0x800000) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT +#define MYNEWT_VAL_BLE_MESH_PB_ADV_RETRANS_TIMEOUT (500) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY +#define MYNEWT_VAL_BLE_MESH_PROV_OOB_PUBLIC_KEY (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_RX_SEG_MAX +#define MYNEWT_VAL_BLE_MESH_RX_SEG_MAX (3) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_SEG_BUFS +#define MYNEWT_VAL_BLE_MESH_SEG_BUFS (64) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST +#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_UNICAST (400) +#endif + +#ifndef MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP +#define MYNEWT_VAL_BLE_MESH_TX_SEG_RETRANS_TIMEOUT_GROUP (50) +#endif + +#ifndef MYNEWT_VAL_BLE_STORE_MAX_CSFCS +#define MYNEWT_VAL_BLE_STORE_MAX_CSFCS (CONFIG_BT_NIMBLE_MAX_CONNECTIONS) +#endif + +#ifndef MYNEWT_VAL_BLE_SM_LVL +#define MYNEWT_VAL_BLE_SM_LVL (0) +#endif + #endif /* !ESP_PLATFORM */ #if 0 @@ -129,7 +275,7 @@ #endif #ifndef MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME -#define MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME ("trng") +#define MYNEWT_VAL_TINYCRYPT_UECC_RNG_TRNG_DEV_NAME "trng" #endif #ifndef MYNEWT_VAL_TINYCRYPT_UECC_RNG_USE_TRNG @@ -424,7 +570,7 @@ #endif #ifndef MYNEWT_VAL_CONSOLE_UART_DEV -#define MYNEWT_VAL_CONSOLE_UART_DEV ("uart0") +#define MYNEWT_VAL_CONSOLE_UART_DEV "uart0" #endif #ifndef MYNEWT_VAL_CONSOLE_UART_FLOW_CONTROL @@ -538,6 +684,10 @@ #endif /*** @apache-mynewt-nimble/nimble */ +#ifndef MYNEWT_VAL_BLE_CONN_SUBRATING +#define MYNEWT_VAL_BLE_CONN_SUBRATING (0) +#endif + #ifndef MYNEWT_VAL_BLE_EXT_ADV #define MYNEWT_VAL_BLE_EXT_ADV (0) #endif @@ -586,6 +736,10 @@ #define MYNEWT_VAL_BLE_PERIODIC_ADV_SYNC_TRANSFER (0) #endif +#ifndef MYNEWT_VAL_BLE_POWER_CONTROL +#define MYNEWT_VAL_BLE_POWER_CONTROL (0) +#endif + #ifndef MYNEWT_VAL_BLE_ROLE_BROADCASTER #define MYNEWT_VAL_BLE_ROLE_BROADCASTER (1) #endif @@ -610,10 +764,6 @@ #define MYNEWT_VAL_BLE_WHITELIST (1) #endif -#ifndef MYNEWT_VAL_BLE_POWER_CONTROL -#define MYNEWT_VAL_BLE_POWER_CONTROL (0) -#endif - /*** @apache-mynewt-nimble/nimble/host */ #ifndef MYNEWT_VAL_BLE_ATT_PREFERRED_MTU #define MYNEWT_VAL_BLE_ATT_PREFERRED_MTU (256) @@ -639,6 +789,10 @@ #define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI +#define MYNEWT_VAL_BLE_ATT_SVR_NOTIFY_MULTI (MYNEWT_VAL_BLE_ATT_SVR_NOTIFY && (MYNEWT_VAL_BLE_VERSION >= 52)) +#endif + #ifndef MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE #define MYNEWT_VAL_BLE_ATT_SVR_QUEUED_WRITE (1) #endif @@ -679,6 +833,22 @@ #define MYNEWT_VAL_BLE_ATT_SVR_WRITE_NO_RSP (1) #endif +#ifndef MYNEWT_VAL_BLE_EATT_CHAN_NUM +#define MYNEWT_VAL_BLE_EATT_CHAN_NUM (0) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_LVL +#define MYNEWT_VAL_BLE_EATT_LOG_LVL (1) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_LOG_MOD +#define MYNEWT_VAL_BLE_EATT_LOG_MOD (27) +#endif + +#ifndef MYNEWT_VAL_BLE_EATT_MTU +#define MYNEWT_VAL_BLE_EATT_MTU (128) +#endif + #ifndef MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE #define MYNEWT_VAL_BLE_GAP_MAX_PENDING_CONN_PARAM_UPDATE (1) #endif @@ -719,6 +889,10 @@ #define MYNEWT_VAL_BLE_GATT_NOTIFY (1) #endif +#ifndef MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE +#define MYNEWT_VAL_BLE_GATT_NOTIFY_MULTIPLE (1) +#endif + #ifndef MYNEWT_VAL_BLE_GATT_READ #define MYNEWT_VAL_BLE_GATT_READ (MYNEWT_VAL_BLE_ROLE_CENTRAL) #endif @@ -839,6 +1013,10 @@ #define MYNEWT_VAL_BLE_L2CAP_COC_MPS (MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8) #endif +#ifndef MYNEWT_VAL_BLE_L2CAP_COC_SDU_BUFF_COUNT +#define MYNEWT_VAL_BLE_L2CAP_COC_SDU_BUFF_COUNT (1) +#endif + #ifndef MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC #define MYNEWT_VAL_BLE_L2CAP_ENHANCED_COC (0) #endif @@ -863,42 +1041,6 @@ #define MYNEWT_VAL_BLE_MESH (1) #endif -#ifndef MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE -#define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128) -#endif - -#ifndef MYNEWT_VAL_BLE_MONITOR_RTT -#define MYNEWT_VAL_BLE_MONITOR_RTT (0) -#endif - -#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED -#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1) -#endif - -#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME -#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME ("btmonitor") -#endif - -#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE -#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256) -#endif - -#ifndef MYNEWT_VAL_BLE_MONITOR_UART -#define MYNEWT_VAL_BLE_MONITOR_UART (0) -#endif - -#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE -#define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000) -#endif - -#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE -#define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64) -#endif - -#ifndef MYNEWT_VAL_BLE_MONITOR_UART_DEV -#define MYNEWT_VAL_BLE_MONITOR_UART_DEV ("uart0") -#endif - #ifndef MYNEWT_VAL_BLE_RPA_TIMEOUT #define MYNEWT_VAL_BLE_RPA_TIMEOUT (300) #endif @@ -919,6 +1061,10 @@ #define MYNEWT_VAL_BLE_SM_LEGACY (1) #endif +#ifndef MYNEWT_VAL_BLE_SM_LVL +#define MYNEWT_VAL_BLE_SM_LVL (0) +#endif + #ifndef MYNEWT_VAL_BLE_SM_MAX_PROCS #define MYNEWT_VAL_BLE_SM_MAX_PROCS (1) #endif @@ -943,10 +1089,6 @@ #define MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS (0) #endif -#ifndef MYNEWT_VAL_BLE_SM_SC_LVL -#define MYNEWT_VAL_BLE_SM_SC_LVL (0) -#endif - #ifndef MYNEWT_VAL_BLE_SM_SC_ONLY #define MYNEWT_VAL_BLE_SM_SC_ONLY (0) #endif @@ -1338,7 +1480,7 @@ #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_DEFAULT -#define MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_DEFAULT ("Apache Mynewt NimBLE") +#define MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_DEFAULT "Apache Mynewt NimBLE" #endif #ifndef MYNEWT_VAL_BLE_SVC_DIS_MODEL_NUMBER_READ_PERM @@ -1399,7 +1541,7 @@ #endif #ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME -#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME ("nimble") +#define MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME "nimble" #endif #ifndef MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH @@ -1470,6 +1612,42 @@ #undef MYNEWT_VAL_BLE_HCI_TRANSPORT +#ifndef MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE +#define MYNEWT_VAL_BLE_MONITOR_CONSOLE_BUFFER_SIZE (128) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT +#define MYNEWT_VAL_BLE_MONITOR_RTT (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFERED (1) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_NAME "btmonitor" +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE +#define MYNEWT_VAL_BLE_MONITOR_RTT_BUFFER_SIZE (256) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART +#define MYNEWT_VAL_BLE_MONITOR_UART (0) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE +#define MYNEWT_VAL_BLE_MONITOR_UART_BAUDRATE (1000000) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE +#define MYNEWT_VAL_BLE_MONITOR_UART_BUFFER_SIZE (64) +#endif + +#ifndef MYNEWT_VAL_BLE_MONITOR_UART_DEV +#define MYNEWT_VAL_BLE_MONITOR_UART_DEV "uart0" +#endif + #ifndef MYNEWT_VAL_BLE_TRANSPORT #define MYNEWT_VAL_BLE_TRANSPORT (1) #endif @@ -1489,7 +1667,7 @@ #endif #ifndef MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE -#define MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE (255) +#define MYNEWT_VAL_BLE_TRANSPORT_ACL_SIZE (251) #endif #ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_COUNT @@ -1504,11 +1682,13 @@ #define MYNEWT_VAL_BLE_TRANSPORT_EVT_DISCARDABLE_COUNT (16) #endif -/* Overridden by @apache-mynewt-nimble/nimble/transport (defined by @apache-mynewt-nimble/nimble/transport) */ #ifndef MYNEWT_VAL_BLE_TRANSPORT_EVT_SIZE -#define MYNEWT_VAL_BLE_TRANSPORT_EVT_SIZE (257) +#define MYNEWT_VAL_BLE_TRANSPORT_EVT_SIZE (70) #endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__cdc +#define MYNEWT_VAL_BLE_TRANSPORT_HS__cdc (0) +#endif #ifndef MYNEWT_VAL_BLE_TRANSPORT_HS__custom #define MYNEWT_VAL_BLE_TRANSPORT_HS__custom (0) #endif @@ -1532,12 +1712,18 @@ #endif /* Overridden by @apache-mynewt-nimble/porting/targets/porting_default (defined by @apache-mynewt-nimble/nimble/transport) */ +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__apollo3 +#define MYNEWT_VAL_BLE_TRANSPORT_LL__apollo3 (0) +#endif #ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__custom #define MYNEWT_VAL_BLE_TRANSPORT_LL__custom (0) #endif #ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__dialog_cmac #define MYNEWT_VAL_BLE_TRANSPORT_LL__dialog_cmac (0) #endif +#ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__emspi +#define MYNEWT_VAL_BLE_TRANSPORT_LL__emspi (0) +#endif #ifndef MYNEWT_VAL_BLE_TRANSPORT_LL__native #define MYNEWT_VAL_BLE_TRANSPORT_LL__native (0) #endif @@ -1588,7 +1774,7 @@ /*** newt */ #ifndef MYNEWT_VAL_APP_NAME -#define MYNEWT_VAL_APP_NAME ("dummy_app") +#define MYNEWT_VAL_APP_NAME "dummy_app" #endif #ifndef MYNEWT_VAL_APP_dummy_app @@ -1596,7 +1782,7 @@ #endif #ifndef MYNEWT_VAL_ARCH_NAME -#define MYNEWT_VAL_ARCH_NAME ("sim") +#define MYNEWT_VAL_ARCH_NAME "sim" #endif #ifndef MYNEWT_VAL_ARCH_sim @@ -1604,7 +1790,7 @@ #endif #ifndef MYNEWT_VAL_BSP_NAME -#define MYNEWT_VAL_BSP_NAME ("native") +#define MYNEWT_VAL_BSP_NAME "native" #endif #ifndef MYNEWT_VAL_BSP_native @@ -1620,16 +1806,57 @@ #endif #ifndef MYNEWT_VAL_TARGET_NAME -#define MYNEWT_VAL_TARGET_NAME ("porting_default") +#define MYNEWT_VAL_TARGET_NAME "porting_default" #endif #ifndef MYNEWT_VAL_TARGET_porting_default #define MYNEWT_VAL_TARGET_porting_default (1) #endif -#ifndef MYNEWT_VAL_BLE_LL_CONN_PHY_DEFAULT_PREF_MASK -#define MYNEWT_VAL_BLE_LL_CONN_PHY_DEFAULT_PREF_MASK (0x07) -#endif +/*** Included packages */ +#define MYNEWT_PKG_apache_mynewt_core__compiler_sim 1 +#define MYNEWT_PKG_apache_mynewt_core__crypto_tinycrypt 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_bsp_native 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_drivers_flash_enc_flash 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_drivers_flash_enc_flash_ef_tinycrypt 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_drivers_trng 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_drivers_trng_trng_sw 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_drivers_uart 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_drivers_uart_uart_hal 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_hal 1 +#define MYNEWT_PKG_apache_mynewt_core__hw_mcu_native 1 +#define MYNEWT_PKG_apache_mynewt_core__kernel_os 1 +#define MYNEWT_PKG_apache_mynewt_core__kernel_sim 1 +#define MYNEWT_PKG_apache_mynewt_core__net_ip_mn_socket 1 +#define MYNEWT_PKG_apache_mynewt_core__net_ip_native_sockets 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_console_stub 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_defs 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_flash_map 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_log_common 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_log_modlog 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_log_stub 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_stats_stub 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_sys 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_sysdown 1 +#define MYNEWT_PKG_apache_mynewt_core__sys_sysinit 1 +#define MYNEWT_PKG_apache_mynewt_core__util_mem 1 +#define MYNEWT_PKG_apache_mynewt_core__util_rwlock 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_ans 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_bas 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_dis 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_gap 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_gatt 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_ias 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_ipss 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_lls 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_host_services_tps 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_transport 1 +#define MYNEWT_PKG_apache_mynewt_nimble__nimble_transport_socket 1 +#define MYNEWT_PKG_apache_mynewt_nimble__porting_npl_mynewt 1 +#define MYNEWT_PKG_apache_mynewt_nimble__porting_targets_dummy_app 1 +#define MYNEWT_PKG_apache_mynewt_nimble__porting_targets_porting_default 1 #endif #endif diff --git a/src/nimble/porting/nimble/include/sysflash/sysflash.h b/src/nimble/porting/nimble/include/sysflash/sysflash.h index 28391ca6..8d358ac9 100644 --- a/src/nimble/porting/nimble/include/sysflash/sysflash.h +++ b/src/nimble/porting/nimble/include/sysflash/sysflash.h @@ -1,5 +1,5 @@ /** - * This file was generated by Apache newt version: 1.10.0-dev + * This file was generated by Apache newt version: 1.11.0-dev */ #ifndef H_MYNEWT_SYSFLASH_ @@ -15,10 +15,33 @@ extern const struct flash_area sysflash_map_dflt[6]; #define FLASH_AREA_BOOTLOADER 0 +#define FLASH_AREA_BOOTLOADER_DEVICE 0 +#define FLASH_AREA_BOOTLOADER_OFFSET 0x00000000 +#define FLASH_AREA_BOOTLOADER_SIZE 16384 + #define FLASH_AREA_IMAGE_0 1 +#define FLASH_AREA_IMAGE_0_DEVICE 0 +#define FLASH_AREA_IMAGE_0_OFFSET 0x00020000 +#define FLASH_AREA_IMAGE_0_SIZE 393216 + #define FLASH_AREA_IMAGE_1 2 +#define FLASH_AREA_IMAGE_1_DEVICE 0 +#define FLASH_AREA_IMAGE_1_OFFSET 0x00080000 +#define FLASH_AREA_IMAGE_1_SIZE 393216 + #define FLASH_AREA_IMAGE_SCRATCH 3 +#define FLASH_AREA_IMAGE_SCRATCH_DEVICE 0 +#define FLASH_AREA_IMAGE_SCRATCH_OFFSET 0x000e0000 +#define FLASH_AREA_IMAGE_SCRATCH_SIZE 131072 + #define FLASH_AREA_REBOOT_LOG 16 +#define FLASH_AREA_REBOOT_LOG_DEVICE 0 +#define FLASH_AREA_REBOOT_LOG_OFFSET 0x00004000 +#define FLASH_AREA_REBOOT_LOG_SIZE 16384 + #define FLASH_AREA_NFFS 17 +#define FLASH_AREA_NFFS_DEVICE 0 +#define FLASH_AREA_NFFS_OFFSET 0x00008000 +#define FLASH_AREA_NFFS_SIZE 32768 #endif diff --git a/src/nimble/porting/nimble/src/endian.c b/src/nimble/porting/nimble/src/endian.c index f8563924..a5becc51 100644 --- a/src/nimble/porting/nimble/src/endian.c +++ b/src/nimble/porting/nimble/src/endian.c @@ -17,7 +17,7 @@ * under the License. */ -#include "../include/os/endian.h" +#include "nimble/porting/nimble/include/os/endian.h" void put_le16(void *buf, uint16_t x) diff --git a/src/nimble/porting/nimble/src/hal_timer.c b/src/nimble/porting/nimble/src/hal_timer.c index 611a5fe2..289b0cf1 100644 --- a/src/nimble/porting/nimble/src/hal_timer.c +++ b/src/nimble/porting/nimble/src/hal_timer.c @@ -22,10 +22,10 @@ #include #include #include -#include "../include/os/os.h" +#include "nimble/porting/nimble/include/os/os.h" #include "nrfx.h" -#include "../include/hal/hal_timer.h" -#include "../include/os/os_trace_api.h" +#include "nimble/porting/nimble/include/hal/hal_timer.h" +#include "nimble/porting/nimble/include/os/os_trace_api.h" /* IRQ prototype */ typedef void (*hal_timer_irq_handler_t)(void); @@ -185,7 +185,7 @@ nrf_timer_set_ocmp(struct nrf52_hal_timer *bsptimer, uint32_t expiry) } else { rtctimer->INTENCLR = RTC_INTENCLR_TICK_Msk; - if (delta_t < (1UL << 24)) { + if (delta_t < (1L << 24)) { rtctimer->CC[NRF_RTC_TIMER_CC_INT] = expiry & 0x00ffffff; } else { /* CC too far ahead. Just make sure we set compare far ahead */ @@ -539,8 +539,10 @@ hal_timer_init(int timer_num, void *cfg) /* Disable IRQ, set priority and set vector in table */ NVIC_DisableIRQ(irq_num); +#ifndef RIOT_VERSION NVIC_SetPriority(irq_num, (1 << __NVIC_PRIO_BITS) - 1); -#if MYNEWT +#endif +#ifdef MYNEWT NVIC_SetVector(irq_num, (uint32_t)irq_isr); #else ble_npl_hw_set_isr(irq_num, irq_isr); diff --git a/src/nimble/porting/nimble/src/mem.c b/src/nimble/porting/nimble/src/mem.c index 5edfd2c3..7c666cb9 100644 --- a/src/nimble/porting/nimble/src/mem.c +++ b/src/nimble/porting/nimble/src/mem.c @@ -18,9 +18,11 @@ */ #include -#include "../include/os/os.h" -#include "../include/mem/mem.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/mem/mem.h" +#ifdef ESP_PLATFORM #include "nimble/esp_port/port/include/esp_nimble_mem.h" +#endif /** * Generic mempool allocation function. Used with basic and extended mempools. @@ -32,11 +34,7 @@ mem_malloc_mempool_gen(uint16_t num_blocks, uint32_t block_size, block_size = OS_ALIGN(block_size, OS_ALIGNMENT); if (num_blocks > 0) { -#ifdef ESP_PLATFORM *out_buf = nimble_platform_mem_malloc(OS_MEMPOOL_BYTES(num_blocks, block_size)); -#else - *out_buf = malloc(OS_MEMPOOL_BYTES(num_blocks, block_size)); -#endif if (*out_buf == NULL) { return OS_ENOMEM; } @@ -77,11 +75,7 @@ mem_malloc_mempool(struct os_mempool *mempool, uint16_t num_blocks, rc = os_mempool_init(mempool, num_blocks, block_size, buf, name); if (rc != 0) { -#ifdef ESP_PLATFORM nimble_platform_mem_free(buf); -#else - free(buf); -#endif return rc; } @@ -122,11 +116,7 @@ mem_malloc_mempool_ext(struct os_mempool_ext *mpe, uint16_t num_blocks, rc = os_mempool_ext_init(mpe, num_blocks, block_size, buf, name); if (rc != 0) { -#ifdef ESP_PLATFORM nimble_platform_mem_free(buf); -#else - free(buf); -#endif return rc; } @@ -173,11 +163,7 @@ mem_malloc_mbuf_pool(struct os_mempool *mempool, rc = os_mbuf_pool_init(mbuf_pool, mempool, block_size, num_blocks); if (rc != 0) { -#ifdef ESP_PLATFORM nimble_platform_mem_free(buf); -#else - free(buf); -#endif return rc; } diff --git a/src/nimble/porting/nimble/src/nimble_port.c b/src/nimble/porting/nimble/src/nimble_port.c index 215d8f3e..41be8329 100644 --- a/src/nimble/porting/nimble/src/nimble_port.c +++ b/src/nimble/porting/nimble/src/nimble_port.c @@ -18,58 +18,52 @@ */ #include -#include "../include/os/os.h" -#include "../include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" + +#if CONFIG_BT_NIMBLE_ENABLED #include "nimble/nimble/host/include/host/ble_hs.h" -#include "../include/nimble/nimble_port.h" -#include "../../npl/freertos/include/nimble/nimble_port_freertos.h" -#if NIMBLE_CFG_CONTROLLER -#include "nimble/nimble/controller/include/controller/ble_ll.h" -#include "nimble/porting/nimble/include/hal/hal_timer.h" -#include "nimble/porting/nimble/include/os/os_cputime.h" -#endif +#endif //CONFIG_BT_NIMBLE_ENABLED +#include "nimble/porting/nimble/include/nimble/nimble_port.h" +#include "nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h" #ifdef ESP_PLATFORM #include "esp_log.h" -# if defined __has_include -# if __has_include ("soc/soc_caps.h") -# include "soc/soc_caps.h" -# endif -# endif +#include "soc/soc_caps.h" #include "esp_intr_alloc.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #if CONFIG_BT_CONTROLLER_ENABLED #include "esp_bt.h" #endif - #if !SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED #include "nimble/esp_port/esp-hci/include/esp_nimble_hci.h" #endif #if !CONFIG_BT_CONTROLLER_ENABLED #include "nimble/nimble/transport/include/nimble/transport.h" #endif -#endif - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" +// #if (BT_HCI_LOG_INCLUDED == TRUE) +// #include "hci_log/bt_hci_log.h" +// #endif // (BT_HCI_LOG_INCLUDED == TRUE) +// #include "bt_common.h" #define NIMBLE_PORT_LOG_TAG "BLE_INIT" +#endif // ESP_PLATFORM extern void os_msys_init(void); +extern void os_mempool_module_init(void); #if CONFIG_BT_NIMBLE_ENABLED - extern void ble_hs_deinit(void); -static struct ble_hs_stop_listener stop_listener; - #endif //CONFIG_BT_NIMBLE_ENABLED static struct ble_npl_eventq g_eventq_dflt; + +#ifdef ESP_PLATFORM static struct ble_npl_sem ble_hs_stop_sem; +static struct ble_hs_stop_listener stop_listener; static struct ble_npl_event ble_hs_ev_stop; -extern void os_msys_init(void); -extern void os_mempool_module_init(void); - /** * Called when the host stop procedure has completed. */ @@ -85,7 +79,6 @@ nimble_port_stop_cb(struct ble_npl_event *ev) ble_npl_sem_release(&ble_hs_stop_sem); } -#ifdef ESP_PLATFORM /** * @brief esp_nimble_init - Initialize the NimBLE host stack * @@ -97,13 +90,10 @@ esp_err_t esp_nimble_init(void) esp_err_t ret; #endif #if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED - -#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS /* Initialize the function pointers for OS porting */ npl_freertos_funcs_init(); npl_freertos_mempool_init(); -#endif #if false // Arduino disable #if CONFIG_BT_CONTROLLER_ENABLED @@ -112,8 +102,8 @@ esp_err_t esp_nimble_init(void) return ESP_FAIL; } #else - //ret = ble_buf_alloc(); - if (ble_buf_alloc() != ESP_OK) { + ret = ble_buf_alloc(); + if (ret != ESP_OK) { ble_buf_free(); return ESP_FAIL; } @@ -131,11 +121,10 @@ esp_err_t esp_nimble_init(void) os_msys_init(); #endif + + ble_transport_ll_init(); /* Initialize the host */ ble_transport_hs_init(); -#if CONFIG_BT_CONTROLLER_DISABLED && CONFIG_BT_NIMBLE_TRANSPORT_UART - ble_transport_ll_init(); -#endif return ESP_OK; } @@ -165,10 +154,10 @@ esp_err_t esp_nimble_deinit(void) #endif ble_hs_deinit(); #if !SOC_ESP_NIMBLE_CONTROLLER || !CONFIG_BT_CONTROLLER_ENABLED -#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS npl_freertos_funcs_deinit(); #endif -#endif + + ble_transport_ll_deinit(); return ESP_OK; } @@ -226,6 +215,10 @@ nimble_port_init(void) return ret; } +// #if MYNEWT_VAL(BT_HCI_LOG_INCLUDED) +// bt_hci_log_init(); +// #endif // (BT_HCI_LOG_INCLUDED == TRUE) + return ESP_OK; } @@ -260,10 +253,13 @@ nimble_port_deinit(void) } #endif +#if (BT_HCI_LOG_INCLUDED == TRUE) + //bt_hci_log_deinit(); +#endif // (BT_HCI_LOG_INCLUDED == TRUE) + return ESP_OK; } - int nimble_port_stop(void) { @@ -273,8 +269,8 @@ nimble_port_stop(void) rc = ble_npl_sem_init(&ble_hs_stop_sem, 0); if( rc != 0) { - ESP_LOGE(NIMBLE_PORT_LOG_TAG, "sem init failed with reason: %d", rc); - return rc; + ESP_LOGE(NIMBLE_PORT_LOG_TAG, "sem init failed with reason: %d \n", rc); + return rc; } /* Initiate a host stop procedure. */ @@ -324,16 +320,20 @@ IRAM_ATTR nimble_port_get_dflt_eventq(void) return &g_eventq_dflt; } -#else // ESP_PLATFORM +#else // !ESP_PLATFORM + +#if NIMBLE_CFG_CONTROLLER +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#include "nimble/porting/nimble/include/hal/hal_timer.h" +#include "nimble/porting/nimble/include/os/os_cputime.h" +//#include "nimble/nimble/transport/include/nimble/transport.h" +#endif void nimble_port_init(void) { -#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS npl_freertos_funcs_init(); - npl_freertos_mempool_init(); -#endif /* Initialize default event queue */ ble_npl_eventq_init(&g_eventq_dflt); @@ -346,62 +346,12 @@ nimble_port_init(void) ble_transport_hs_init(); #if NIMBLE_CFG_CONTROLLER - //ble_hci_ram_init(); +#ifndef RIOT_VERSION hal_timer_init(5, NULL); os_cputime_init(32768); - ble_transport_ll_init(); -#endif - -#if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) - ble_adv_list_init(); #endif -} - -int -nimble_port_stop(void) -{ - int rc = 0; - - rc = ble_npl_sem_init(&ble_hs_stop_sem, 0); - if (rc != 0) { - return rc; - } - - /* Initiate a host stop procedure. */ - rc = ble_hs_stop(&stop_listener, ble_hs_stop_cb, - NULL); - if (rc != 0) { - ble_npl_sem_deinit(&ble_hs_stop_sem); - return rc; - } - - /* Wait till the host stop procedure is complete */ - ble_npl_sem_pend(&ble_hs_stop_sem, BLE_NPL_TIME_FOREVER); - - ble_npl_event_init(&ble_hs_ev_stop, nimble_port_stop_cb, - NULL); - ble_npl_eventq_put(&g_eventq_dflt, &ble_hs_ev_stop); - - /* Wait till the event is serviced */ - ble_npl_sem_pend(&ble_hs_stop_sem, BLE_NPL_TIME_FOREVER); - - ble_npl_sem_deinit(&ble_hs_stop_sem); - - return rc; -} - -void -nimble_port_deinit(void) -{ -#if MYNEWT_VAL(BLE_QUEUE_CONG_CHECK) - ble_adv_list_deinit(); -#endif - ble_npl_eventq_deinit(&g_eventq_dflt); - ble_hs_deinit(); -#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS - npl_freertos_funcs_deinit(); + ble_transport_ll_init(); #endif - } void @@ -430,5 +380,4 @@ nimble_port_ll_task_func(void *arg) ble_ll_task(arg); } #endif - #endif // ESP_PLATFORM diff --git a/src/nimble/porting/nimble/src/os_cputime.c b/src/nimble/porting/nimble/src/os_cputime.c index 5c418c6a..bc8e7a19 100644 --- a/src/nimble/porting/nimble/src/os_cputime.c +++ b/src/nimble/porting/nimble/src/os_cputime.c @@ -20,9 +20,9 @@ #include #include #include -#include "../include/syscfg/syscfg.h" -#include "../include/os/os_cputime.h" -#include "../include/hal/hal_timer.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/os/os_cputime.h" +#include "nimble/porting/nimble/include/hal/hal_timer.h" #if defined(OS_CPUTIME_FREQ_HIGH) struct os_cputime_data g_os_cputime; diff --git a/src/nimble/porting/nimble/src/os_cputime_pwr2.c b/src/nimble/porting/nimble/src/os_cputime_pwr2.c index 73870c4e..9bc229cf 100644 --- a/src/nimble/porting/nimble/src/os_cputime_pwr2.c +++ b/src/nimble/porting/nimble/src/os_cputime_pwr2.c @@ -17,7 +17,7 @@ * under the License. */ -#include "../include/os/os_cputime.h" +#include "nimble/porting/nimble/include/os/os_cputime.h" /** * This module implements cputime functionality for timers for which: diff --git a/src/nimble/porting/nimble/src/os_mbuf.c b/src/nimble/porting/nimble/src/os_mbuf.c index a3236e43..10086230 100644 --- a/src/nimble/porting/nimble/src/os_mbuf.c +++ b/src/nimble/porting/nimble/src/os_mbuf.c @@ -33,8 +33,9 @@ * */ -#include "../include/os/os.h" -#include "../include/os/os_trace_api.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/os/os_trace_api.h" +#include "nimble/porting/nimble/include/modlog/modlog.h" #include #include @@ -59,6 +60,7 @@ STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list = STAILQ_HEAD_INITIALIZER(g_msys_pool_list); +static uint8_t log_count; int os_mqueue_init(struct os_mqueue *mq, ble_npl_event_fn *ev_cb, void *arg) @@ -186,6 +188,11 @@ os_msys_get(uint16_t dsize, uint16_t leadingspace) m = os_mbuf_get(pool, leadingspace); return (m); err: + log_count ++; + if ((log_count % 100) == 0) { + log_count = 0; + } + return (NULL); } @@ -205,6 +212,10 @@ os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len) m = os_mbuf_get_pkthdr(pool, user_hdr_len); return (m); err: + log_count ++; + if ((log_count % 100) == 0) { + log_count = 0; + } return (NULL); } @@ -389,8 +400,6 @@ os_mbuf_len(const struct os_mbuf *om) return len; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpointer-arith" int os_mbuf_append(struct os_mbuf *om, const void *data, uint16_t len) { @@ -464,7 +473,6 @@ os_mbuf_append(struct os_mbuf *om, const void *data, uint16_t len) err: return (rc); } -#pragma GCC diagnostic pop int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src, @@ -674,9 +682,6 @@ os_mbuf_adj(struct os_mbuf *mp, int req_len) } } - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpointer-arith" int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len) { @@ -717,7 +722,6 @@ os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len) } } } -#pragma GCC diagnostic pop int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1, diff --git a/src/nimble/porting/nimble/src/os_mempool.c b/src/nimble/porting/nimble/src/os_mempool.c index 297a6701..9e0af24c 100644 --- a/src/nimble/porting/nimble/src/os_mempool.c +++ b/src/nimble/porting/nimble/src/os_mempool.c @@ -17,13 +17,14 @@ * under the License. */ -#include "../include/os/os.h" -#include "../include/os/os_trace_api.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/os/os_trace_api.h" #include #include #include -#include "../include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/syscfg/syscfg.h" +#include "nimble/porting/nimble/include/modlog/modlog.h" #if !MYNEWT_VAL(OS_SYSVIEW_TRACE_MEMPOOL) #define OS_TRACE_DISABLE_FILE_API #endif diff --git a/src/nimble/porting/nimble/src/os_msys_init.c b/src/nimble/porting/nimble/src/os_msys_init.c index 57e62ed5..bb314873 100644 --- a/src/nimble/porting/nimble/src/os_msys_init.c +++ b/src/nimble/porting/nimble/src/os_msys_init.c @@ -18,12 +18,12 @@ */ #include -#include "../include/os/os.h" -#include "../include/mem/mem.h" -#include "../include/sysinit/sysinit.h" +#include "nimble/porting/nimble/include/os/os.h" +#include "nimble/porting/nimble/include/mem/mem.h" +#include "nimble/porting/nimble/include/sysinit/sysinit.h" -#include "nimble/esp_port/port/include/esp_nimble_mem.h" #ifdef ESP_PLATFORM +#include "nimble/esp_port/port/include/esp_nimble_mem.h" #include "esp_err.h" #endif diff --git a/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h b/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h index d23f474f..c1bc7bb7 100644 --- a/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h +++ b/src/nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h @@ -19,19 +19,18 @@ #ifndef _NIMBLE_NPL_OS_H_ #define _NIMBLE_NPL_OS_H_ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" - -#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS #include #include #include #include "freertos/FreeRTOS.h" -#include "freertos/queue.h" +#include "nimble/porting/nimble/include/os/queue.h" #include "freertos/semphr.h" #include "freertos/task.h" #include "freertos/timers.h" +#if CONFIG_BT_NIMBLE_USE_ESP_TIMER #include "esp_timer.h" +#endif #ifdef __cplusplus extern "C" { @@ -44,13 +43,7 @@ extern "C" { #ifdef ESP_PLATFORM extern int ets_printf(const char *fmt, ...); -#else -#define ets_printf printf -#define IRAM_ATTR -#define NIMBLE_CFG_CONTROLLER 1 -#endif - -#define PLATFORM_BLE_LL_ASSERT(con) \ +#define BLE_LL_ASSERT(con) \ do{ \ if(!(con)) { \ ets_printf("assertion:%s\n",#con); \ @@ -58,6 +51,9 @@ extern int ets_printf(const char *fmt, ...); assert(0); \ } \ }while(0) +#else +#define NIMBLE_CFG_CONTROLLER 1 +#endif // ESP_PLATFORM #define BLE_NPL_OS_ALIGNMENT (4)/*ble_npl_get_os_alignment()*/ @@ -378,14 +374,13 @@ ble_npl_hw_set_isr(int irqn, uint32_t addr) } #else static inline void -IRAM_ATTR ble_npl_hw_set_isr(int irqn, void (*addr)(void)) +ble_npl_hw_set_isr(int irqn, void (*addr)(void)) { return npl_funcs->p_ble_npl_hw_set_isr(irqn, addr); } #endif #endif -//critical section static inline uint32_t ble_npl_hw_enter_critical(void) { @@ -412,353 +407,4 @@ static inline bool ble_npl_hw_is_in_critical(void) } #endif -#else // Not using MEM Pools - -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" -#include "freertos/task.h" -#include "freertos/timers.h" -#ifdef CONFIG_BT_NIMBLE_USE_ESP_TIMER -#include "esp_timer.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define BLE_NPL_OS_ALIGNMENT 4 - -#define BLE_NPL_TIME_FOREVER portMAX_DELAY - -#ifndef ESP_PLATFORM -#define IRAM_ATTR -#define NIMBLE_CFG_CONTROLLER 1 -#define NIMBLE_EVT_QUEUE_SIZE 4 -#else -#define NIMBLE_EVT_QUEUE_SIZE 32 -#endif - -/* This should be compatible with TickType_t */ -typedef uint32_t ble_npl_time_t; -typedef int32_t ble_npl_stime_t; - -struct ble_npl_event { - bool queued; - ble_npl_event_fn *fn; - void *arg; -}; - -struct ble_npl_eventq { - QueueHandle_t q; -}; - -struct ble_npl_callout { -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - esp_timer_handle_t handle; -#else - TimerHandle_t handle; -#endif - struct ble_npl_eventq *evq; - struct ble_npl_event ev; -}; - -struct ble_npl_mutex { - SemaphoreHandle_t handle; -}; - -struct ble_npl_sem { - SemaphoreHandle_t handle; -}; - -/* - * Simple APIs are just defined as static inline below, but some are a bit more - * complex or require some global state variables and thus are defined in .c - * file instead and static inline wrapper just calls proper implementation. - * We need declarations of these functions and they are defined in header below. - */ -#include "npl_freertos.h" - -static inline bool -ble_npl_os_started(void) -{ - return xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED; -} - -static inline void * -ble_npl_get_current_task_id(void) -{ - return xTaskGetCurrentTaskHandle(); -} - -static inline void -ble_npl_eventq_init(struct ble_npl_eventq *evq) -{ - evq->q = xQueueCreate(NIMBLE_EVT_QUEUE_SIZE, sizeof(struct ble_npl_eventq *)); -} - -static inline void -ble_npl_eventq_deinit(struct ble_npl_eventq *evq) -{ - vQueueDelete(evq->q); -} - -static inline struct ble_npl_event * -ble_npl_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) -{ - return npl_freertos_eventq_get(evq, tmo); -} - -static inline void -ble_npl_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) -{ - npl_freertos_eventq_put(evq, ev); -} - -static inline void -ble_npl_eventq_remove(struct ble_npl_eventq *evq, struct ble_npl_event *ev) -{ - npl_freertos_eventq_remove(evq, ev); -} - -static inline void -ble_npl_event_run(struct ble_npl_event *ev) -{ - ev->fn(ev); -} - -static inline bool -ble_npl_eventq_is_empty(struct ble_npl_eventq *evq) -{ - return xQueueIsQueueEmptyFromISR(evq->q); -} - -static inline void -ble_npl_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, - void *arg) -{ - memset(ev, 0, sizeof(*ev)); - ev->fn = fn; - ev->arg = arg; -} - -static inline void -ble_npl_event_deinit(struct ble_npl_event *ev) -{ - -} - -static inline bool -ble_npl_event_is_queued(struct ble_npl_event *ev) -{ - return ev->queued; -} - -static inline void * -ble_npl_event_get_arg(struct ble_npl_event *ev) -{ - return ev->arg; -} - -static inline void -ble_npl_event_set_arg(struct ble_npl_event *ev, void *arg) -{ - ev->arg = arg; -} - -static inline ble_npl_error_t -ble_npl_mutex_init(struct ble_npl_mutex *mu) -{ - return npl_freertos_mutex_init(mu); -} - -static inline ble_npl_error_t -ble_npl_mutex_deinit(struct ble_npl_mutex *mu) -{ - return npl_freertos_mutex_deinit(mu); -} - -static inline ble_npl_error_t -ble_npl_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) -{ - return npl_freertos_mutex_pend(mu, timeout); -} - -static inline ble_npl_error_t -ble_npl_mutex_release(struct ble_npl_mutex *mu) -{ - return npl_freertos_mutex_release(mu); -} - -static inline ble_npl_error_t -ble_npl_sem_init(struct ble_npl_sem *sem, uint16_t tokens) -{ - return npl_freertos_sem_init(sem, tokens); -} - -static inline ble_npl_error_t -ble_npl_sem_deinit(struct ble_npl_sem *sem) -{ - return npl_freertos_sem_deinit(sem); -} - -static inline ble_npl_error_t -ble_npl_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) -{ - return npl_freertos_sem_pend(sem, timeout); -} - -static inline ble_npl_error_t -ble_npl_sem_release(struct ble_npl_sem *sem) -{ - return npl_freertos_sem_release(sem); -} - -static inline uint16_t -ble_npl_sem_get_count(struct ble_npl_sem *sem) -{ - return uxSemaphoreGetCount(sem->handle); -} - -static inline int -ble_npl_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, - ble_npl_event_fn *ev_cb, void *ev_arg) -{ - return npl_freertos_callout_init(co, evq, ev_cb, ev_arg); -} - -static inline void -ble_npl_callout_deinit(struct ble_npl_callout *co) -{ - npl_freertos_callout_deinit(co); -} - -static inline ble_npl_error_t -ble_npl_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) -{ - return npl_freertos_callout_reset(co, ticks); -} - -static inline void -ble_npl_callout_stop(struct ble_npl_callout *co) -{ - npl_freertos_callout_stop(co); -} - -static inline bool -ble_npl_callout_is_active(struct ble_npl_callout *co) -{ - return npl_freertos_callout_is_active(co); -} - -static inline ble_npl_time_t -ble_npl_callout_get_ticks(struct ble_npl_callout *co) -{ - return npl_freertos_callout_get_ticks(co); -} - -static inline uint32_t -ble_npl_callout_remaining_ticks(struct ble_npl_callout *co, - ble_npl_time_t time) -{ - return npl_freertos_callout_remaining_ticks(co, time); -} - -static inline void -ble_npl_callout_set_arg(struct ble_npl_callout *co, void *arg) -{ - co->ev.arg = arg; -} - -static inline uint32_t -ble_npl_time_get(void) -{ - return xTaskGetTickCountFromISR(); -} - -static inline ble_npl_error_t -ble_npl_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) -{ - return npl_freertos_time_ms_to_ticks(ms, out_ticks); -} - -static inline ble_npl_error_t -ble_npl_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms) -{ - return ble_npl_time_ticks_to_ms(ticks, out_ms); -} - -static inline ble_npl_time_t -ble_npl_time_ms_to_ticks32(uint32_t ms) -{ - return ms * configTICK_RATE_HZ / 1000; -} - -static inline uint32_t -ble_npl_time_ticks_to_ms32(ble_npl_time_t ticks) -{ - return ticks * 1000 / configTICK_RATE_HZ; -} - -static inline void -ble_npl_time_delay(ble_npl_time_t ticks) -{ - vTaskDelay(ticks); -} - -#if NIMBLE_CFG_CONTROLLER -static inline void -ble_npl_hw_set_isr(int irqn, void (*addr)(void)) -{ - npl_freertos_hw_set_isr(irqn, addr); -} - -static inline bool -ble_npl_hw_is_in_critical(void) -{ - return (uxGetCriticalNestingDepth() > 0); -} -#endif - -#ifdef ESP_PLATFORM -extern portMUX_TYPE ble_port_mutex; -//critical section -static inline uint32_t -ble_npl_hw_enter_critical(void) -{ - portENTER_CRITICAL(&ble_port_mutex); - return 0; -} - -static inline void -ble_npl_hw_exit_critical(uint32_t ctx) -{ - portEXIT_CRITICAL(&ble_port_mutex); -} - -#else -static inline uint32_t -ble_npl_hw_enter_critical(void) -{ - vPortEnterCritical(); - return 0; -} - -static inline void -ble_npl_hw_exit_critical(uint32_t ctx) -{ - (void)ctx; - vPortExitCritical(); -} -#endif - -#ifdef __cplusplus -} -#endif - -#endif // CONFIG_NIMBLE_STACK_USE_MEM_POOLS - #endif /* _NPL_H_ */ diff --git a/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h b/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h index bc44eb08..00858d71 100644 --- a/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h +++ b/src/nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h @@ -21,11 +21,11 @@ #define _NIMBLE_PORT_FREERTOS_H #include "nimble/nimble/include/nimble/nimble_npl.h" -#include "nimble/porting/nimble/include/syscfg/syscfg.h" #ifdef ESP_PLATFORM #include "esp_err.h" #endif + #ifdef __cplusplus extern "C" { #endif @@ -45,19 +45,14 @@ esp_err_t esp_nimble_enable(void *host_task); * @return esp_err_t */ esp_err_t esp_nimble_disable(void); - -#endif // ESP_PLATFORM +#endif void nimble_port_freertos_init(TaskFunction_t host_task_fn); void nimble_port_freertos_deinit(void); -UBaseType_t nimble_port_freertos_get_hs_hwm(void); - -#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS void npl_freertos_funcs_init(void); void npl_freertos_funcs_deinit(void); int npl_freertos_mempool_init(void); struct npl_funcs_t * npl_freertos_funcs_get(void); -#endif #ifndef ESP_PLATFORM UBaseType_t nimble_port_freertos_get_ll_hwm(void); #endif diff --git a/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h b/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h index 6bbe0845..9baf1fb9 100644 --- a/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h +++ b/src/nimble/porting/npl/freertos/include/nimble/npl_freertos.h @@ -20,13 +20,10 @@ #ifndef _NPL_FREERTOS_H_ #define _NPL_FREERTOS_H_ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" - #ifdef __cplusplus extern "C" { #endif -#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS typedef void ble_npl_event_fn(struct ble_npl_event *ev); struct ble_npl_event_freertos { @@ -58,7 +55,6 @@ struct ble_npl_sem_freertos { }; typedef void ble_npl_event_fn_freertos(struct ble_npl_event_freertos *ev); -#endif struct ble_npl_eventq *npl_freertos_eventq_dflt_get(void); @@ -110,8 +106,11 @@ ble_npl_error_t npl_freertos_time_ms_to_ticks(uint32_t ms, ble_npl_error_t npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms); - +#ifdef ESP_PLATFORM +void npl_freertos_hw_set_isr(int irqn, uint32_t addr); +#else void npl_freertos_hw_set_isr(int irqn, void (*addr)(void)); +#endif uint32_t npl_freertos_hw_enter_critical(void); diff --git a/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c b/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c index 65702349..6d5be4a2 100644 --- a/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c +++ b/src/nimble/porting/npl/freertos/src/nimble_port_freertos.c @@ -21,29 +21,25 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "../../../nimble/include/nimble/nimble_port.h" + +static TaskHandle_t host_task_h = NULL; + +UBaseType_t nimble_port_freertos_get_hs_hwm(void) { + if (!host_task_h) { + return 0; + } + return uxTaskGetStackHighWaterMark(host_task_h); +} + #ifdef ESP_PLATFORM #include "esp_bt.h" -#endif -#ifndef ESP_PLATFORM -#if NIMBLE_CFG_CONTROLLER -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) -#define NIMBLE_LL_STACK_SIZE (130) +#ifdef CONFIG_BT_NIMBLE_HOST_TASK_PRIORITY +# define NIMBLE_HOST_TASK_PRIORITY (CONFIG_BT_NIMBLE_HOST_TASK_PRIORITY) #else -#define NIMBLE_LL_STACK_SIZE (100) -#endif -static StackType_t ll_xStack[ NIMBLE_LL_STACK_SIZE ]; -static StaticTask_t ll_xTaskBuffer; -static TaskHandle_t ll_task_h; -#endif - -static StackType_t hs_xStack[ NIMBLE_HS_STACK_SIZE ]; -static StaticTask_t hs_xTaskBuffer; +# define NIMBLE_HOST_TASK_PRIORITY (configMAX_PRIORITIES - 4) #endif -static TaskHandle_t host_task_h = NULL; - -#ifdef ESP_PLATFORM /** * @brief esp_nimble_enable - Initialize the NimBLE host * @@ -53,12 +49,12 @@ static TaskHandle_t host_task_h = NULL; esp_err_t esp_nimble_enable(void *host_task) { /* - * Create task where NimBLE host will run. It is not strictly necessary to - * have separate task for NimBLE host, but since something needs to handle - * default queue it is just easier to make separate task which does this. - */ + * Create task where NimBLE host will run. It is not strictly necessary to + * have separate task for NimBLE host, but since something needs to handle + * default queue it is just easier to make separate task which does this. + */ xTaskCreatePinnedToCore(host_task, "nimble_host", NIMBLE_HS_STACK_SIZE, - NULL, (configMAX_PRIORITIES - 4), &host_task_h, NIMBLE_CORE); + NULL, NIMBLE_HOST_TASK_PRIORITY, &host_task_h, NIMBLE_CORE); return ESP_OK; } @@ -99,28 +95,60 @@ nimble_port_freertos_deinit(void) esp_nimble_disable(); } -#else // !ESP_PLATFORM +#else // ESP_PLATFORM + +#if NIMBLE_CFG_CONTROLLER +# ifdef CONFIG_BT_NIMBLE_LL_TASK_STACK_SIZE +# define NIMBLE_LL_STACK_SIZE (CONFIG_BT_NIMBLE_LL_TASK_STACK_SIZE / 4) +# else +# if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) +# define NIMBLE_LL_STACK_SIZE (130) +# else +# define NIMBLE_LL_STACK_SIZE (100) +# endif +# endif + +// configMAX_PRIORITIES - 1 is Tmr builtin task +#ifdef CONFIG_BT_NIMBLE_LL_TASK_PRIORITY +# define NIMBLE_LL_TASK_PRIORITY (CONFIG_BT_NIMBLE_LL_TASK_PRIORITY) +#else +# define NIMBLE_LL_TASK_PRIORITY (configMAX_PRIORITIES - 1) +#endif + +static StackType_t ll_stack[ NIMBLE_LL_STACK_SIZE ]; +static StaticTask_t ll_task_buffer; +static TaskHandle_t ll_task_h; +#endif // NIMBLE_CFG_CONTROLLER + +#ifdef CONFIG_BT_NIMBLE_HOST_TASK_PRIORITY +# define NIMBLE_HOST_TASK_PRIORITY (CONFIG_BT_NIMBLE_HOST_TASK_PRIORITY) +#else +# define NIMBLE_HOST_TASK_PRIORITY (configMAX_PRIORITIES - 2) +#endif + +static StackType_t hs_stack[ NIMBLE_HS_STACK_SIZE ]; +static StaticTask_t hs_task_buffer; void nimble_port_freertos_init(TaskFunction_t host_task_fn) { #if NIMBLE_CFG_CONTROLLER /* - * Create task where NimBLE LL will run. This one is required as LL has its - * own event queue and should have highest priority. The task function is - * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped - * since it has compatible prototype. - */ + * Create task where NimBLE LL will run. This one is required as LL has its + * own event queue and should have highest priority. The task function is + * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped + * since it has compatible prototype. + */ ll_task_h = xTaskCreateStatic(nimble_port_ll_task_func, "ll", NIMBLE_LL_STACK_SIZE, - NULL, configMAX_PRIORITIES, ll_xStack, &ll_xTaskBuffer); + NULL, NIMBLE_LL_TASK_PRIORITY, ll_stack, &ll_task_buffer); #endif /* - * Create task where NimBLE host will run. It is not strictly necessary to - * have separate task for NimBLE host, but since something needs to handle - * default queue it is just easier to make separate task which does this. - */ - host_task_h = xTaskCreateStatic(host_task_fn, "ble", NIMBLE_HS_STACK_SIZE, - NULL, (configMAX_PRIORITIES - 1), hs_xStack, &hs_xTaskBuffer); + * Create task where NimBLE host will run. It is not strictly necessary to + * have separate task for NimBLE host, but since something needs to handle + * default queue it is just easier to make separate task which does this. + */ + host_task_h = xTaskCreateStatic(host_task_fn, "host", NIMBLE_HS_STACK_SIZE, + NULL, NIMBLE_HOST_TASK_PRIORITY, hs_stack, &hs_task_buffer); } void @@ -135,16 +163,11 @@ nimble_port_freertos_deinit(void) UBaseType_t nimble_port_freertos_get_ll_hwm(void) { - if (ll_task_h == NULL) + if (!ll_task_h) { return 0; + } return uxTaskGetStackHighWaterMark(ll_task_h); } #endif -#endif // !ESP_PLATFORM -UBaseType_t -nimble_port_freertos_get_hs_hwm(void) { - if (host_task_h == NULL) - return 0; - return uxTaskGetStackHighWaterMark(host_task_h); -} +#endif // ESP_PLATFORM diff --git a/src/nimble/porting/npl/freertos/src/npl_os_freertos.c b/src/nimble/porting/npl/freertos/src/npl_os_freertos.c index 4d96f0ac..2b715262 100644 --- a/src/nimble/porting/npl/freertos/src/npl_os_freertos.c +++ b/src/nimble/porting/npl/freertos/src/npl_os_freertos.c @@ -17,28 +17,29 @@ * under the License. */ -#include "nimble/porting/nimble/include/syscfg/syscfg.h" - -#if CONFIG_NIMBLE_STACK_USE_MEM_POOLS - #include #include #include #include +#include "nimble/porting/nimble/include/syscfg/syscfg.h" #include "nimble/console/console.h" #include "nimble/nimble/include/nimble/nimble_npl.h" #include "freertos/FreeRTOS.h" -#include "freertos/queue.h" +#include "nimble/porting/nimble/include/os/queue.h" #include "freertos/semphr.h" #include "freertos/task.h" #include "freertos/timers.h" #include "freertos/portable.h" -#include "../include/nimble/npl_freertos.h" +#include "nimble/porting/npl/freertos/include/nimble/npl_freertos.h" #include "nimble/porting/nimble/include/os/os_mempool.h" +#if NIMBLE_CFG_CONTROLLER +#include "nimble/nimble/controller/include/controller/ble_ll.h" +#endif + #ifdef ESP_PLATFORM #include "esp_log.h" @@ -58,7 +59,13 @@ static void *rtc0_isr_addr; static const char *LOG_TAG = "Timer"; #endif -#define OS_MEM_ALLOC (1) +#ifdef CONFIG_NIMBLE_STACK_USE_MEM_POOLS +#define OS_MEM_ALLOC (CONFIG_NIMBLE_STACK_USE_MEM_POOLS) +#else +#define OS_MEM_ALLOC (0) +#endif + +#if OS_MEM_ALLOC #if CONFIG_BT_NIMBLE_ENABLED #define BT_LE_HCI_EVT_HI_BUF_COUNT MYNEWT_VAL(BLE_TRANSPORT_EVT_COUNT) @@ -164,6 +171,20 @@ static os_membuf_t ble_freertos_mutex_buf[ OS_MEMPOOL_SIZE(BLE_TOTAL_MUTEX_COUNT, sizeof (struct ble_npl_mutex_freertos)) ]; +#endif +#else + +#ifndef CONFIG_BT_NIMBLE_LL_EVENT_QUEUE_SIZE +#define CONFIG_BT_NIMBLE_LL_EVENT_QUEUE_SIZE (5) +#endif + +#ifndef CONFIG_BT_NIMBLE_DEFAULT_EVENT_QUEUE_SIZE +#define CONFIG_BT_NIMBLE_DEFAULT_EVENT_QUEUE_SIZE (10) +#endif + +#define NIMBLE_LL_QUEUE_SIZE CONFIG_BT_NIMBLE_LL_EVENT_QUEUE_SIZE +#define NIMBLE_DEFAULT_QUEUE_SIZE CONFIG_BT_NIMBLE_DEFAULT_EVENT_QUEUE_SIZE + #endif bool @@ -193,7 +214,7 @@ npl_freertos_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, } #endif event = (struct ble_npl_event_freertos *)ev->event; - PLATFORM_BLE_LL_ASSERT(event); + BLE_LL_ASSERT(event); memset(event, 0, sizeof(*event)); event->fn = fn; @@ -203,7 +224,7 @@ npl_freertos_event_init(struct ble_npl_event *ev, ble_npl_event_fn *fn, void npl_freertos_event_deinit(struct ble_npl_event *ev) { - PLATFORM_BLE_LL_ASSERT(ev->event); + BLE_LL_ASSERT(ev->event); #if OS_MEM_ALLOC os_memblock_put(&ble_freertos_ev_pool,ev->event); #else @@ -216,7 +237,7 @@ void npl_freertos_event_reset(struct ble_npl_event *ev) { struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event; - PLATFORM_BLE_LL_ASSERT(event); + BLE_LL_ASSERT(event); event->queued = 0; } @@ -228,21 +249,28 @@ npl_freertos_eventq_init(struct ble_npl_eventq *evq) if (!os_memblock_from(&ble_freertos_evq_pool,evq->eventq)) { evq->eventq = os_memblock_get(&ble_freertos_evq_pool); eventq = (struct ble_npl_eventq_freertos*)evq->eventq; - PLATFORM_BLE_LL_ASSERT(eventq); + BLE_LL_ASSERT(eventq); memset(eventq, 0, sizeof(*eventq)); eventq->q = xQueueCreate(BLE_TOTAL_EV_COUNT, sizeof(struct ble_npl_eventq *)); - PLATFORM_BLE_LL_ASSERT(eventq->q); + BLE_LL_ASSERT(eventq->q); } #else if(!evq->eventq) { evq->eventq = malloc(sizeof(struct ble_npl_eventq_freertos)); eventq = (struct ble_npl_eventq_freertos*)evq->eventq; - PLATFORM_BLE_LL_ASSERT(eventq); + BLE_LL_ASSERT(eventq); memset(eventq, 0, sizeof(*eventq)); - eventq->q = xQueueCreate(BLE_TOTAL_EV_COUNT, sizeof(struct ble_npl_eventq *)); - PLATFORM_BLE_LL_ASSERT(eventq->q); +#if NIMBLE_CFG_CONTROLLER + eventq->q = xQueueCreate(evq == &g_ble_ll_data.ll_evq ? + NIMBLE_LL_QUEUE_SIZE : + NIMBLE_DEFAULT_QUEUE_SIZE, + sizeof(struct ble_npl_eventq *)); +#else + eventq->q = xQueueCreate(NIMBLE_DEFAULT_QUEUE_SIZE , sizeof(struct ble_npl_eventq *)); +#endif + BLE_LL_ASSERT(eventq->q); } #endif } @@ -252,7 +280,7 @@ npl_freertos_eventq_deinit(struct ble_npl_eventq *evq) { struct ble_npl_eventq_freertos *eventq = (struct ble_npl_eventq_freertos *)evq->eventq; - PLATFORM_BLE_LL_ASSERT(eventq); + BLE_LL_ASSERT(eventq); vQueueDelete(eventq->q); #if OS_MEM_ALLOC os_memblock_put(&ble_freertos_evq_pool,eventq); @@ -267,8 +295,8 @@ npl_freertos_callout_mem_reset(struct ble_npl_callout *co) { struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)co->co; - PLATFORM_BLE_LL_ASSERT(callout); - PLATFORM_BLE_LL_ASSERT(callout->handle); + BLE_LL_ASSERT(callout); + BLE_LL_ASSERT(callout->handle); ble_npl_event_reset(&callout->ev); } @@ -334,7 +362,7 @@ npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) BaseType_t ret; if (in_isr()) { - PLATFORM_BLE_LL_ASSERT(tmo == 0); + BLE_LL_ASSERT(tmo == 0); ret = xQueueReceiveFromISR(eventq->q, &ev, &woken); #ifdef ESP_PLATFORM @@ -347,7 +375,7 @@ npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) } else { ret = xQueueReceive(eventq->q, &ev, tmo); } - PLATFORM_BLE_LL_ASSERT(ret == pdPASS || ret == errQUEUE_EMPTY); + BLE_LL_ASSERT(ret == pdPASS || ret == errQUEUE_EMPTY); if (ev) { struct ble_npl_event_freertos *event = (struct ble_npl_event_freertos *)ev->event; @@ -386,7 +414,7 @@ npl_freertos_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) ret = xQueueSendToBack(eventq->q, &ev, portMAX_DELAY); } - PLATFORM_BLE_LL_ASSERT(ret == pdPASS); + BLE_LL_ASSERT(ret == pdPASS); } void @@ -418,7 +446,7 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, count = uxQueueMessagesWaitingFromISR(eventq->q); for (i = 0; i < count; i++) { ret = xQueueReceiveFromISR(eventq->q, &tmp_ev, &woken2); - PLATFORM_BLE_LL_ASSERT(ret == pdPASS); + BLE_LL_ASSERT(ret == pdPASS); woken |= woken2; if (tmp_ev == ev) { @@ -426,7 +454,7 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, } ret = xQueueSendToBackFromISR(eventq->q, &tmp_ev, &woken2); - PLATFORM_BLE_LL_ASSERT(ret == pdPASS); + BLE_LL_ASSERT(ret == pdPASS); woken |= woken2; } @@ -449,14 +477,14 @@ npl_freertos_eventq_remove(struct ble_npl_eventq *evq, #endif for (i = 0; i < count; i++) { ret = xQueueReceive(eventq->q, &tmp_ev, 0); - PLATFORM_BLE_LL_ASSERT(ret == pdPASS); + BLE_LL_ASSERT(ret == pdPASS); if (tmp_ev == ev) { continue; } ret = xQueueSendToBack(eventq->q, &tmp_ev, 0); - PLATFORM_BLE_LL_ASSERT(ret == pdPASS); + BLE_LL_ASSERT(ret == pdPASS); } #ifdef ESP_PLATFORM portEXIT_CRITICAL(&ble_npl_mut); @@ -483,7 +511,7 @@ npl_freertos_mutex_init(struct ble_npl_mutex *mu) memset(mutex, 0, sizeof(*mutex)); mutex->handle = xSemaphoreCreateRecursiveMutex(); - PLATFORM_BLE_LL_ASSERT(mutex->handle); + BLE_LL_ASSERT(mutex->handle); } #else if(!mu->mutex) { @@ -496,7 +524,7 @@ npl_freertos_mutex_init(struct ble_npl_mutex *mu) memset(mutex, 0, sizeof(*mutex)); mutex->handle = xSemaphoreCreateRecursiveMutex(); - PLATFORM_BLE_LL_ASSERT(mutex->handle); + BLE_LL_ASSERT(mutex->handle); } #endif @@ -512,7 +540,7 @@ npl_freertos_mutex_deinit(struct ble_npl_mutex *mu) return BLE_NPL_INVALID_PARAM; } - PLATFORM_BLE_LL_ASSERT(mutex->handle); + BLE_LL_ASSERT(mutex->handle); vSemaphoreDelete(mutex->handle); #if OS_MEM_ALLOC @@ -581,11 +609,11 @@ npl_freertos_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) return BLE_NPL_INVALID_PARAM; } - PLATFORM_BLE_LL_ASSERT(mutex->handle); + BLE_LL_ASSERT(mutex->handle); if (in_isr()) { ret = pdFAIL; - PLATFORM_BLE_LL_ASSERT(0); + BLE_LL_ASSERT(0); } else { ret = xSemaphoreTakeRecursive(mutex->handle, timeout); } @@ -602,10 +630,10 @@ npl_freertos_mutex_release(struct ble_npl_mutex *mu) return BLE_NPL_INVALID_PARAM; } - PLATFORM_BLE_LL_ASSERT(mutex->handle); + BLE_LL_ASSERT(mutex->handle); if (in_isr()) { - PLATFORM_BLE_LL_ASSERT(0); + BLE_LL_ASSERT(0); } else { if (xSemaphoreGiveRecursive(mutex->handle) != pdPASS) { return BLE_NPL_BAD_MUTEX; @@ -630,7 +658,7 @@ npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens) memset(semaphor, 0, sizeof(*semaphor)); semaphor->handle = xSemaphoreCreateCounting(128, tokens); - PLATFORM_BLE_LL_ASSERT(semaphor->handle); + BLE_LL_ASSERT(semaphor->handle); } #else if(!sem->sem) { @@ -643,7 +671,7 @@ npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens) memset(semaphor, 0, sizeof(*semaphor)); semaphor->handle = xSemaphoreCreateCounting(128, tokens); - PLATFORM_BLE_LL_ASSERT(semaphor->handle); + BLE_LL_ASSERT(semaphor->handle); } #endif @@ -659,7 +687,7 @@ npl_freertos_sem_deinit(struct ble_npl_sem *sem) return BLE_NPL_INVALID_PARAM; } - PLATFORM_BLE_LL_ASSERT(semaphor->handle); + BLE_LL_ASSERT(semaphor->handle); vSemaphoreDelete(semaphor->handle); #if OS_MEM_ALLOC @@ -683,10 +711,10 @@ npl_freertos_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) return BLE_NPL_INVALID_PARAM; } - PLATFORM_BLE_LL_ASSERT(semaphor->handle); + BLE_LL_ASSERT(semaphor->handle); if (in_isr()) { - PLATFORM_BLE_LL_ASSERT(timeout == 0); + BLE_LL_ASSERT(timeout == 0); ret = xSemaphoreTakeFromISR(semaphor->handle, &woken); #ifdef ESP_PLATFORM if( woken == pdTRUE ) { @@ -713,7 +741,7 @@ npl_freertos_sem_release(struct ble_npl_sem *sem) return BLE_NPL_INVALID_PARAM; } - PLATFORM_BLE_LL_ASSERT(semaphor->handle); + BLE_LL_ASSERT(semaphor->handle); if (in_isr()) { ret = xSemaphoreGiveFromISR(semaphor->handle, &woken); @@ -728,7 +756,7 @@ npl_freertos_sem_release(struct ble_npl_sem *sem) ret = xSemaphoreGive(semaphor->handle); } - PLATFORM_BLE_LL_ASSERT(ret == pdPASS); + BLE_LL_ASSERT(ret == pdPASS); return BLE_NPL_OK; } @@ -737,7 +765,7 @@ static void ble_npl_event_fn_wrapper(void *arg) { struct ble_npl_callout_freertos *callout = (struct ble_npl_callout_freertos *)arg; - PLATFORM_BLE_LL_ASSERT(callout); + BLE_LL_ASSERT(callout); if (callout->evq) { ble_npl_eventq_put(callout->evq, &callout->ev); @@ -772,7 +800,7 @@ os_callout_timer_cb(TimerHandle_t timer) struct ble_npl_callout_freertos *callout; callout = pvTimerGetTimerID(timer); - PLATFORM_BLE_LL_ASSERT(callout); + BLE_LL_ASSERT(callout); if (callout->evq) { ble_npl_eventq_put(callout->evq, &callout->ev); @@ -793,19 +821,19 @@ npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq if (!os_memblock_from(&ble_freertos_co_pool, co->co)) { co->co = os_memblock_get(&ble_freertos_co_pool); callout = (struct ble_npl_callout_freertos *)co->co; - PLATFORM_BLE_LL_ASSERT(callout); + BLE_LL_ASSERT(callout); memset(callout, 0, sizeof(*callout)); ble_npl_event_init(&callout->ev, ev_cb, ev_arg); #if CONFIG_BT_NIMBLE_USE_ESP_TIMER - callout->evq = evq; + callout->evq = evq; - esp_timer_create_args_t create_args = { - .callback = ble_npl_event_fn_wrapper, - .arg = callout, - .name = "nimble_timer" - }; + esp_timer_create_args_t create_args = { + .callback = ble_npl_event_fn_wrapper, + .arg = callout, + .name = "nimble_timer" + }; if (esp_timer_create(&create_args, &callout->handle) != ESP_OK) { ble_npl_event_deinit(&callout->ev); @@ -813,8 +841,9 @@ npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq co->co = NULL; return -1; } + #else - callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb); + callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb); if (!callout->handle) { ble_npl_event_deinit(&callout->ev); @@ -822,13 +851,14 @@ npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq co->co = NULL; return -1; } + #endif } else { - callout = (struct ble_npl_callout_freertos *)co->co; - PLATFORM_BLE_LL_ASSERT(callout); - callout->evq = evq; - ble_npl_event_init(&callout->ev, ev_cb, ev_arg); + callout = (struct ble_npl_callout_freertos *)co->co; + BLE_LL_ASSERT(callout); + callout->evq = evq; + ble_npl_event_init(&callout->ev, ev_cb, ev_arg); } #else @@ -839,7 +869,7 @@ npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq return -1; } - memset(callout, 0, sizeof(*callout)); + memset(callout, 0, sizeof(*callout)); ble_npl_event_init(&callout->ev, ev_cb, ev_arg); #if CONFIG_BT_NIMBLE_USE_ESP_TIMER @@ -858,7 +888,7 @@ npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq return -1; } #else - callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb); + callout->handle = xTimerCreate("co", 1, pdFALSE, callout, os_callout_timer_cb); if (!callout->handle) { ble_npl_event_deinit(&callout->ev); @@ -870,9 +900,9 @@ npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq } else { callout = (struct ble_npl_callout_freertos *)co->co; - PLATFORM_BLE_LL_ASSERT(callout); - callout->evq = evq; - ble_npl_event_init(&callout->ev, ev_cb, ev_arg); + BLE_LL_ASSERT(callout); + callout->evq = evq; + ble_npl_event_init(&callout->ev, ev_cb, ev_arg); } #endif return 0; @@ -888,7 +918,7 @@ npl_freertos_callout_deinit(struct ble_npl_callout *co) return; } - PLATFORM_BLE_LL_ASSERT(callout->handle); + BLE_LL_ASSERT(callout->handle); ble_npl_event_deinit(&callout->ev); #if CONFIG_BT_NIMBLE_USE_ESP_TIMER if(esp_timer_stop(callout->handle)) @@ -1248,6 +1278,7 @@ void npl_freertos_funcs_init(void) int npl_freertos_mempool_init(void) { +#if OS_MEM_ALLOC int rc = -1; #if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED @@ -1334,14 +1365,16 @@ int npl_freertos_mempool_init(void) return -1; #else - PLATFORM_BLE_LL_ASSERT(rc == 0); + BLE_LL_ASSERT(rc == 0); return rc; #endif +#endif // OS_MEM_ALLOC +return 0; } void npl_freertos_mempool_deinit(void) { -#if SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED +#if OS_MEM_ALLOC && SOC_ESP_NIMBLE_CONTROLLER && CONFIG_BT_CONTROLLER_ENABLED if(ble_freertos_ev_buf) { free(ble_freertos_ev_buf); ble_freertos_ev_buf = NULL; @@ -1372,613 +1405,3 @@ void npl_freertos_funcs_deinit(void) } npl_funcs = NULL; } - -#else // Not using MEM pools - -#include -#include -#include - -#include "nimble/nimble/include/nimble/nimble_npl.h" - -#ifdef ESP_PLATFORM -#include "freertos/portable.h" -#include "esp_log.h" -portMUX_TYPE ble_port_mutex = portMUX_INITIALIZER_UNLOCKED; -# if CONFIG_BT_NIMBLE_USE_ESP_TIMER -static const char *LOG_TAG = "Timer"; -# endif - -#else -#include "nrf.h" -static void *radio_isr_addr; -static void *rng_isr_addr; -static void *rtc0_isr_addr; -#endif - -#ifdef ESP_PLATFORM -static inline bool -in_isr(void) -{ - /* XXX hw specific! */ - return xPortInIsrContext() != 0; -} - -#else -static inline bool -in_isr(void) -{ - /* XXX hw specific! */ - return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0; -} - -void -RADIO_IRQHandler(void) -{ - ((void (*)(void))radio_isr_addr)(); -} - -void -RNG_IRQHandler(void) -{ - ((void (*)(void))rng_isr_addr)(); -} - -void -RTC0_IRQHandler(void) -{ - ((void (*)(void))rtc0_isr_addr)(); -} - -/* This is called by NimBLE radio driver to set interrupt handlers */ -void -npl_freertos_hw_set_isr(int irqn, void (*addr)(void)) -{ - switch (irqn) { - case RADIO_IRQn: - radio_isr_addr = addr; - break; - case RNG_IRQn: - rng_isr_addr = addr; - break; - case RTC0_IRQn: - rtc0_isr_addr = addr; - break; - } -} -#endif - -struct ble_npl_event * -npl_freertos_eventq_get(struct ble_npl_eventq *evq, ble_npl_time_t tmo) -{ - struct ble_npl_event *ev = NULL; - BaseType_t woken; - BaseType_t ret; - - if (in_isr()) { - assert(tmo == 0); - ret = xQueueReceiveFromISR(evq->q, &ev, &woken); -#ifdef ESP_PLATFORM - if( woken == pdTRUE ) { - portYIELD_FROM_ISR(); - } -#else - portYIELD_FROM_ISR(woken); -#endif - } else { - ret = xQueueReceive(evq->q, &ev, tmo); - } - assert(ret == pdPASS || ret == errQUEUE_EMPTY); - - if (ev) { - ev->queued = false; - } - - return ev; -} - -void -npl_freertos_eventq_put(struct ble_npl_eventq *evq, struct ble_npl_event *ev) -{ - BaseType_t woken; - BaseType_t ret; - - if (ev->queued) { - return; - } - - ev->queued = true; - - if (in_isr()) { - ret = xQueueSendToBackFromISR(evq->q, &ev, &woken); -#ifdef ESP_PLATFORM - if( woken == pdTRUE ) { - portYIELD_FROM_ISR(); - } -#else - portYIELD_FROM_ISR(woken); -#endif - } else { - ret = xQueueSendToBack(evq->q, &ev, portMAX_DELAY); - } - - assert(ret == pdPASS); -} - -void -npl_freertos_eventq_remove(struct ble_npl_eventq *evq, - struct ble_npl_event *ev) -{ - struct ble_npl_event *tmp_ev; - BaseType_t ret; - int i; - int count; - BaseType_t woken, woken2; - - if (!ev->queued) { - return; - } - - /* - * XXX We cannot extract element from inside FreeRTOS queue so as a quick - * workaround we'll just remove all elements and add them back except the - * one we need to remove. This is silly, but works for now - we probably - * better use counting semaphore with os_queue to handle this in future. - */ - - if (in_isr()) { - woken = pdFALSE; - - count = uxQueueMessagesWaitingFromISR(evq->q); - for (i = 0; i < count; i++) { - ret = xQueueReceiveFromISR(evq->q, &tmp_ev, &woken2); - assert(ret == pdPASS); - woken |= woken2; - - if (tmp_ev == ev) { - continue; - } - - ret = xQueueSendToBackFromISR(evq->q, &tmp_ev, &woken2); - assert(ret == pdPASS); - woken |= woken2; - } - -#ifdef ESP_PLATFORM - if( woken == pdTRUE ) { - portYIELD_FROM_ISR(); - } -#else - portYIELD_FROM_ISR(woken); -#endif - } else { -#ifdef ESP_PLATFORM - portMUX_TYPE ble_npl_mut = portMUX_INITIALIZER_UNLOCKED; - portENTER_CRITICAL(&ble_npl_mut); -#else - vPortEnterCritical(); -#endif - count = uxQueueMessagesWaiting(evq->q); - for (i = 0; i < count; i++) { - ret = xQueueReceive(evq->q, &tmp_ev, 0); - assert(ret == pdPASS); - - if (tmp_ev == ev) { - continue; - } - - ret = xQueueSendToBack(evq->q, &tmp_ev, 0); - assert(ret == pdPASS); - } -#ifdef ESP_PLATFORM - portEXIT_CRITICAL(&ble_npl_mut); -#else - vPortExitCritical(); -#endif - } - - ev->queued = 0; -} - -ble_npl_error_t -npl_freertos_mutex_init(struct ble_npl_mutex *mu) -{ - if (!mu) { - return BLE_NPL_INVALID_PARAM; - } - - mu->handle = xSemaphoreCreateRecursiveMutex(); - assert(mu->handle); - - return BLE_NPL_OK; -} - -ble_npl_error_t -npl_freertos_mutex_deinit(struct ble_npl_mutex *mu) -{ - if (!mu) { - return BLE_NPL_INVALID_PARAM; - } - - if (mu->handle) { - vSemaphoreDelete(mu->handle); - } - - return BLE_NPL_OK; -} - -ble_npl_error_t -npl_freertos_mutex_pend(struct ble_npl_mutex *mu, ble_npl_time_t timeout) -{ - BaseType_t ret; - - if (!mu) { - return BLE_NPL_INVALID_PARAM; - } - - assert(mu->handle); - - if (in_isr()) { - ret = pdFAIL; - assert(0); - } else { - ret = xSemaphoreTakeRecursive(mu->handle, timeout); - } - - return ret == pdPASS ? BLE_NPL_OK : BLE_NPL_TIMEOUT; -} - -ble_npl_error_t -npl_freertos_mutex_release(struct ble_npl_mutex *mu) -{ - if (!mu) { - return BLE_NPL_INVALID_PARAM; - } - - assert(mu->handle); - - if (in_isr()) { - assert(0); - } else { - if (xSemaphoreGiveRecursive(mu->handle) != pdPASS) { - return BLE_NPL_BAD_MUTEX; - } - } - - return BLE_NPL_OK; -} - -ble_npl_error_t -npl_freertos_sem_init(struct ble_npl_sem *sem, uint16_t tokens) -{ - if (!sem) { - return BLE_NPL_INVALID_PARAM; - } - - sem->handle = xSemaphoreCreateCounting(128, tokens); - assert(sem->handle); - - return BLE_NPL_OK; -} - -ble_npl_error_t -npl_freertos_sem_deinit(struct ble_npl_sem *sem) -{ - if (!sem) { - return BLE_NPL_INVALID_PARAM; - } - - if (sem->handle) { - vSemaphoreDelete(sem->handle); - } - - return BLE_NPL_OK; -} - -ble_npl_error_t -npl_freertos_sem_pend(struct ble_npl_sem *sem, ble_npl_time_t timeout) -{ - BaseType_t woken; - BaseType_t ret; - - if (!sem) { - return BLE_NPL_INVALID_PARAM; - } - - assert(sem->handle); - - if (in_isr()) { - assert(timeout == 0); - ret = xSemaphoreTakeFromISR(sem->handle, &woken); -#ifdef ESP_PLATFORM - if( woken == pdTRUE ) { - portYIELD_FROM_ISR(); - } -#else - portYIELD_FROM_ISR(woken); -#endif - } else { - ret = xSemaphoreTake(sem->handle, timeout); - } - - return ret == pdPASS ? BLE_NPL_OK : BLE_NPL_TIMEOUT; -} - -ble_npl_error_t -npl_freertos_sem_release(struct ble_npl_sem *sem) -{ - BaseType_t ret; - BaseType_t woken; - - if (!sem) { - return BLE_NPL_INVALID_PARAM; - } - - assert(sem->handle); - - if (in_isr()) { - ret = xSemaphoreGiveFromISR(sem->handle, &woken); -#ifdef ESP_PLATFORM - if( woken == pdTRUE ) { - portYIELD_FROM_ISR(); - } -#else - portYIELD_FROM_ISR(woken); -#endif - } else { - ret = xSemaphoreGive(sem->handle); - } - - assert(ret == pdPASS); - return BLE_NPL_OK; -} - - -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER -static void -ble_npl_event_fn_wrapper(void *arg) -{ - struct ble_npl_callout *co = (struct ble_npl_callout *)arg; - - if (co->evq) { - ble_npl_eventq_put(co->evq, &co->ev); - } else { - co->ev.fn(&co->ev); - } -} - -static -ble_npl_error_t esp_err_to_npl_error(esp_err_t err) -{ - switch(err) { - case ESP_ERR_INVALID_ARG: - return BLE_NPL_INVALID_PARAM; - - case ESP_ERR_INVALID_STATE: - return BLE_NPL_EINVAL; - - case ESP_OK: - return BLE_NPL_OK; - - default: - return BLE_NPL_ERROR; - } -} -#else -static void -os_callout_timer_cb(TimerHandle_t timer) -{ - struct ble_npl_callout *co; - - co = pvTimerGetTimerID(timer); - assert(co); - - if (co->evq) { - ble_npl_eventq_put(co->evq, &co->ev); - } else { - co->ev.fn(&co->ev); - } -} -#endif - -int -npl_freertos_callout_init(struct ble_npl_callout *co, struct ble_npl_eventq *evq, - ble_npl_event_fn *ev_cb, void *ev_arg) -{ -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - co->ev.fn = ev_cb; - co->ev.arg = ev_arg; - co->evq = evq; - - esp_timer_create_args_t create_args = { - .callback = ble_npl_event_fn_wrapper, - .arg = co, - .name = "nimble_timer" - }; - - ESP_ERROR_CHECK(esp_timer_create(&create_args, &co->handle)); -#else - if (co->handle == NULL) { - co->handle = xTimerCreate("co", 1, pdFALSE, co, os_callout_timer_cb); - if (co->handle == NULL) { - return -1; - } - } - - co->evq = evq; - ble_npl_event_init(&co->ev, ev_cb, ev_arg); -#endif - return 0; -} - -void -npl_freertos_callout_deinit(struct ble_npl_callout *co) -{ - if (!co->handle) { - return; - } - -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - if(esp_timer_stop(co->handle)) - ESP_LOGW(LOG_TAG, "Timer not stopped"); - - if(esp_timer_delete(co->handle)) - ESP_LOGW(LOG_TAG, "Timer not deleted"); -#else - xTimerDelete(co->handle, portMAX_DELAY); - ble_npl_event_deinit(&co->ev); -#endif - memset(co, 0, sizeof(struct ble_npl_callout)); -} - -ble_npl_error_t -npl_freertos_callout_reset(struct ble_npl_callout *co, ble_npl_time_t ticks) -{ -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - esp_timer_stop(co->handle); - - return esp_err_to_npl_error(esp_timer_start_once(co->handle, ticks*1000)); -#else - - BaseType_t woken1, woken2, woken3; - - if (ticks == 0) { - ticks = 1; - } - - if (in_isr()) { - xTimerStopFromISR(co->handle, &woken1); - xTimerChangePeriodFromISR(co->handle, ticks, &woken2); - xTimerResetFromISR(co->handle, &woken3); -#ifdef ESP_PLATFORM - if( woken1 == pdTRUE || woken2 == pdTRUE || woken3 == pdTRUE) { - portYIELD_FROM_ISR(); - } -#else - portYIELD_FROM_ISR(woken1 || woken2 || woken3); -#endif - } else { - xTimerStop(co->handle, portMAX_DELAY); - xTimerChangePeriod(co->handle, ticks, portMAX_DELAY); - xTimerReset(co->handle, portMAX_DELAY); - } - - return BLE_NPL_OK; -#endif -} - -void -npl_freertos_callout_stop(struct ble_npl_callout *co) -{ - if (!co->handle) { - return; - } -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - esp_timer_stop(co->handle); -#else - xTimerStop(co->handle, portMAX_DELAY); -#endif -} - -bool -npl_freertos_callout_is_active(struct ble_npl_callout *co) -{ -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - return esp_timer_is_active(co->handle); -#else - /* Workaround for bug in xTimerIsTimerActive with FreeRTOS V10.2.0, fixed in V10.4.4 - * See: https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/305 - * Sometimes xTimerIsTimerActive returns pdTRUE even though the timer has expired, so we double check. - */ - return xTimerIsTimerActive(co->handle) == pdTRUE && xTimerGetExpiryTime(co->handle) > xTaskGetTickCountFromISR(); -#endif -} - -ble_npl_time_t -npl_freertos_callout_get_ticks(struct ble_npl_callout *co) -{ -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER - /* Currently, esp_timer does not support an API which gets the expiry time for - * current timer. - * Returning 0 from here should not cause any effect. - * Drawback of this approach is that existing code to reset timer would be called - * more often (since the if condition to invoke reset timer would always succeed if - * timer is active). - */ - - return 0; -#else - return xTimerGetExpiryTime(co->handle); -#endif -} - -ble_npl_time_t -npl_freertos_callout_remaining_ticks(struct ble_npl_callout *co, - ble_npl_time_t now) -{ - ble_npl_time_t rt; - uint32_t exp = 0; - -#if CONFIG_BT_NIMBLE_USE_ESP_TIMER -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) - uint64_t expiry = 0; - esp_err_t err; - - //Fetch expiry time in microseconds - err = esp_timer_get_expiry_time((esp_timer_handle_t)(co->handle), &expiry); - if (err != ESP_OK) { - //Error. Could not fetch the expiry time - return 0; - } - - //Convert microseconds to ticks - npl_freertos_time_ms_to_ticks((uint32_t)(expiry / 1000), &exp); -#else - //esp_timer_get_expiry_time() is only available from IDF 5.0 onwards - //Set expiry to 0 - exp = 0; -#endif //ESP_IDF_VERSION -#else - exp = xTimerGetExpiryTime(co->handle); -#endif - - if (exp > now) { - rt = exp - now; - } else { - rt = 0; - } - - return rt; -} - -ble_npl_error_t -npl_freertos_time_ms_to_ticks(uint32_t ms, ble_npl_time_t *out_ticks) -{ - uint64_t ticks; - - ticks = ((uint64_t)ms * configTICK_RATE_HZ) / 1000; - if (ticks > UINT32_MAX) { - return BLE_NPL_EINVAL; - } - - *out_ticks = ticks; - - return 0; -} - -ble_npl_error_t -npl_freertos_time_ticks_to_ms(ble_npl_time_t ticks, uint32_t *out_ms) -{ - uint64_t ms; - - ms = ((uint64_t)ticks * 1000) / configTICK_RATE_HZ; - if (ms > UINT32_MAX) { - return BLE_NPL_EINVAL; - } - - *out_ms = ms; - - return 0; -} - -#endif // CONFIG_NIMBLE_STACK_USE_MEM_POOLS diff --git a/src/nimconfig.h b/src/nimconfig.h index f89e6a9a..3a847c22 100644 --- a/src/nimconfig.h +++ b/src/nimconfig.h @@ -4,6 +4,11 @@ #include "sdkconfig.h" #else #include "ext_nimble_config.h" +/* Clear redefinition warnings */ +#undef CONFIG_BT_NIMBLE_ROLE_CENTRAL +#undef CONFIG_BT_NIMBLE_ROLE_PERIPHERAL +#undef CONFIG_BT_NIMBLE_ROLE_BROADCASTER +#undef CONFIG_BT_NIMBLE_ROLE_OBSERVER #endif #include "nimconfig_rename.h" @@ -177,19 +182,19 @@ /* This section should not be altered */ #ifndef CONFIG_BT_NIMBLE_ROLE_CENTRAL_DISABLED -#define CONFIG_BT_NIMBLE_ROLE_CENTRAL +#define CONFIG_BT_NIMBLE_ROLE_CENTRAL 1 #endif #ifndef CONFIG_BT_NIMBLE_ROLE_OBSERVER_DISABLED -#define CONFIG_BT_NIMBLE_ROLE_OBSERVER +#define CONFIG_BT_NIMBLE_ROLE_OBSERVER 1 #endif #ifndef CONFIG_BT_NIMBLE_ROLE_PERIPHERAL_DISABLED -#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL +#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL 1 #endif #ifndef CONFIG_BT_NIMBLE_ROLE_BROADCASTER_DISABLED -#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER +#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER 1 #endif #ifndef CONFIG_BT_NIMBLE_PINNED_TO_CORE @@ -228,8 +233,14 @@ #define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0 #endif -#ifndef CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT -#define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT 12 +#ifdef CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT // backward compatibility +#define CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT +#elif !defined(CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT) +#define CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT 12 +#endif + +#ifndef CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE +#define CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE 256 #endif #ifndef CONFIG_BT_NIMBLE_RPA_TIMEOUT @@ -257,27 +268,32 @@ #define CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN 31 /** @brief ACL Buffer count */ -#define CONFIG_BT_NIMBLE_ACL_BUF_COUNT 12 +#define CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT 12 /** @brief ACL Buffer size */ #define CONFIG_BT_NIMBLE_TRANSPORT_ACL_SIZE 255 -/** @brief HCI Event Buffer size */ +/** @brief Transport (HCI) Event Buffer size */ #if CONFIG_BT_NIMBLE_EXT_ADV -# define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 257 +# define CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE 257 #else -# define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE 70 +# define CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE 70 #endif /** @brief Number of high priority HCI event buffers */ -#define CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT 30 +#define CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT 30 /** @brief Number of low priority HCI event buffers */ -#define CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT 8 +#define CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT 8 /** @brief Maximum number of connection oriented channels */ #define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0 +#define CONFIG_BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT 1 +#define CONFIG_BT_NIMBLE_EATT_CHAN_NUM 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION -1 +#define CONFIG_BT_NIMBLE_GATT_MAX_PROCS 4 + #define CONFIG_BT_NIMBLE_HS_FLOW_CTRL 1 #define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_ITVL 1000 #define CONFIG_BT_NIMBLE_HS_FLOW_CTRL_THRESH 2