From 8c00dcd84ee3de1af7f8846035a9f6ad93bb5118 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Thu, 22 Mar 2018 23:53:52 +0700 Subject: [PATCH 1/7] Fix WDT on large reload values --- .../ruuvitag_b/s132/armgcc/Makefile | 2 +- sdk_overrides/nrf_drv_wdt.c | 176 ++++++++++++++++++ 2 files changed, 177 insertions(+), 1 deletion(-) create mode 100644 sdk_overrides/nrf_drv_wdt.c diff --git a/ruuvi_examples/ruuvi_firmware/ruuvitag_b/s132/armgcc/Makefile b/ruuvi_examples/ruuvi_firmware/ruuvitag_b/s132/armgcc/Makefile index df8411b6..ef8cf15c 100644 --- a/ruuvi_examples/ruuvi_firmware/ruuvitag_b/s132/armgcc/Makefile +++ b/ruuvi_examples/ruuvi_firmware/ruuvitag_b/s132/armgcc/Makefile @@ -38,6 +38,7 @@ SRC_FILES += \ $(PROJ_DIR)/../../libraries/ruuvi_sensor_formats/chain_channels.c \ $(PROJ_DIR)/../../libraries/ruuvi_sensor_formats/sensortag.c \ $(PROJ_DIR)/../../sdk_overrides/app_button.c \ + $(PROJ_DIR)/../../sdk_overrides/nrf_drv_wdt.c \ $(PROJ_DIR)/ble_services/application_ble_event_handlers.c \ $(PROJ_DIR)/ble_services/application_service_if.c \ $(PROJ_DIR)/ble_services/nrf_dfu_flash_buttonless.c \ @@ -74,7 +75,6 @@ SRC_FILES += \ $(SDK_ROOT)/components/drivers_nrf/saadc/nrf_drv_saadc.c \ $(SDK_ROOT)/components/drivers_nrf/hal/nrf_saadc.c \ $(SDK_ROOT)/components/drivers_nrf/gpiote/nrf_drv_gpiote.c \ - $(SDK_ROOT)/components/drivers_nrf/wdt/nrf_drv_wdt.c \ $(SDK_ROOT)/components/ble/ble_advertising/ble_advertising.c \ $(SDK_ROOT)/components/libraries/bootloader/dfu/nrf_dfu_settings.c \ $(SDK_ROOT)/components/libraries/crc16/crc16.c \ diff --git a/sdk_overrides/nrf_drv_wdt.c b/sdk_overrides/nrf_drv_wdt.c new file mode 100644 index 00000000..040cda8d --- /dev/null +++ b/sdk_overrides/nrf_drv_wdt.c @@ -0,0 +1,176 @@ +/** + * Copyright (c) 2015 - 2017, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(WDT) +#include "nrf_drv_wdt.h" +#include "nrf_drv_common.h" +#include "nrf_error.h" +#include "nrf_assert.h" +#include "nrf_wdt.h" +#include "app_util_platform.h" +#include +#include + +#define NRF_LOG_MODULE_NAME "WDT" + +#if WDT_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL WDT_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR WDT_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR WDT_CONFIG_DEBUG_COLOR +#else //WDT_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif //WDT_CONFIG_LOG_ENABLED +#include "nrf_log.h" +#include "nrf_log_ctrl.h" + + +/**@brief WDT event handler. */ +static nrf_wdt_event_handler_t m_wdt_event_handler; + +/**@brief WDT state. */ +static nrf_drv_state_t m_state; + +/**@brief WDT alloc table. */ +static uint32_t m_alloc_index; + +static const nrf_drv_wdt_config_t m_default_config = NRF_DRV_WDT_DEAFULT_CONFIG; + +/**@brief WDT interrupt handler. */ +void WDT_IRQHandler(void) +{ + if (nrf_wdt_int_enable_check(NRF_WDT_INT_TIMEOUT_MASK) == true) + { + nrf_wdt_event_clear(NRF_WDT_EVENT_TIMEOUT); + m_wdt_event_handler(); + } +} + + +ret_code_t nrf_drv_wdt_init(nrf_drv_wdt_config_t const * p_config, + nrf_wdt_event_handler_t wdt_event_handler) +{ + ASSERT(wdt_event_handler != NULL); + ret_code_t err_code; + m_wdt_event_handler = wdt_event_handler; + + if (m_state == NRF_DRV_STATE_UNINITIALIZED) + { + m_state = NRF_DRV_STATE_INITIALIZED; + } + else + { + err_code = NRF_ERROR_INVALID_STATE; + NRF_LOG_WARNING("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code)); + return err_code; + } + + if (p_config == NULL) + { + p_config = &m_default_config; + } + + nrf_wdt_behaviour_set(p_config->behaviour); + + + + + + + + nrf_wdt_reload_value_set((p_config->reload_value * 32768) / 1000); + + nrf_drv_common_irq_enable(WDT_IRQn, p_config->interrupt_priority); + + err_code = NRF_SUCCESS; + NRF_LOG_INFO("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(err_code)); + return err_code; +} + + +void nrf_drv_wdt_enable(void) +{ + ASSERT(m_alloc_index != 0); + ASSERT(m_state == NRF_DRV_STATE_INITIALIZED); + nrf_wdt_int_enable(NRF_WDT_INT_TIMEOUT_MASK); + nrf_wdt_task_trigger(NRF_WDT_TASK_START); + m_state = NRF_DRV_STATE_POWERED_ON; + NRF_LOG_INFO("Enabled.\r\n"); +} + + +void nrf_drv_wdt_feed(void) +{ + ASSERT(m_state == NRF_DRV_STATE_POWERED_ON); + for (uint32_t i = 0; i < m_alloc_index; i++) + { + nrf_wdt_reload_request_set((nrf_wdt_rr_register_t)(NRF_WDT_RR0 + i)); + } +} + +ret_code_t nrf_drv_wdt_channel_alloc(nrf_drv_wdt_channel_id * p_channel_id) +{ + ret_code_t result; + ASSERT(p_channel_id); + ASSERT(m_state == NRF_DRV_STATE_INITIALIZED); + + CRITICAL_REGION_ENTER(); + if (m_alloc_index < NRF_WDT_CHANNEL_NUMBER) + { + *p_channel_id = (nrf_drv_wdt_channel_id)(NRF_WDT_RR0 + m_alloc_index); + m_alloc_index++; + nrf_wdt_reload_request_enable(*p_channel_id); + result = NRF_SUCCESS; + } + else + { + result = NRF_ERROR_NO_MEM; + } + CRITICAL_REGION_EXIT(); + NRF_LOG_INFO("Function: %s, error code: %s.\r\n", (uint32_t)__func__, (uint32_t)ERR_TO_STR(result)); + return result; +} + +void nrf_drv_wdt_channel_feed(nrf_drv_wdt_channel_id channel_id) +{ + ASSERT(m_state == NRF_DRV_STATE_POWERED_ON); + nrf_wdt_reload_request_set(channel_id); +} +#endif //NRF_MODULE_ENABLED(WDT) From 90db19f034812c31dcfd19a92fc56abb47c85f39 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Fri, 23 Mar 2018 00:10:39 +0700 Subject: [PATCH 2/7] Import overflow check from sdk14 --- sdk_overrides/nrf_drv_wdt.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/sdk_overrides/nrf_drv_wdt.c b/sdk_overrides/nrf_drv_wdt.c index 040cda8d..17207e2e 100644 --- a/sdk_overrides/nrf_drv_wdt.c +++ b/sdk_overrides/nrf_drv_wdt.c @@ -109,13 +109,11 @@ ret_code_t nrf_drv_wdt_init(nrf_drv_wdt_config_t const * p_config, nrf_wdt_behaviour_set(p_config->behaviour); - - - - - - - nrf_wdt_reload_value_set((p_config->reload_value * 32768) / 1000); + if ((((uint64_t) p_config->reload_value * 32768) / 1000) > UINT32_MAX) // Check for overflow + { + return NRF_ERROR_INVALID_PARAM; + } + nrf_wdt_reload_value_set(((uint64_t) p_config->reload_value * 32768) / 1000); nrf_drv_common_irq_enable(WDT_IRQn, p_config->interrupt_priority); From 1e1155b84bea50bced7c59cdd723dbf577163887 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Fri, 6 Apr 2018 14:49:35 +0300 Subject: [PATCH 3/7] Add advertisement type to configuration --- .../ruuvi_firmware/bluetooth_application_config.h | 8 ++++++++ ruuvi_examples/ruuvi_firmware/main.c | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ruuvi_examples/ruuvi_firmware/bluetooth_application_config.h b/ruuvi_examples/ruuvi_firmware/bluetooth_application_config.h index 7d075dfe..c4bdb0ba 100644 --- a/ruuvi_examples/ruuvi_firmware/bluetooth_application_config.h +++ b/ruuvi_examples/ruuvi_firmware/bluetooth_application_config.h @@ -26,4 +26,12 @@ //Raw v2 #define RAW_DATA_LENGTH 24 +/** + * BLE_GAP_ADV_TYPE_ADV_IND 0x00 Connectable, scannable + * BLE_GAP_ADV_TYPE_ADV_DIRECT_IND 0x01 + * BLE_GAP_ADV_TYPE_ADV_SCAN_IND 0x02 Nonconnectable, scannable + * BLE_GAP_ADV_TYPE_ADV_NONCONN_IND 0x03 Nonconnectable, nonscannable + */ +#define APPLICATION_ADVERTISEMENT_TYPE 0x00 + #endif diff --git a/ruuvi_examples/ruuvi_firmware/main.c b/ruuvi_examples/ruuvi_firmware/main.c index 42a72a6f..d0b4746b 100644 --- a/ruuvi_examples/ruuvi_firmware/main.c +++ b/ruuvi_examples/ruuvi_firmware/main.c @@ -260,7 +260,7 @@ int main(void) // Initialize BLE Stack. Required in all applications for timer operation. err_code |= init_ble(); - bluetooth_advertising_stop(); + bluetooth_configure_advertisement_type(APPLICATION_ADVERTISEMENT_TYPE); bluetooth_tx_power_set(BLE_TX_POWER); bluetooth_configure_advertising_interval(ADVERTISING_INTERVAL_RAW); @@ -290,8 +290,8 @@ int main(void) lis2dh12_enable(); lis2dh12_set_scale(LIS2DH12_SCALE); // Sample rate 10 for activity detection. - lis2dh12_set_sample_rate(LIS2DH12_RATE_10); - lis2dh12_set_resolution(LIS2DH12_SAMPLERATE_RAW); + lis2dh12_set_sample_rate(LIS2DH12_SAMPLERATE_RAW); + lis2dh12_set_resolution(LIS2DH12_RESOLUTION); //XXX If you read this, I'm sorry about line below. #include "lis2dh12_registers.h" From c31e50060f4468e5f17eaa4f6acfe4351d307bf5 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Fri, 6 Apr 2018 15:07:47 +0300 Subject: [PATCH 4/7] fix #83 --- drivers/bluetooth/ble_event_handlers.c | 7 ++++++- drivers/bluetooth/bluetooth_core.c | 8 ++++++-- ruuvi_examples/eddystone/bluetooth_application_config.h | 4 +++- .../ruuvi_firmware/bluetooth_application_config.h | 6 ++++-- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/drivers/bluetooth/ble_event_handlers.c b/drivers/bluetooth/ble_event_handlers.c index 911b3726..e91f43a9 100644 --- a/drivers/bluetooth/ble_event_handlers.c +++ b/drivers/bluetooth/ble_event_handlers.c @@ -13,7 +13,9 @@ #include "bluetooth_config.h" #include "app_scheduler.h" +#if APPLICATION_GATT #include "application_ble_event_handlers.h" +#endif static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ @@ -329,6 +331,9 @@ void ble_evt_dispatch(ble_evt_t * p_ble_evt) bsp_btn_ble_on_ble_evt(p_ble_evt); ble_advertising_on_ble_evt(p_ble_evt); on_ble_evt(p_ble_evt); - application_on_ble_evt(p_ble_evt); nrf_ble_qwr_on_ble_evt(&m_qwr, p_ble_evt); + +#if APPLICATION_GATT + application_on_ble_evt(p_ble_evt); +#endif } diff --git a/drivers/bluetooth/bluetooth_core.c b/drivers/bluetooth/bluetooth_core.c index 0c3752a0..316495ba 100644 --- a/drivers/bluetooth/bluetooth_core.c +++ b/drivers/bluetooth/bluetooth_core.c @@ -26,13 +26,15 @@ #include "sdk_errors.h" #include "nrf_delay.h" -#include "ble_event_handlers.h" #include "bluetooth_config.h" #include "ble_bulk_transfer.h" #include "eddystone.h" #include "ruuvi_endpoints.h" +#include "ble_event_handlers.h" +#if APPLICATION_GATT #include "application_service_if.h" +#endif #define NRF_LOG_MODULE_NAME "BLE_CORE" #define NRF_LOG__DEFAULT_LEVEL 4 @@ -358,10 +360,12 @@ ret_code_t bluetooth_stack_init(void) peer_manager_init(true); NRF_LOG_INFO("Peer manager init \r\n"); nrf_delay_ms(10); - + + #if APPLICATION_GATT err_code |= application_services_init(); NRF_LOG_INFO("Services init status %d\r\n", err_code); nrf_delay_ms(10); + #endif gap_params_init(); NRF_LOG_INFO("GAP params init\r\n"); diff --git a/ruuvi_examples/eddystone/bluetooth_application_config.h b/ruuvi_examples/eddystone/bluetooth_application_config.h index 5404610f..e1676ab3 100644 --- a/ruuvi_examples/eddystone/bluetooth_application_config.h +++ b/ruuvi_examples/eddystone/bluetooth_application_config.h @@ -8,7 +8,9 @@ #define APPLICATION_ADV_INTERVAL 500 /**< ms **/ #define APP_TX_POWER 4 /**< dBm **/ -#define INIT_FWREV "Eddystone_2.2.0" /**< Github tag **/ +#define INIT_FWREV "Eddystone_2.2.1" /**< Github tag **/ #define INIT_SWREV INIT_FWREV /**< Practicially same thing, as there is no separate SW **/ +#define APPLICATION_GATT 1 + #endif \ No newline at end of file diff --git a/ruuvi_examples/ruuvi_firmware/bluetooth_application_config.h b/ruuvi_examples/ruuvi_firmware/bluetooth_application_config.h index c4bdb0ba..eae1c907 100644 --- a/ruuvi_examples/ruuvi_firmware/bluetooth_application_config.h +++ b/ruuvi_examples/ruuvi_firmware/bluetooth_application_config.h @@ -5,9 +5,9 @@ #define APPLICATION_DEVICE_NAME_LENGTH 5 /**< number of characters in above string, excluding null */ #define APP_DEVICE_NAME APPLICATION_DEVICE_NAME /**< TODO: Refactoring **/ #define APP_DEVICE_NAME_LENGTH APPLICATION_DEVICE_NAME_LENGTH -#define APPLICATION_ADV_INTERVAL 1000 /**< ms **/ +#define APPLICATION_ADV_INTERVAL 1010 /**< ms. Use value which is not exactly divisible by 1000 ms for Minew interoperability **/ #define APP_TX_POWER 4 /**< dBm **/ -#define INIT_FWREV "2.2.0" /**< Github tag. Do not include specifiers such as "alpha" so you can accept ready binaries as they are **/ +#define INIT_FWREV "2.2.1" /**< Github tag. Do not include specifiers such as "alpha" so you can accept ready binaries as they are **/ #define INIT_SWREV INIT_FWREV /**< FW and SW are same thing in this context **/ // milliseconds until main loop timer function is called. Other timers can bring @@ -33,5 +33,7 @@ * BLE_GAP_ADV_TYPE_ADV_NONCONN_IND 0x03 Nonconnectable, nonscannable */ #define APPLICATION_ADVERTISEMENT_TYPE 0x00 +//Set to 0 if you don't want to include GATT connectivity. Remember to adjust advertisement type +#define APPLICATION_GATT 1 #endif From 0bb1eabdfbfa1f1b42bbfefa786db845b5bc56a1 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Fri, 6 Apr 2018 15:08:04 +0300 Subject: [PATCH 5/7] Ignore build files --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 21d642d2..7b056f14 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,10 @@ keys _build +#build files +*.hex +*.zip + # VisualGDB Makefile nrf5x.mak From 290ccfde7ae04eeeb10efc8a5df7696fa16380b7 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Fri, 6 Apr 2018 15:08:34 +0300 Subject: [PATCH 6/7] Add hack to allow few bytes more data in adv packet --- sdk_overrides/ble_advdata.c | 689 ++++++++++++++++++++++++++++++++++++ 1 file changed, 689 insertions(+) create mode 100644 sdk_overrides/ble_advdata.c diff --git a/sdk_overrides/ble_advdata.c b/sdk_overrides/ble_advdata.c new file mode 100644 index 00000000..c9ddac81 --- /dev/null +++ b/sdk_overrides/ble_advdata.c @@ -0,0 +1,689 @@ +/** + * Copyright (c) 2012 - 2017, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "ble_advdata.h" +#include "ble_gap.h" +#include "ble_srv_common.h" +#include "sdk_common.h" + +// Configure skipping advdata flags +#include "bluetooth_application_config.h" + +// NOTE: For now, Security Manager Out of Band Flags (OOB) are omitted from the advertising data. + +// Types of LE Bluetooth Device Address AD type +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC 0UL +#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM 1UL + +static uint32_t ble_device_addr_encode(uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t err_code; + ble_gap_addr_t device_addr; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_BLE_DEVICE_ADDR_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Get BLE address. + #if (NRF_SD_BLE_API_VERSION == 3) + err_code = sd_ble_gap_addr_get(&device_addr); + #else + err_code = sd_ble_gap_address_get(&device_addr); + #endif + VERIFY_SUCCESS(err_code); + + // Encode LE Bluetooth Device Address. + p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + + AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE); + *p_offset += ADV_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS; + *p_offset += ADV_AD_TYPE_FIELD_SIZE; + memcpy(&p_encoded_data[*p_offset], &device_addr.addr[0], BLE_GAP_ADDR_LEN); + *p_offset += BLE_GAP_ADDR_LEN; + if (BLE_GAP_ADDR_TYPE_PUBLIC == device_addr.addr_type) + { + p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC; + } + else + { + p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM; + } + *p_offset += AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE; + + return NRF_SUCCESS; +} + +static uint32_t name_encode(const ble_advdata_t * p_advdata, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t err_code; + uint16_t rem_adv_data_len; + uint16_t actual_length; + uint8_t adv_data_format; + + + // Validate parameters + if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && (0 == p_advdata->short_name_len)) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Check for buffer overflow. + if ( (((*p_offset) + ADV_AD_DATA_OFFSET) > max_size) || + ( (BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && + (((*p_offset) + ADV_AD_DATA_OFFSET + p_advdata->short_name_len) > max_size))) + { + return NRF_ERROR_DATA_SIZE; + } + + rem_adv_data_len = max_size - (*p_offset) - ADV_AD_DATA_OFFSET; + actual_length = rem_adv_data_len; + + // Get GAP device name and length + err_code = sd_ble_gap_device_name_get(&p_encoded_data[(*p_offset) + ADV_AD_DATA_OFFSET], + &actual_length); + VERIFY_SUCCESS(err_code); + + // Check if device intend to use short name and it can fit available data size. + if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len)) + { + // Complete device name can fit, setting Complete Name in Adv Data. + adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; + } + else + { + // Else short name needs to be used. Or application has requested use of short name. + adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME; + + // If application has set a preference on the short name size, it needs to be considered, + // else fit what can be fit. + if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && + (p_advdata->short_name_len <= rem_adv_data_len)) + { + // Short name fits available size. + actual_length = p_advdata->short_name_len; + } + // Else whatever can fit the data buffer will be packed. + else + { + actual_length = rem_adv_data_len; + } + } + + // There is only 1 byte intended to encode length which is (actual_length + ADV_AD_TYPE_FIELD_SIZE) + if (actual_length > (0x00FF - ADV_AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Complete name field in encoded data. + p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + actual_length); + *p_offset += ADV_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = adv_data_format; + *p_offset += ADV_AD_TYPE_FIELD_SIZE; + *p_offset += actual_length; + + return NRF_SUCCESS; +} + + +static uint32_t appearance_encode(uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t err_code; + uint16_t appearance; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_APPEARANCE_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Get GAP appearance field. + err_code = sd_ble_gap_appearance_get(&appearance); + VERIFY_SUCCESS(err_code); + + // Encode Length, AD Type and Appearance. + p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + AD_TYPE_APPEARANCE_DATA_SIZE); + *p_offset += ADV_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_APPEARANCE; + *p_offset += ADV_AD_TYPE_FIELD_SIZE; + *p_offset += uint16_encode(appearance, &p_encoded_data[*p_offset]); + + return NRF_SUCCESS; +} + +static uint32_t flags_encode(int8_t flags, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_FLAGS_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode flags. + p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + AD_TYPE_FLAGS_DATA_SIZE); + *p_offset += ADV_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_FLAGS; + *p_offset += ADV_AD_TYPE_FIELD_SIZE; + p_encoded_data[*p_offset] = flags; + *p_offset += AD_TYPE_FLAGS_DATA_SIZE; + + return NRF_SUCCESS; +} + +static uint32_t tx_power_level_encode(int8_t tx_power_level, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_TX_POWER_LEVEL_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode TX Power Level. + p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + + AD_TYPE_TX_POWER_LEVEL_DATA_SIZE); + *p_offset += ADV_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL; + *p_offset += ADV_AD_TYPE_FIELD_SIZE; + p_encoded_data[*p_offset] = tx_power_level; + *p_offset += AD_TYPE_TX_POWER_LEVEL_DATA_SIZE; + + return NRF_SUCCESS; +} + + +static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list, + uint8_t adv_type, + uint8_t uuid_size, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + int i; + bool is_heading_written = false; + uint16_t start_pos = *p_offset; + uint16_t length; + + for (i = 0; i < p_uuid_list->uuid_cnt; i++) + { + uint32_t err_code; + uint8_t encoded_size; + ble_uuid_t uuid = p_uuid_list->p_uuids[i]; + + // Find encoded uuid size. + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL); + VERIFY_SUCCESS(err_code); + + // Check size. + if (encoded_size == uuid_size) + { + uint8_t heading_bytes = (is_heading_written) ? 0 : ADV_AD_DATA_OFFSET; + + // Check for buffer overflow + if (((*p_offset) + encoded_size + heading_bytes) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + if (!is_heading_written) + { + // Write AD structure heading. + *p_offset += ADV_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = adv_type; + *p_offset += ADV_AD_TYPE_FIELD_SIZE; + is_heading_written = true; + } + + // Write UUID. + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_offset]); + VERIFY_SUCCESS(err_code); + *p_offset += encoded_size; + } + } + + if (is_heading_written) + { + // Write length. + length = (*p_offset) - (start_pos + ADV_LENGTH_FIELD_SIZE); + // There is only 1 byte intended to encode length + if (length > 0x00FF) + { + return NRF_ERROR_DATA_SIZE; + } + p_encoded_data[start_pos] = (uint8_t)length; + } + + return NRF_SUCCESS; +} + + +static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list, + uint8_t adv_type_16, + uint8_t adv_type_128, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t err_code; + + // Encode 16 bit UUIDs. + err_code = uuid_list_sized_encode(p_uuid_list, + adv_type_16, + sizeof(uint16_le_t), + p_encoded_data, + p_offset, + max_size); + VERIFY_SUCCESS(err_code); + + // Encode 128 bit UUIDs. + err_code = uuid_list_sized_encode(p_uuid_list, + adv_type_128, + sizeof(ble_uuid128_t), + p_encoded_data, + p_offset, + max_size); + VERIFY_SUCCESS(err_code); + + return NRF_SUCCESS; +} + + +static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int) +{ + // Check Minimum Connection Interval. + if ((p_conn_int->min_conn_interval < 0x0006) || + ( + (p_conn_int->min_conn_interval > 0x0c80) && + (p_conn_int->min_conn_interval != 0xffff) + ) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Check Maximum Connection Interval. + if ((p_conn_int->max_conn_interval < 0x0006) || + ( + (p_conn_int->max_conn_interval > 0x0c80) && + (p_conn_int->max_conn_interval != 0xffff) + ) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + // Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval. + if ((p_conn_int->min_conn_interval != 0xffff) && + (p_conn_int->max_conn_interval != 0xffff) && + (p_conn_int->min_conn_interval > p_conn_int->max_conn_interval) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + + +static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t err_code; + + // Check for buffer overflow. + if (((*p_offset) + AD_TYPE_CONN_INT_SIZE) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // Check parameters. + err_code = conn_int_check(p_conn_int); + VERIFY_SUCCESS(err_code); + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + AD_TYPE_CONN_INT_DATA_SIZE); + *p_offset += ADV_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE; + *p_offset += ADV_AD_TYPE_FIELD_SIZE; + + // Encode Minimum and Maximum Connection Intervals. + *p_offset += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_offset]); + *p_offset += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_offset]); + + return NRF_SUCCESS; +} + + +static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint32_t data_size = AD_TYPE_MANUF_SPEC_DATA_ID_SIZE + p_manuf_sp_data->data.size; + + // Check for buffer overflow. + if (((*p_offset) + ADV_AD_DATA_OFFSET + data_size) > max_size) + { + return NRF_ERROR_DATA_SIZE; + } + + // There is only 1 byte intended to encode length which is (data_size + ADV_AD_TYPE_FIELD_SIZE) + if (data_size > (0x00FF - ADV_AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + data_size); + *p_offset += ADV_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA; + *p_offset += ADV_AD_TYPE_FIELD_SIZE; + + // Encode Company Identifier. + *p_offset += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_offset]); + + // Encode additional manufacturer specific data. + if (p_manuf_sp_data->data.size > 0) + { + if (p_manuf_sp_data->data.p_data == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + memcpy(&p_encoded_data[*p_offset], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size); + *p_offset += p_manuf_sp_data->data.size; + } + + return NRF_SUCCESS; +} + +// Implemented only for 16-bit UUIDs +static uint32_t service_data_encode(const ble_advdata_t * p_advdata, + uint8_t * p_encoded_data, + uint16_t * p_offset, + uint16_t max_size) +{ + uint8_t i; + + // Check parameter consistency. + if (p_advdata->p_service_data_array == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + for (i = 0; i < p_advdata->service_data_count; i++) + { + ble_advdata_service_data_t * p_service_data; + uint32_t data_size; + + p_service_data = &p_advdata->p_service_data_array[i]; + // For now implemented only for 16-bit UUIDs + data_size = AD_TYPE_SERV_DATA_16BIT_UUID_SIZE + p_service_data->data.size; + + // There is only 1 byte intended to encode length which is (data_size + ADV_AD_TYPE_FIELD_SIZE) + if (data_size > (0x00FF - ADV_AD_TYPE_FIELD_SIZE)) + { + return NRF_ERROR_DATA_SIZE; + } + + // Encode Length and AD Type. + p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + data_size); + *p_offset += ADV_LENGTH_FIELD_SIZE; + p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SERVICE_DATA; + *p_offset += ADV_AD_TYPE_FIELD_SIZE; + + // Encode service 16-bit UUID. + *p_offset += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_offset]); + + // Encode additional service data. + if (p_service_data->data.size > 0) + { + if (p_service_data->data.p_data == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + memcpy(&p_encoded_data[*p_offset], p_service_data->data.p_data, p_service_data->data.size); + *p_offset += p_service_data->data.size; + } + } + + return NRF_SUCCESS; +} + +uint32_t adv_data_encode(ble_advdata_t const * const p_advdata, + uint8_t * const p_encoded_data, + uint16_t * const p_len) +{ + uint32_t err_code = NRF_SUCCESS; + uint16_t max_size = *p_len; + *p_len = 0; + + // Encode LE Bluetooth Device Address + if (p_advdata->include_ble_device_addr) + { + err_code = ble_device_addr_encode(p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode appearance. + if (p_advdata->include_appearance) + { + err_code = appearance_encode(p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + //Encode Flags + if (p_advdata->flags != 0 ) + { + err_code = flags_encode(p_advdata->flags, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode TX power level. + if (p_advdata->p_tx_power_level != NULL) + { + err_code = tx_power_level_encode(*p_advdata->p_tx_power_level, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'more available' uuid list. + if (p_advdata->uuids_more_available.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_more_available, + BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE, + BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'complete' uuid list. + if (p_advdata->uuids_complete.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_complete, + BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, + BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode 'solicited service' uuid list. + if (p_advdata->uuids_solicited.uuid_cnt > 0) + { + err_code = uuid_list_encode(&p_advdata->uuids_solicited, + BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT, + BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Slave Connection Interval Range. + if (p_advdata->p_slave_conn_int != NULL) + { + err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Manufacturer Specific Data. + if (p_advdata->p_manuf_specific_data != NULL) + { + err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data, + p_encoded_data, + p_len, + max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode Service Data. + if (p_advdata->service_data_count > 0) + { + err_code = service_data_encode(p_advdata, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + // Encode name. WARNING: it is encoded last on purpose since too long device name is truncated. + if (p_advdata->name_type != BLE_ADVDATA_NO_NAME) + { + err_code = name_encode(p_advdata, p_encoded_data, p_len, max_size); + VERIFY_SUCCESS(err_code); + } + + return err_code; +} + + +static uint32_t advdata_check(const ble_advdata_t * p_advdata) +{ + // Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set. + // This hack allows skipping flags which leads to technically ok but spec-violating BLE packets. + #if BLE_SKIP_ADVDATA_FLAGS + #else + if ( + ((p_advdata->flags & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0) + ) + { + return NRF_ERROR_INVALID_PARAM; + } + #endif + + return NRF_SUCCESS; +} + + +static uint32_t srdata_check(const ble_advdata_t * p_srdata) +{ + // Flags shall not be included in the scan response data. + if (p_srdata->flags) + { + return NRF_ERROR_INVALID_PARAM; + } + + return NRF_SUCCESS; +} + + +uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata) +{ + uint32_t err_code; + uint16_t len_advdata = BLE_GAP_ADV_MAX_SIZE; + uint16_t len_srdata = BLE_GAP_ADV_MAX_SIZE; + uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE]; + uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE]; + uint8_t * p_encoded_advdata; + uint8_t * p_encoded_srdata; + + // Encode advertising data (if supplied). + if (p_advdata != NULL) + { + err_code = advdata_check(p_advdata); + VERIFY_SUCCESS(err_code); + + err_code = adv_data_encode(p_advdata, encoded_advdata, &len_advdata); + VERIFY_SUCCESS(err_code); + p_encoded_advdata = encoded_advdata; + } + else + { + p_encoded_advdata = NULL; + len_advdata = 0; + } + + // Encode scan response data (if supplied). + if (p_srdata != NULL) + { + err_code = srdata_check(p_srdata); + VERIFY_SUCCESS(err_code); + + err_code = adv_data_encode(p_srdata, encoded_srdata, &len_srdata); + VERIFY_SUCCESS(err_code); + p_encoded_srdata = encoded_srdata; + } + else + { + p_encoded_srdata = NULL; + len_srdata = 0; + } + + // Pass encoded advertising data and/or scan response data to the stack. + return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata); +} From 831782112363f26296c9fa33a376def1fb299641 Mon Sep 17 00:00:00 2001 From: Otso Jousimaa Date: Fri, 6 Apr 2018 15:09:09 +0300 Subject: [PATCH 7/7] Ignore SDK 14 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7b056f14..a2653223 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,4 @@ nRF5_SDK_12.1.0_0d23e2a.zip nRF5_SDK_12.2.* nRF5_SDK_12.3.* nRF5_SDK_13.* +nRF5_SDK_14.*