Merge branch 'develop' of https://github.com/ARMmbed/ble-nrf51822 into characteristicDescriptorDiscovery

master
Vincent Coubard 2015-12-14 11:57:57 +00:00
commit 7e784e0e0c
105 changed files with 219 additions and 31137 deletions

View File

@ -1,31 +0,0 @@
/*
* Copyright (c) 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 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 other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

11
LICENSE
View File

@ -1,9 +1,6 @@
Many of the files in this module have been inherited from the Nordic SDK for
nRF51822. With the exception of the softdevice, they come with a BSD license
offered by Nordic for use in mbed. The Nordic Softdevice License Agreement, a
BSD-like licence for binary distributions, applies to the softdevice. Some
This module contains softdevice which comes with The Nordic Softdevice License Agreement,
a BSD-like licence for binary distributions, offered by Nordic for use in mbed. Some
other files come from the mbed SDK, and are licensed under Apache-2.0. Unless
specifically indicated otherwise in a file, files are licensed under the
Apache 2.0 license, as can be found in: apache-2.0.txt. The BSD-like Nordic
license can be found in BSD-3clause-Nordic.txt. The Nordic Semiconductor Softdevice
License Agreement can be found in softdevice_nrf51822_licence_agreement.txt.
Apache 2.0 license, as can be found in: apache-2.0.txt. The Nordic Semiconductor Softdevice
License Agreement can be found in softdevice_nrf51822_licence_agreement.txt.

View File

@ -1,6 +1,6 @@
{
"name": "ble-nrf51822",
"version": "2.0.6",
"version": "2.2.5",
"description": "Nordic stack and drivers for the mbed BLE API.",
"keywords": [
"Bluetooth",
@ -24,29 +24,13 @@
}
],
"dependencies": {
"ble": "^2.0.0"
"ble": "^2.1.11",
"nrf51-sdk": "^1.0.0"
},
"extraIncludes": [
"source/btle",
"source/btle/custom",
"source/common",
"source/nordic-sdk/components",
"source/nordic-sdk/components/libraries/util",
"source/nordic-sdk/components/libraries/hci",
"source/nordic-sdk/components/libraries/bootloader_dfu",
"source/nordic-sdk/components/libraries/bootloader_dfu/hci_transport",
"source/nordic-sdk/components/libraries/bootloader_dfu/experimental",
"source/nordic-sdk/components/softdevice/s130/include",
"source/nordic-sdk/components/softdevice/common/softdevice_handler",
"source/nordic-sdk/components/drivers_nrf/hal",
"source/nordic-sdk/components/drivers_nrf/ble_flash",
"source/nordic-sdk/components/drivers_nrf/pstorage",
"source/nordic-sdk/components/drivers_nrf/pstorage/config",
"source/nordic-sdk/components/ble/ble_radio_notification",
"source/nordic-sdk/components/ble/ble_services/ble_dfu",
"source/nordic-sdk/components/ble/common",
"source/nordic-sdk/components/ble/device_manager",
"source/nordic-sdk/components/ble/device_manager/config"
"source/common"
],
"targetDependencies": {}
}

View File

@ -19,7 +19,6 @@
#include "btle.h"
#include "ble_stack_handler_types.h"
#include "ble_flash.h"
#include "ble_conn_params.h"
@ -27,15 +26,17 @@
#include "btle_advertising.h"
#include "custom/custom_helper.h"
#include "softdevice_handler.h"
#include "pstorage.h"
#include "ble/GapEvents.h"
#include "nRF5xGap.h"
#include "nRF5xGattServer.h"
#include "nRF5xSecurityManager.h"
extern "C" {
#include "pstorage.h"
#include "device_manager.h"
#include "softdevice_handler.h"
#include "ble_stack_handler_types.h"
}
#include "ble_hci.h"
#include "btle_discovery.h"

View File

@ -15,17 +15,35 @@
*/
#include "btle.h"
#include "pstorage.h"
#include "nRF5xGap.h"
#include "nRF5xSecurityManager.h"
extern "C" {
#include "pstorage.h"
#include "device_manager.h"
}
#include "btle_security.h"
static dm_application_instance_t applicationInstance;
static ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result);
// default security parameters
static ble_gap_sec_params_t securityParameters = {
.bond = true, /**< Perform bonding. */
.mitm = true, /**< Man In The Middle protection required. */
.io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */
.oob = 0, /**< Out Of Band data available. */
.min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */
.max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */
.kdist_periph = {
.enc = 1, /**< Long Term Key and Master Identification. */
.id = 1, /**< Identity Resolving Key and Identity Address Information. */
.sign = 1, /**< Connection Signature Resolving Key. */
}, /**< Key distribution bitmap: keys that the peripheral device will distribute. */
};
ble_error_t
btle_initializeSecurity(bool enableBonding,
bool requireMITM,
@ -68,22 +86,15 @@ btle_initializeSecurity(bool enableBonding,
return BLE_ERROR_UNSPECIFIED;
}
// update default security parameters with function call parameters
securityParameters.bond = enableBonding;
securityParameters.mitm = requireMITM;
securityParameters.io_caps = iocaps;
const dm_application_param_t dm_param = {
.evt_handler = dm_handler,
.service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID,
.sec_param = {
.bond = enableBonding,/**< Perform bonding. */
.mitm = requireMITM, /**< Man In The Middle protection required. */
.io_caps = iocaps, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */
.oob = 0, /**< Out Of Band data available. */
.min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */
.max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */
.kdist_periph = {
.enc = 1, /**< Long Term Key and Master Identification. */
.id = 1, /**< Identity Resolving Key and Identity Address Information. */
.sign = 1, /**< Connection Signature Resolving Key. */
}, /**< Key distribution bitmap: keys that the peripheral device will distribute. */
}
.sec_param = securityParameters
};
if ((rc = dm_register(&applicationInstance, &dm_param)) != NRF_SUCCESS) {
@ -148,6 +159,48 @@ btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecuri
return BLE_ERROR_NONE;
}
ble_error_t
btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode)
{
// use default and updated parameters as starting point
// and modify structure based on security mode.
ble_gap_sec_params_t params = securityParameters;
switch (securityMode) {
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK:
/**< Require no protection, open link. */
securityParameters.bond = false;
securityParameters.mitm = false;
break;
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM:
/**< Require encryption, but no MITM protection. */
securityParameters.bond = true;
securityParameters.mitm = false;
break;
// not yet implemented security modes
case SecurityManager::SECURITY_MODE_NO_ACCESS:
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM:
/**< Require encryption and MITM protection. */
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM:
/**< Require signing or encryption, but no MITM protection. */
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM:
/**< Require signing or encryption, and MITM protection. */
default:
return BLE_ERROR_NOT_IMPLEMENTED;
}
// update security settings for given connection
uint32_t result = sd_ble_gap_authenticate(connectionHandle, &params);
if (result == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else {
return BLE_ERROR_UNSPECIFIED;
}
}
ret_code_t
dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result)
{

View File

@ -48,10 +48,23 @@ ble_error_t btle_initializeSecurity(bool en
* @param[out] securityStatusP
* security status.
*
* @return BLE_SUCCESS Or appropriate error code indicating reason for failure.
* @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure.
*/
ble_error_t btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP);
/**
* Set the security mode on a connection. Useful for elevating the security mode
* once certain conditions are met, e.g., a particular service is found.
*
* @param[in] connectionHandle
* Handle to identify the connection.
* @param[in] securityMode
* security mode.
*
* @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure.
*/
ble_error_t btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode);
/**
* Function for deleting all peer device context and all related bonding
* information from the database.

View File

@ -148,9 +148,8 @@ uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base)
ble_uuid128_t base_uuid;
uint8_t uuid_type = 0;
/* Reverse the bytes since ble_uuid128_t is LSB */
for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
base_uuid.uuid128[i] = p_uuid_base[UUID::LENGTH_OF_LONG_UUID - 1 - i];
base_uuid.uuid128[i] = p_uuid_base[i];
}
ASSERT_INT( ERROR_NONE, sd_ble_uuid_vs_add( &base_uuid, &uuid_type ), 0);
@ -168,9 +167,8 @@ error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base,
{
UUID::LongUUIDBytes_t uuid_base_le;
/* Reverse the bytes since ble_uuid128_t is LSB */
for (uint8_t i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
uuid_base_le[i] = p_uuid_base[UUID::LENGTH_OF_LONG_UUID - 1 - i];
uuid_base_le[i] = p_uuid_base[i];
}
ASSERT_STATUS( sd_ble_uuid_decode(UUID::LENGTH_OF_LONG_UUID, uuid_base_le, p_uuid));
@ -191,6 +189,8 @@ error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base,
@param[in] char_props The characteristic properties, as
defined by ble_gatt_char_props_t
@param[in] max_length The maximum length of this characeristic
@param[in] has_variable_len Whether the characteristic data has
variable length.
@param[out] p_char_handle
@returns
@ -202,8 +202,9 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
uint8_t properties,
SecurityManager::SecurityMode_t requiredSecurity,
uint8_t *p_data,
uint16_t min_length,
uint16_t length,
uint16_t max_length,
bool has_variable_len,
const uint8_t *userDescriptionDescriptorValuePtr,
uint16_t userDescriptionDescriptorValueLen,
bool readAuthorization,
@ -242,7 +243,8 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
attr_md.wr_auth = writeAuthorization;
attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.vlen = (min_length == max_length) ? 0 : 1;
/* Always set variable size */
attr_md.vlen = has_variable_len;
if (char_props.read || char_props.notify || char_props.indicate) {
switch (requiredSecurity) {
@ -292,7 +294,7 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
attr_char_value.p_uuid = p_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = min_length;
attr_char_value.init_len = length;
attr_char_value.max_len = max_length;
attr_char_value.p_value = p_data;
@ -317,23 +319,27 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
since 1 is typically used by the primary
service).
@param[in] max_length The maximum length of this descriptor
@param[in] has_variable_len Whether the characteristic data has
variable length.
@returns
@retval ERROR_NONE Everything executed normally
*/
/**************************************************************************/
error_t custom_add_in_descriptor(uint16_t char_handle,
ble_uuid_t *p_uuid,
uint8_t *p_data,
uint16_t min_length,
uint16_t max_length,
uint16_t *p_desc_handle)
ble_uuid_t *p_uuid,
uint8_t *p_data,
uint16_t length,
uint16_t max_length,
bool has_variable_len,
uint16_t *p_desc_handle)
{
/* Descriptor metadata */
ble_gatts_attr_md_t desc_md = {0};
desc_md.vloc = BLE_GATTS_VLOC_STACK;
desc_md.vlen = (min_length == max_length) ? 0 : 1;
/* Always set variable size */
desc_md.vlen = has_variable_len;
/* Make it readable and writable */
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm);
@ -343,7 +349,7 @@ error_t custom_add_in_descriptor(uint16_t char_handle,
attr_desc.p_uuid = p_uuid;
attr_desc.p_attr_md = &desc_md;
attr_desc.init_len = min_length;
attr_desc.init_len = length;
attr_desc.max_len = max_length;
attr_desc.p_value = p_data;

View File

@ -36,8 +36,9 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
uint8_t properties,
SecurityManager::SecurityMode_t requiredSecurity,
uint8_t *p_data,
uint16_t min_length,
uint16_t length,
uint16_t max_length,
bool has_variable_len,
const uint8_t *userDescriptionDescriptorValuePtr,
uint16_t userDescriptionDescriptorValueLen,
bool readAuthorization,
@ -47,8 +48,9 @@ error_t custom_add_in_characteristic(uint16_t service_handle,
error_t custom_add_in_descriptor(uint16_t char_handle,
ble_uuid_t *p_uuid,
uint8_t *p_data,
uint16_t min_length,
uint16_t length,
uint16_t max_length,
bool has_variable_len,
uint16_t *p_desc_handle);
#ifdef __cplusplus

View File

@ -374,15 +374,30 @@ uint16_t nRF5xGap::getConnectionHandle(void)
/**************************************************************************/
ble_error_t nRF5xGap::setAddress(AddressType_t type, const Address_t address)
{
if (type > ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) {
uint8_t cycle_mode;
ble_gap_addr_t dev_addr;
/* When using Public or Static addresses, the cycle mode must be None.
When using Random Private addresses, the cycle mode must be Auto.
In auto mode, the given address is ignored.
*/
if ((type == ADDR_TYPE_PUBLIC) || (type == ADDR_TYPE_RANDOM_STATIC))
{
cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_NONE;
memcpy(dev_addr.addr, address, ADDR_LEN);
}
else if ((type == ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE) || (type == ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE))
{
cycle_mode = BLE_GAP_ADDR_CYCLE_MODE_AUTO;
// address is ignored when in auto mode
}
else
{
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
ble_gap_addr_t dev_addr;
dev_addr.addr_type = type;
memcpy(dev_addr.addr, address, ADDR_LEN);
ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE);
ASSERT_INT(ERROR_NONE, sd_ble_gap_address_set(cycle_mode, &dev_addr), BLE_ERROR_PARAM_OUT_OF_RANGE);
return BLE_ERROR_NONE;
}

View File

@ -26,7 +26,11 @@
#include "ble/GapScanningParams.h"
#include "nrf_soc.h"
extern "C" {
#include "ble_radio_notification.h"
}
#include "btle_security.h"
void radioNotificationStaticCallback(bool param);
@ -109,64 +113,84 @@ public:
#endif
private:
#ifdef YOTTA_CFG_MBED_OS
/*
* In mbed OS, all user-facing BLE events (interrupts) are posted to the
* MINAR scheduler to be executed as callbacks in thread mode. MINAR guards
* its critical sections from interrupts by acquiring CriticalSectionLock,
* which results in a call to sd_nvic_critical_region_enter(). Thus, it is
* safe to invoke MINAR APIs from interrupt context as long as those
* interrupts are blocked by sd_nvic_critical_region_enter().
*
* Radio notifications are a special case for the above. The Radio
* Notification IRQ is handled at a very high priority--higher than the
* level blocked by sd_nvic_critical_region_enter(). Thus Radio Notification
* events can preempt MINAR's critical sections. Using MINAR APIs (such as
* posting an event) directly in processRadioNotification() may result in a
* race condition ending in a hard-fault.
*
* The solution is to *not* call MINAR APIs directly from the Radio
* Notification handling; i.e. to do the bulk of RadioNotification
* processing at a reduced priority which respects MINAR's critical
* sections. Unfortunately, on a cortex-M0, there is no clean way to demote
* priority for the currently executing interrupt--we wouldn't want to
* demote the radio notification handling anyway because it is sensitive to
* timing, and the system expects to finish this handling very quickly. The
* workaround is to employ a Timeout to trigger
* postRadioNotificationCallback() after a very short delay (~0 us) and post
* the MINAR callback that context.
*
* !!!WARNING!!! Radio notifications are very time critical events. The
* current solution is expected to work under the assumption that
* postRadioNotificationCalback() will be executed BEFORE the next radio
* notification event is generated.
*/
bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */
Timeout radioNotificationTimeout;
/*
* A helper function to post radio notification callbacks through MINAR when using mbed OS.
* A helper function to post radio notification callbacks with low interrupt priority.
*/
void postRadioNotificationCallback(void) {
#ifdef YOTTA_CFG_MBED_OS
/*
* In mbed OS, all user-facing BLE events (interrupts) are posted to the
* MINAR scheduler to be executed as callbacks in thread mode. MINAR guards
* its critical sections from interrupts by acquiring CriticalSectionLock,
* which results in a call to sd_nvic_critical_region_enter(). Thus, it is
* safe to invoke MINAR APIs from interrupt context as long as those
* interrupts are blocked by sd_nvic_critical_region_enter().
*
* Radio notifications are a special case for the above. The Radio
* Notification IRQ is handled at a very high priority--higher than the
* level blocked by sd_nvic_critical_region_enter(). Thus Radio Notification
* events can preempt MINAR's critical sections. Using MINAR APIs (such as
* posting an event) directly in processRadioNotification() may result in a
* race condition ending in a hard-fault.
*
* The solution is to *not* call MINAR APIs directly from the Radio
* Notification handling; i.e. to do the bulk of RadioNotification
* processing at a reduced priority which respects MINAR's critical
* sections. Unfortunately, on a cortex-M0, there is no clean way to demote
* priority for the currently executing interrupt--we wouldn't want to
* demote the radio notification handling anyway because it is sensitive to
* timing, and the system expects to finish this handling very quickly. The
* workaround is to employ a Timeout to trigger
* postRadioNotificationCallback() after a very short delay (~0 us) and post
* the MINAR callback that context.
*
* !!!WARNING!!! Radio notifications are very time critical events. The
* current solution is expected to work under the assumption that
* postRadioNotificationCalback() will be executed BEFORE the next radio
* notification event is generated.
*/
minar::Scheduler::postCallback(
mbed::util::FunctionPointer1<void, bool>(&radioNotificationCallback, &FunctionPointerWithContext<bool>::call).bind(radioNotificationCallbackParam)
);
}
#else
/*
* In mbed classic, all user-facing BLE events execute callbacks in interrupt
* mode. Radio Notifications are a special case because its IRQ is handled at
* a very high priority. Thus Radio Notification events can preempt other
* operations that require interaction with the SoftDevice such as advertising
* payload updates and changing the Gap state. Therefore, executing a Radio
* Notification callback directly from processRadioNotification() may result
* in a race condition ending in a hard-fault.
*
* The solution is to *not* execute the Radio Notification callback directly
* from the Radio Notification handling; i.e. to do the bulk of the
* Radio Notification processing at a reduced priority. Unfortunately, on a
* cortex-M0, there is no clean way to demote priority for the currently
* executing interrupt--we wouldn't want to demote the radio notification
* handling anyway because it is sensitive to timing, and the system expects
* to finish this handling very quickly. The workaround is to employ a Timeout
* to trigger postRadioNotificationCallback() after a very short delay (~0 us)
* and execute the callback in that context.
*
* !!!WARNING!!! Radio notifications are very time critical events. The
* current solution is expected to work under the assumption that
* postRadioNotificationCalback() will be executed BEFORE the next radio
* notification event is generated.
*/
radioNotificationCallback.call(radioNotificationCallbackParam);
#endif /* #ifdef YOTTA_CFG_MBED_OS */
}
/**
* A helper function to process radio-notification events; to be called internally.
* @param param [description]
*/
void processRadioNotificationEvent(bool param) {
#ifdef YOTTA_CFG_MBED_OS
/* When using mbed OS the callback to the user-defined function will be posted through minar */
radioNotificationCallbackParam = param;
radioNotificationTimeout.attach_us(this, &nRF5xGap::postRadioNotificationCallback, 0);
#else
radioNotificationCallback.call(param);
#endif
}
friend void radioNotificationStaticCallback(bool param); /* allow invocations of processRadioNotificationEvent() */

View File

@ -69,7 +69,7 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
/* Skip any incompletely defined, read-only characteristics. */
if ((p_char->getValueAttribute().getValuePtr() == NULL) &&
(p_char->getValueAttribute().getInitialLength() == 0) &&
(p_char->getValueAttribute().getLength() == 0) &&
(p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) {
continue;
}
@ -95,8 +95,9 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
p_char->getProperties(),
p_char->getRequiredSecurity(),
p_char->getValueAttribute().getValuePtr(),
p_char->getValueAttribute().getInitialLength(),
p_char->getValueAttribute().getLength(),
p_char->getValueAttribute().getMaxLength(),
p_char->getValueAttribute().hasVariableLength(),
userDescriptionDescriptorValuePtr,
userDescriptionDescriptorValueLen,
p_char->isReadAuthorizationEnabled(),
@ -127,8 +128,9 @@ ble_error_t nRF5xGattServer::addService(GattService &service)
custom_add_in_descriptor(BLE_GATT_HANDLE_INVALID,
&nordicUUID,
p_desc->getValuePtr(),
p_desc->getInitialLength(),
p_desc->getLength(),
p_desc->getMaxLength(),
p_desc->hasVariableLength(),
&nrfDescriptorHandles[descriptorCount]),
BLE_ERROR_PARAM_OUT_OF_RANGE);

View File

@ -39,6 +39,10 @@ public:
return btle_getLinkSecurity(connectionHandle, securityStatusP);
}
virtual ble_error_t setLinkSecurity(Gap::Handle_t connectionHandle, SecurityMode_t securityMode) {
return btle_setLinkSecurity(connectionHandle, securityMode);
}
virtual ble_error_t purgeAllBondingState(void) {
return btle_purgeAllBondingState();
}

View File

@ -285,13 +285,10 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_char_val_
if (state == DISCOVER_SERVICE_UUIDS) {
if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) {
UUID::LongUUIDBytes_t uuid;
/* Switch longUUID bytes to MSB */
for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
uuid[i] = response->handle_value[0].p_value[UUID::LENGTH_OF_LONG_UUID - 1 - i];
}
memcpy(uuid, response->handle_value[0].p_value, UUID::LENGTH_OF_LONG_UUID);
unsigned serviceIndex = serviceUUIDDiscoveryQueue.dequeue();
services[serviceIndex].setupLongUUID(uuid);
services[serviceIndex].setupLongUUID(uuid, UUID::LSB);
serviceUUIDDiscoveryQueue.triggerFirst();
} else {
@ -300,13 +297,11 @@ nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_char_val_
} else if (state == DISCOVER_CHARACTERISTIC_UUIDS) {
if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) {
UUID::LongUUIDBytes_t uuid;
/* Switch longUUID bytes to MSB */
for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
uuid[i] = response->handle_value[0].p_value[3 + UUID::LENGTH_OF_LONG_UUID - 1 - i];
}
memcpy(uuid, &(response->handle_value[0].p_value[3]), UUID::LENGTH_OF_LONG_UUID);
unsigned charIndex = charUUIDDiscoveryQueue.dequeue();
characteristics[charIndex].setupLongUUID(uuid);
characteristics[charIndex].setupLongUUID(uuid, UUID::LSB);
charUUIDDiscoveryQueue.triggerFirst();
} else {

View File

@ -22,7 +22,9 @@
#include "btle/btle.h"
#include "nrf_delay.h"
extern "C" {
#include "softdevice_handler.h"
}
/**
* The singleton which represents the nRF51822 transport for the BLE.

View File

@ -1,80 +0,0 @@
/*
* Copyright (c) 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 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 other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_radio_notification.h"
#include <stdlib.h>
static bool m_radio_active = false; /**< Current radio state. */
static ble_radio_notification_evt_handler_t m_evt_handler = NULL; /**< Application event handler for handling Radio Notification events. */
void SWI1_IRQHandler(void)
{
m_radio_active = !m_radio_active;
if (m_evt_handler != NULL)
{
m_evt_handler(m_radio_active);
}
}
uint32_t ble_radio_notification_init(nrf_app_irq_priority_t irq_priority,
nrf_radio_notification_distance_t distance,
ble_radio_notification_evt_handler_t evt_handler)
{
uint32_t err_code;
m_evt_handler = evt_handler;
// Initialize Radio Notification software interrupt
err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = sd_nvic_SetPriority(SWI1_IRQn, irq_priority);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = sd_nvic_EnableIRQ(SWI1_IRQn);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
// Configure the event
return sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH, distance);
}

View File

@ -1,74 +0,0 @@
/*
* Copyright (c) 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 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 other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_radio_notification Radio Notification Event Handler
* @{
* @ingroup ble_sdk_lib
* @brief Module for propagating Radio Notification events to the application.
*/
#ifndef BLE_RADIO_NOTIFICATION_H__
#define BLE_RADIO_NOTIFICATION_H__
#include <stdint.h>
#include <stdbool.h>
#include "nrf_soc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Application radio notification event handler type. */
typedef void (*ble_radio_notification_evt_handler_t) (bool radio_active);
/**@brief Function for initializing the Radio Notification module.
*
* @param[in] irq_priority Interrupt priority for the Radio Notification interrupt handler.
* @param[in] distance The time from an Active event until the radio is activated.
* @param[in] evt_handler Handler to be executed when a radio notification event has been
* received.
*
* @return NRF_SUCCESS on successful initialization, otherwise an error code.
*/
uint32_t ble_radio_notification_init(nrf_app_irq_priority_t irq_priority,
nrf_radio_notification_distance_t distance,
ble_radio_notification_evt_handler_t evt_handler);
#ifdef __cplusplus
}
#endif
#endif // BLE_RADIO_NOTIFICATION_H__
/** @} */

View File

@ -1,686 +0,0 @@
/*
* Copyright (c) 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 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 other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_dfu.h"
#include "nrf_error.h"
#include "ble_types.h"
#include "ble_gatts.h"
#include "app_util.h"
#include "ble_srv_common.h"
#include "nordic_common.h"
#include <stdint.h>
#include <string.h>
#include <stddef.h>
#define MAX_DFU_PKT_LEN 20 /**< Maximum length (in bytes) of the DFU Packet characteristic. */
#define PKT_START_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Start DFU Request. */
#define PKT_INIT_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Init DFU Request. */
#define PKT_RCPT_NOTIF_REQ_LEN 3 /**< Length (in bytes) of the Packet Receipt Notification Request. */
#define MAX_PKTS_RCPT_NOTIF_LEN 6 /**< Maximum length (in bytes) of the Packets Receipt Notification. */
#define MAX_RESPONSE_LEN 7 /**< Maximum length (in bytes) of the response to a Control Point command. */
#define MAX_NOTIF_BUFFER_LEN MAX(MAX_PKTS_RCPT_NOTIF_LEN, MAX_RESPONSE_LEN) /**< Maximum length (in bytes) of the buffer needed by DFU Service while sending notifications to peer. */
enum
{
OP_CODE_START_DFU = 1, /**< Value of the Op code field for 'Start DFU' command.*/
OP_CODE_RECEIVE_INIT = 2, /**< Value of the Op code field for 'Initialize DFU parameters' command.*/
OP_CODE_RECEIVE_FW = 3, /**< Value of the Op code field for 'Receive firmware image' command.*/
OP_CODE_VALIDATE = 4, /**< Value of the Op code field for 'Validate firmware' command.*/
OP_CODE_ACTIVATE_N_RESET = 5, /**< Value of the Op code field for 'Activate & Reset' command.*/
OP_CODE_SYS_RESET = 6, /**< Value of the Op code field for 'Reset System' command.*/
OP_CODE_IMAGE_SIZE_REQ = 7, /**< Value of the Op code field for 'Report received image size' command.*/
OP_CODE_PKT_RCPT_NOTIF_REQ = 8, /**< Value of the Op code field for 'Request packet receipt notification.*/
OP_CODE_RESPONSE = 16, /**< Value of the Op code field for 'Response.*/
OP_CODE_PKT_RCPT_NOTIF = 17 /**< Value of the Op code field for 'Packets Receipt Notification'.*/
};
static bool m_is_dfu_service_initialized = false; /**< Variable to check if the DFU service was initialized by the application.*/
static uint8_t m_notif_buffer[MAX_NOTIF_BUFFER_LEN]; /**< Buffer used for sending notifications to peer. */
/**@brief Function for adding DFU Packet characteristic to the BLE Stack.
*
* @param[in] p_dfu DFU Service structure.
*
* @return NRF_SUCCESS on success. Otherwise an error code.
*/
static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu)
{
ble_gatts_char_md_t char_md;
ble_gatts_attr_t attr_char_value;
ble_uuid_t char_uuid;
ble_gatts_attr_md_t attr_md;
memset(&char_md, 0, sizeof(char_md));
char_md.char_props.write_wo_resp = 1;
char_md.p_char_user_desc = NULL;
char_md.p_char_pf = NULL;
char_md.p_user_desc_md = NULL;
char_md.p_cccd_md = NULL;
char_md.p_sccd_md = NULL;
char_uuid.type = p_dfu->uuid_type;
char_uuid.uuid = BLE_DFU_PKT_CHAR_UUID;
memset(&attr_md, 0, sizeof(attr_md));
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = 0;
attr_md.wr_auth = 0;
attr_md.vlen = 1;
memset(&attr_char_value, 0, sizeof(attr_char_value));
attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = 0;
attr_char_value.init_offs = 0;
attr_char_value.max_len = MAX_DFU_PKT_LEN;
attr_char_value.p_value = NULL;
return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
&char_md,
&attr_char_value,
&p_dfu->dfu_pkt_handles);
}
/**@brief Function for adding DFU Revision characteristic to the BLE Stack.
*
* @param[in] p_dfu DFU Service structure.
*
* @return NRF_SUCCESS on success. Otherwise an error code.
*/
static uint32_t dfu_rev_char_add(ble_dfu_t * const p_dfu, ble_dfu_init_t const * const p_dfu_init)
{
ble_gatts_char_md_t char_md;
ble_gatts_attr_t attr_char_value;
ble_uuid_t char_uuid;
ble_gatts_attr_md_t attr_md;
memset(&char_md, 0, sizeof(char_md));
char_md.char_props.read = 1;
char_md.p_char_user_desc = NULL;
char_md.p_char_pf = NULL;
char_md.p_user_desc_md = NULL;
char_md.p_cccd_md = NULL;
char_md.p_sccd_md = NULL;
char_uuid.type = p_dfu->uuid_type;
char_uuid.uuid = BLE_DFU_REV_CHAR_UUID;
memset(&attr_md, 0, sizeof(attr_md));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = 0;
attr_md.wr_auth = 0;
attr_md.vlen = 1;
memset(&attr_char_value, 0, sizeof(attr_char_value));
attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = sizeof(uint16_t);
attr_char_value.init_offs = 0;
attr_char_value.max_len = sizeof(uint16_t);
attr_char_value.p_value = (uint8_t *)&p_dfu_init->revision;
return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
&char_md,
&attr_char_value,
&p_dfu->dfu_rev_handles);
}
/**@brief Function for adding DFU Control Point characteristic to the BLE Stack.
*
* @param[in] p_dfu DFU Service structure.
*
* @return NRF_SUCCESS on success. Otherwise an error code.
*/
static uint32_t dfu_ctrl_pt_add(ble_dfu_t * const p_dfu)
{
ble_gatts_char_md_t char_md;
ble_gatts_attr_t attr_char_value;
ble_uuid_t char_uuid;
ble_gatts_attr_md_t attr_md;
memset(&char_md, 0, sizeof(char_md));
char_md.char_props.write = 1;
char_md.char_props.notify = 1;
char_md.p_char_user_desc = NULL;
char_md.p_char_pf = NULL;
char_md.p_user_desc_md = NULL;
char_md.p_cccd_md = NULL;
char_md.p_sccd_md = NULL;
char_uuid.type = p_dfu->uuid_type;
char_uuid.uuid = BLE_DFU_CTRL_PT_UUID;
memset(&attr_md, 0, sizeof(attr_md));
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = 0;
attr_md.wr_auth = 1;
attr_md.vlen = 1;
memset(&attr_char_value, 0, sizeof(attr_char_value));
attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = 0;
attr_char_value.init_offs = 0;
attr_char_value.max_len = BLE_L2CAP_MTU_DEF;
attr_char_value.p_value = NULL;
return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
&char_md,
&attr_char_value,
&p_dfu->dfu_ctrl_pt_handles);
}
/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the S110 SoftDevice.
*
* @param[in] p_dfu DFU Service Structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_connect(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
{
p_dfu->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
}
/**@brief Function for checking if the CCCD of DFU Control point is configured for Notification.
*
* @details This function checks if the CCCD of DFU Control Point characteristic is configured
* for Notification by the DFU Controller.
*
* @param[in] p_dfu DFU Service structure.
*
* @return True if the CCCD of DFU Control Point characteristic is configured for Notification.
* False otherwise.
*/
static bool is_cccd_configured(ble_dfu_t * p_dfu)
{
// Check if the CCCDs are configured.
uint8_t cccd_val_buf[BLE_CCCD_VALUE_LEN];
ble_gatts_value_t gatts_value;
// Initialize value struct.
memset(&gatts_value, 0, sizeof(gatts_value));
gatts_value.len = BLE_CCCD_VALUE_LEN;
gatts_value.offset = 0;
gatts_value.p_value = cccd_val_buf;
// Check the CCCD Value of DFU Control Point.
uint32_t err_code = sd_ble_gatts_value_get(p_dfu->conn_handle,
p_dfu->dfu_ctrl_pt_handles.cccd_handle,
&gatts_value);
if (err_code != NRF_SUCCESS)
{
if (p_dfu->error_handler != NULL)
{
p_dfu->error_handler(err_code);
}
return false;
}
return ble_srv_is_notification_enabled(cccd_val_buf);
}
/**@brief Function for handling a Write event on the Control Point characteristic.
*
* @param[in] p_dfu DFU Service Structure.
* @param[in] p_ble_write_evt Pointer to the write event received from BLE stack.
*
* @return NRF_SUCCESS on successful processing of control point write. Otherwise an error code.
*/
static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t * p_ble_write_evt)
{
ble_gatts_rw_authorize_reply_params_t write_authorize_reply;
write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
if (!is_cccd_configured(p_dfu))
{
// Send an error response to the peer indicating that the CCCD is improperly configured.
write_authorize_reply.params.write.gatt_status =
BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR;
return (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply));
}
else
{
uint32_t err_code;
write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
err_code = (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply));
if (err_code != NRF_SUCCESS)
{
return err_code;
}
}
ble_dfu_evt_t ble_dfu_evt;
switch (p_ble_write_evt->data[0])
{
case OP_CODE_START_DFU:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_START;
if (p_ble_write_evt->len < PKT_START_DFU_PARAM_LEN)
{
return ble_dfu_response_send(p_dfu,
(ble_dfu_procedure_t) p_ble_write_evt->data[0],
BLE_DFU_RESP_VAL_OPER_FAILED);
}
ble_dfu_evt.evt.ble_dfu_pkt_write.len = 1;
ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]);
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_RECEIVE_INIT:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_INIT_DATA;
if (p_ble_write_evt->len < PKT_INIT_DFU_PARAM_LEN)
{
return ble_dfu_response_send(p_dfu,
(ble_dfu_procedure_t) p_ble_write_evt->data[0],
BLE_DFU_RESP_VAL_OPER_FAILED);
}
ble_dfu_evt.evt.ble_dfu_pkt_write.len = 1;
ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]);
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_RECEIVE_FW:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_APP_DATA;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_VALIDATE:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_VALIDATE;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_ACTIVATE_N_RESET:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_ACTIVATE_N_RESET;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_SYS_RESET:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_SYS_RESET;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_PKT_RCPT_NOTIF_REQ:
if (p_ble_write_evt->len < PKT_RCPT_NOTIF_REQ_LEN)
{
return (ble_dfu_response_send(p_dfu,
BLE_DFU_PKT_RCPT_REQ_PROCEDURE,
BLE_DFU_RESP_VAL_NOT_SUPPORTED));
}
ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts =
uint16_decode(&(p_ble_write_evt->data[1]));
if (ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts == 0)
{
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_DISABLED;
}
else
{
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_ENABLED;
}
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_IMAGE_SIZE_REQ:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_BYTES_RECEIVED_SEND;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
default:
// Unsupported op code.
return ble_dfu_response_send(p_dfu,
(ble_dfu_procedure_t) p_ble_write_evt->data[0],
BLE_DFU_RESP_VAL_NOT_SUPPORTED);
}
return NRF_SUCCESS;
}
/**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event from the S110
* Stack.
*
* @param[in] p_dfu DFU Service Structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_rw_authorize_req(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
{
ble_gatts_evt_rw_authorize_request_t * p_authorize_request;
p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request);
if (
(p_authorize_request->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
&&
(p_authorize_request->request.write.handle == p_dfu->dfu_ctrl_pt_handles.value_handle)
&&
(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ)
&&
(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW)
&&
(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)
)
{
uint32_t err_code;
err_code = on_ctrl_pt_write(p_dfu, &(p_authorize_request->request.write));
if (err_code != NRF_SUCCESS && p_dfu->error_handler != NULL)
{
p_dfu->error_handler(err_code);
}
}
}
/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the S110 SoftDevice.
*
* @param[in] p_dfu DFU Service Structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_write(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
{
if (p_ble_evt->evt.gatts_evt.params.write.handle == p_dfu->dfu_pkt_handles.value_handle)
{
// DFU Packet written
ble_dfu_evt_t ble_dfu_evt;
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PACKET_WRITE;
ble_dfu_evt.evt.ble_dfu_pkt_write.len = p_ble_evt->evt.gatts_evt.params.write.len;
ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = p_ble_evt->evt.gatts_evt.params.write.data;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
}
}
/**@brief Function for handling the BLE_GAP_EVT_DISCONNECTED event from the S110 SoftDevice.
*
* @param[in] p_dfu DFU Service Structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_disconnect(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
{
p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID;
}
uint32_t ble_dfu_init(ble_dfu_t * p_dfu, ble_dfu_init_t * p_dfu_init)
{
if ((p_dfu == NULL) || (p_dfu_init == NULL) || (p_dfu_init->evt_handler == NULL))
{
return NRF_ERROR_NULL;
}
p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID;
ble_uuid_t service_uuid;
uint32_t err_code;
const ble_uuid128_t base_uuid128 =
{
{
0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00
}
};
service_uuid.uuid = BLE_DFU_SERVICE_UUID;
err_code = sd_ble_uuid_vs_add(&base_uuid128, &(service_uuid.type));
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
&service_uuid,
&(p_dfu->service_handle));
if (err_code != NRF_SUCCESS)
{
return err_code;
}
p_dfu->uuid_type = service_uuid.type;
err_code = dfu_pkt_char_add(p_dfu);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = dfu_ctrl_pt_add(p_dfu);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = dfu_rev_char_add(p_dfu, p_dfu_init);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
p_dfu->evt_handler = p_dfu_init->evt_handler;
if (p_dfu_init->error_handler != NULL)
{
p_dfu->error_handler = p_dfu_init->error_handler;