No changes

Fork of nRF51822 by Nordic Semiconductor

Committer:
vcoubard
Date:
Mon Jan 11 10:19:15 2016 +0000
Revision:
561:613dbbdeed27
Parent:
553:2a413611e569
Child:
563:9c4b96f7be8d
Synchronized with git rev 7bf81e7e
Author: Andres Amaya Garcia
Improve shutdown to clear BLE API and not just SD

Improve the shutdown functionality, such that a call to ble.shutdown() from
the user application clears the API and nRF5x state and NOT only the
SoftDevice. To achieve this the following changes are introduced:

* Add a protected member cleanup() to nRF5xGap, nRF5xGattClient,
nRF5xGattServer, nRF5xSecurityManager and nRF5xServiceDiscovery.
* Modify the shutdown() implementation in nRF5xn such that it also calls the
static member shutdown() exposed by the BLE API in Gap.h, SecurityManager.h,
GattClient.h and GattServer.h.
* Modify nRF5xGattClient, nRF5xGattServer and nRF5xSecurityManager
classes so that they dynamically create their respective objects only if
needed. Previously the GattClient, GattServer and SecurityManager objects were
declared as static, which means that they were always present even though they
were not always needed. This increases memory consumption unnecessarily.
Furthermore, pointers to the object instances are stored in static members of
the classes as specified by the BLE API base classes. This ensures that
calls to shutdown do not require calls to getInstance() functions that would
otherwise result in undesired memory allocations.
* nRF5xGap object is always needed, so this remains allocated statically. But
the reference in Gap is pointed to this object.

The shutdown procedure is as follows:

1. The user calls ble.shutdown() which executes the code in nRF5xn::shutdown()
1. The SoftDevice is shutdown
1. The static members of Gap.h, SecurityManager.h, GattClient.h and
GattServer.h are called to clean up their own state.

If at any point an error occur during the last step, BLE_ERROR_INVALID_STATE is
returned.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vcoubard 541:884f95bf5351 1 /* mbed Microcontroller Library
vcoubard 541:884f95bf5351 2 * Copyright (c) 2006-2013 ARM Limited
vcoubard 541:884f95bf5351 3 *
vcoubard 541:884f95bf5351 4 * Licensed under the Apache License, Version 2.0 (the "License");
vcoubard 541:884f95bf5351 5 * you may not use this file except in compliance with the License.
vcoubard 541:884f95bf5351 6 * You may obtain a copy of the License at
vcoubard 541:884f95bf5351 7 *
vcoubard 541:884f95bf5351 8 * http://www.apache.org/licenses/LICENSE-2.0
vcoubard 541:884f95bf5351 9 *
vcoubard 541:884f95bf5351 10 * Unless required by applicable law or agreed to in writing, software
vcoubard 541:884f95bf5351 11 * distributed under the License is distributed on an "AS IS" BASIS,
vcoubard 541:884f95bf5351 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
vcoubard 541:884f95bf5351 13 * See the License for the specific language governing permissions and
vcoubard 541:884f95bf5351 14 * limitations under the License.
vcoubard 541:884f95bf5351 15 */
vcoubard 541:884f95bf5351 16
vcoubard 541:884f95bf5351 17 #include "nRF5xGattServer.h"
vcoubard 541:884f95bf5351 18 #include "mbed.h"
vcoubard 541:884f95bf5351 19
vcoubard 541:884f95bf5351 20 #include "common/common.h"
vcoubard 541:884f95bf5351 21 #include "btle/custom/custom_helper.h"
vcoubard 541:884f95bf5351 22
vcoubard 541:884f95bf5351 23 #include "nRF5xGap.h"
vcoubard 541:884f95bf5351 24
vcoubard 541:884f95bf5351 25 nRF5xGattServer &nRF5xGattServer::getInstance(void) {
vcoubard 561:613dbbdeed27 26 if (gattServerInstance == NULL) {
vcoubard 561:613dbbdeed27 27 gattServerInstance = new nRF5xGattServer();
vcoubard 561:613dbbdeed27 28 }
vcoubard 561:613dbbdeed27 29 return (nRF5xGattServer &) *gattServerInstance;
vcoubard 541:884f95bf5351 30 }
vcoubard 541:884f95bf5351 31
vcoubard 541:884f95bf5351 32 /**************************************************************************/
vcoubard 541:884f95bf5351 33 /*!
vcoubard 541:884f95bf5351 34 @brief Adds a new service to the GATT table on the peripheral
vcoubard 541:884f95bf5351 35
vcoubard 541:884f95bf5351 36 @returns ble_error_t
vcoubard 541:884f95bf5351 37
vcoubard 541:884f95bf5351 38 @retval BLE_ERROR_NONE
vcoubard 541:884f95bf5351 39 Everything executed properly
vcoubard 541:884f95bf5351 40
vcoubard 541:884f95bf5351 41 @section EXAMPLE
vcoubard 541:884f95bf5351 42
vcoubard 541:884f95bf5351 43 @code
vcoubard 541:884f95bf5351 44
vcoubard 541:884f95bf5351 45 @endcode
vcoubard 541:884f95bf5351 46 */
vcoubard 541:884f95bf5351 47 /**************************************************************************/
vcoubard 541:884f95bf5351 48 ble_error_t nRF5xGattServer::addService(GattService &service)
vcoubard 541:884f95bf5351 49 {
vcoubard 541:884f95bf5351 50 /* ToDo: Make sure this service UUID doesn't already exist (?) */
vcoubard 541:884f95bf5351 51 /* ToDo: Basic validation */
vcoubard 541:884f95bf5351 52
vcoubard 541:884f95bf5351 53 /* Add the service to the nRF51 */
vcoubard 541:884f95bf5351 54 ble_uuid_t nordicUUID;
vcoubard 541:884f95bf5351 55 nordicUUID = custom_convert_to_nordic_uuid(service.getUUID());
vcoubard 541:884f95bf5351 56
vcoubard 541:884f95bf5351 57 uint16_t serviceHandle;
vcoubard 541:884f95bf5351 58 ASSERT( ERROR_NONE ==
vcoubard 541:884f95bf5351 59 sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
vcoubard 541:884f95bf5351 60 &nordicUUID,
vcoubard 541:884f95bf5351 61 &serviceHandle),
vcoubard 541:884f95bf5351 62 BLE_ERROR_PARAM_OUT_OF_RANGE );
vcoubard 541:884f95bf5351 63 service.setHandle(serviceHandle);
vcoubard 541:884f95bf5351 64
vcoubard 541:884f95bf5351 65 /* Add characteristics to the service */
vcoubard 541:884f95bf5351 66 for (uint8_t i = 0; i < service.getCharacteristicCount(); i++) {
vcoubard 541:884f95bf5351 67 if (characteristicCount >= BLE_TOTAL_CHARACTERISTICS) {
vcoubard 541:884f95bf5351 68 return BLE_ERROR_NO_MEM;
vcoubard 541:884f95bf5351 69 }
vcoubard 541:884f95bf5351 70 GattCharacteristic *p_char = service.getCharacteristic(i);
vcoubard 541:884f95bf5351 71
vcoubard 541:884f95bf5351 72 /* Skip any incompletely defined, read-only characteristics. */
vcoubard 541:884f95bf5351 73 if ((p_char->getValueAttribute().getValuePtr() == NULL) &&
vcoubard 552:20b282c26f96 74 (p_char->getValueAttribute().getLength() == 0) &&
vcoubard 541:884f95bf5351 75 (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) {
vcoubard 541:884f95bf5351 76 continue;
vcoubard 541:884f95bf5351 77 }
vcoubard 541:884f95bf5351 78
vcoubard 541:884f95bf5351 79 nordicUUID = custom_convert_to_nordic_uuid(p_char->getValueAttribute().getUUID());
vcoubard 541:884f95bf5351 80
vcoubard 541:884f95bf5351 81 /* The user-description descriptor is a special case which needs to be
vcoubard 541:884f95bf5351 82 * handled at the time of adding the characteristic. The following block
vcoubard 541:884f95bf5351 83 * is meant to discover its presence. */
vcoubard 541:884f95bf5351 84 const uint8_t *userDescriptionDescriptorValuePtr = NULL;
vcoubard 541:884f95bf5351 85 uint16_t userDescriptionDescriptorValueLen = 0;
vcoubard 541:884f95bf5351 86 for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) {
vcoubard 541:884f95bf5351 87 GattAttribute *p_desc = p_char->getDescriptor(j);
vcoubard 541:884f95bf5351 88 if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) {
vcoubard 541:884f95bf5351 89 userDescriptionDescriptorValuePtr = p_desc->getValuePtr();
vcoubard 541:884f95bf5351 90 userDescriptionDescriptorValueLen = p_desc->getLength();
vcoubard 541:884f95bf5351 91 }
vcoubard 541:884f95bf5351 92 }
vcoubard 541:884f95bf5351 93
vcoubard 541:884f95bf5351 94 ASSERT ( ERROR_NONE ==
vcoubard 541:884f95bf5351 95 custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID,
vcoubard 541:884f95bf5351 96 &nordicUUID,
vcoubard 541:884f95bf5351 97 p_char->getProperties(),
vcoubard 541:884f95bf5351 98 p_char->getRequiredSecurity(),
vcoubard 541:884f95bf5351 99 p_char->getValueAttribute().getValuePtr(),
vcoubard 552:20b282c26f96 100 p_char->getValueAttribute().getLength(),
vcoubard 541:884f95bf5351 101 p_char->getValueAttribute().getMaxLength(),
vcoubard 553:2a413611e569 102 p_char->getValueAttribute().hasVariableLength(),
vcoubard 541:884f95bf5351 103 userDescriptionDescriptorValuePtr,
vcoubard 541:884f95bf5351 104 userDescriptionDescriptorValueLen,
vcoubard 541:884f95bf5351 105 p_char->isReadAuthorizationEnabled(),
vcoubard 541:884f95bf5351 106 p_char->isWriteAuthorizationEnabled(),
vcoubard 541:884f95bf5351 107 &nrfCharacteristicHandles[characteristicCount]),
vcoubard 541:884f95bf5351 108 BLE_ERROR_PARAM_OUT_OF_RANGE );
vcoubard 541:884f95bf5351 109
vcoubard 541:884f95bf5351 110 /* Update the characteristic handle */
vcoubard 541:884f95bf5351 111 p_characteristics[characteristicCount] = p_char;
vcoubard 541:884f95bf5351 112 p_char->getValueAttribute().setHandle(nrfCharacteristicHandles[characteristicCount].value_handle);
vcoubard 541:884f95bf5351 113 characteristicCount++;
vcoubard 541:884f95bf5351 114
vcoubard 541:884f95bf5351 115 /* Add optional descriptors if any */
vcoubard 541:884f95bf5351 116 for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) {
vcoubard 541:884f95bf5351 117 if (descriptorCount >= BLE_TOTAL_DESCRIPTORS) {
vcoubard 541:884f95bf5351 118 return BLE_ERROR_NO_MEM;
vcoubard 541:884f95bf5351 119 }
vcoubard 541:884f95bf5351 120
vcoubard 541:884f95bf5351 121 GattAttribute *p_desc = p_char->getDescriptor(j);
vcoubard 541:884f95bf5351 122 /* skip the user-description-descriptor here; this has already been handled when adding the characteristic (above). */
vcoubard 541:884f95bf5351 123 if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) {
vcoubard 541:884f95bf5351 124 continue;
vcoubard 541:884f95bf5351 125 }
vcoubard 541:884f95bf5351 126
vcoubard 541:884f95bf5351 127 nordicUUID = custom_convert_to_nordic_uuid(p_desc->getUUID());
vcoubard 541:884f95bf5351 128
vcoubard 541:884f95bf5351 129 ASSERT(ERROR_NONE ==
vcoubard 541:884f95bf5351 130 custom_add_in_descriptor(BLE_GATT_HANDLE_INVALID,
vcoubard 541:884f95bf5351 131 &nordicUUID,
vcoubard 541:884f95bf5351 132 p_desc->getValuePtr(),
vcoubard 552:20b282c26f96 133 p_desc->getLength(),
vcoubard 541:884f95bf5351 134 p_desc->getMaxLength(),
vcoubard 553:2a413611e569 135 p_desc->hasVariableLength(),
vcoubard 541:884f95bf5351 136 &nrfDescriptorHandles[descriptorCount]),
vcoubard 541:884f95bf5351 137 BLE_ERROR_PARAM_OUT_OF_RANGE);
vcoubard 541:884f95bf5351 138
vcoubard 541:884f95bf5351 139 p_descriptors[descriptorCount++] = p_desc;
vcoubard 541:884f95bf5351 140 p_desc->setHandle(nrfDescriptorHandles[descriptorCount]);
vcoubard 541:884f95bf5351 141 }
vcoubard 541:884f95bf5351 142 }
vcoubard 541:884f95bf5351 143
vcoubard 541:884f95bf5351 144 serviceCount++;
vcoubard 541:884f95bf5351 145
vcoubard 541:884f95bf5351 146 return BLE_ERROR_NONE;
vcoubard 541:884f95bf5351 147 }
vcoubard 541:884f95bf5351 148
vcoubard 541:884f95bf5351 149 /**************************************************************************/
vcoubard 541:884f95bf5351 150 /*!
vcoubard 541:884f95bf5351 151 @brief Reads the value of a characteristic, based on the service
vcoubard 541:884f95bf5351 152 and characteristic index fields
vcoubard 541:884f95bf5351 153
vcoubard 541:884f95bf5351 154 @param[in] attributeHandle
vcoubard 541:884f95bf5351 155 The handle of the GattCharacteristic to read from
vcoubard 541:884f95bf5351 156 @param[in] buffer
vcoubard 541:884f95bf5351 157 Buffer to hold the the characteristic's value
vcoubard 541:884f95bf5351 158 (raw byte array in LSB format)
vcoubard 541:884f95bf5351 159 @param[in/out] len
vcoubard 541:884f95bf5351 160 input: Length in bytes to be read.
vcoubard 541:884f95bf5351 161 output: Total length of attribute value upon successful return.
vcoubard 541:884f95bf5351 162
vcoubard 541:884f95bf5351 163 @returns ble_error_t
vcoubard 541:884f95bf5351 164
vcoubard 541:884f95bf5351 165 @retval BLE_ERROR_NONE
vcoubard 541:884f95bf5351 166 Everything executed properly
vcoubard 541:884f95bf5351 167 */
vcoubard 541:884f95bf5351 168 /**************************************************************************/
vcoubard 541:884f95bf5351 169 ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
vcoubard 541:884f95bf5351 170 {
vcoubard 541:884f95bf5351 171 return read(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP);
vcoubard 541:884f95bf5351 172 }
vcoubard 541:884f95bf5351 173
vcoubard 541:884f95bf5351 174 ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
vcoubard 541:884f95bf5351 175 {
vcoubard 541:884f95bf5351 176 ble_gatts_value_t value = {
vcoubard 541:884f95bf5351 177 .len = *lengthP,
vcoubard 541:884f95bf5351 178 .offset = 0,
vcoubard 541:884f95bf5351 179 .p_value = buffer,
vcoubard 541:884f95bf5351 180 };
vcoubard 541:884f95bf5351 181
vcoubard 541:884f95bf5351 182 ASSERT( ERROR_NONE ==
vcoubard 541:884f95bf5351 183 sd_ble_gatts_value_get(connectionHandle, attributeHandle, &value),
vcoubard 541:884f95bf5351 184 BLE_ERROR_PARAM_OUT_OF_RANGE);
vcoubard 541:884f95bf5351 185 *lengthP = value.len;
vcoubard 541:884f95bf5351 186
vcoubard 541:884f95bf5351 187 return BLE_ERROR_NONE;
vcoubard 541:884f95bf5351 188 }
vcoubard 541:884f95bf5351 189
vcoubard 541:884f95bf5351 190 /**************************************************************************/
vcoubard 541:884f95bf5351 191 /*!
vcoubard 541:884f95bf5351 192 @brief Updates the value of a characteristic, based on the service
vcoubard 541:884f95bf5351 193 and characteristic index fields
vcoubard 541:884f95bf5351 194
vcoubard 541:884f95bf5351 195 @param[in] charHandle
vcoubard 541:884f95bf5351 196 The handle of the GattCharacteristic to write to
vcoubard 541:884f95bf5351 197 @param[in] buffer
vcoubard 541:884f95bf5351 198 Data to use when updating the characteristic's value
vcoubard 541:884f95bf5351 199 (raw byte array in LSB format)
vcoubard 541:884f95bf5351 200 @param[in] len
vcoubard 541:884f95bf5351 201 The number of bytes in buffer
vcoubard 541:884f95bf5351 202
vcoubard 541:884f95bf5351 203 @returns ble_error_t
vcoubard 541:884f95bf5351 204
vcoubard 541:884f95bf5351 205 @retval BLE_ERROR_NONE
vcoubard 541:884f95bf5351 206 Everything executed properly
vcoubard 541:884f95bf5351 207 */
vcoubard 541:884f95bf5351 208 /**************************************************************************/
vcoubard 541:884f95bf5351 209 ble_error_t nRF5xGattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
vcoubard 541:884f95bf5351 210 {
vcoubard 541:884f95bf5351 211 return write(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, len, localOnly);
vcoubard 541:884f95bf5351 212 }
vcoubard 541:884f95bf5351 213
vcoubard 541:884f95bf5351 214 ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
vcoubard 541:884f95bf5351 215 {
vcoubard 541:884f95bf5351 216 ble_error_t returnValue = BLE_ERROR_NONE;
vcoubard 541:884f95bf5351 217
vcoubard 541:884f95bf5351 218 ble_gatts_value_t value = {
vcoubard 541:884f95bf5351 219 .len = len,
vcoubard 541:884f95bf5351 220 .offset = 0,
vcoubard 541:884f95bf5351 221 .p_value = const_cast<uint8_t *>(buffer),
vcoubard 541:884f95bf5351 222 };
vcoubard 541:884f95bf5351 223
vcoubard 541:884f95bf5351 224 if (localOnly) {
vcoubard 541:884f95bf5351 225 /* Only update locally regardless of notify/indicate */
vcoubard 541:884f95bf5351 226 ASSERT_INT( ERROR_NONE,
vcoubard 541:884f95bf5351 227 sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
vcoubard 541:884f95bf5351 228 BLE_ERROR_PARAM_OUT_OF_RANGE );
vcoubard 541:884f95bf5351 229 return BLE_ERROR_NONE;
vcoubard 541:884f95bf5351 230 }
vcoubard 541:884f95bf5351 231
vcoubard 541:884f95bf5351 232 int characteristicIndex = resolveValueHandleToCharIndex(attributeHandle);
vcoubard 541:884f95bf5351 233 if ((characteristicIndex != -1) &&
vcoubard 541:884f95bf5351 234 (p_characteristics[characteristicIndex]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) {
vcoubard 541:884f95bf5351 235 /* HVX update for the characteristic value */
vcoubard 541:884f95bf5351 236 ble_gatts_hvx_params_t hvx_params;
vcoubard 541:884f95bf5351 237
vcoubard 541:884f95bf5351 238 hvx_params.handle = attributeHandle;
vcoubard 541:884f95bf5351 239 hvx_params.type =
vcoubard 541:884f95bf5351 240 (p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION;
vcoubard 541:884f95bf5351 241 hvx_params.offset = 0;
vcoubard 541:884f95bf5351 242 hvx_params.p_data = const_cast<uint8_t *>(buffer);
vcoubard 541:884f95bf5351 243 hvx_params.p_len = &len;
vcoubard 541:884f95bf5351 244
vcoubard 541:884f95bf5351 245 if (connectionHandle == BLE_CONN_HANDLE_INVALID) { /* use the default connection handle if the caller hasn't specified a valid connectionHandle. */
vcoubard 541:884f95bf5351 246 connectionHandle = nRF5xGap::getInstance().getConnectionHandle();
vcoubard 541:884f95bf5351 247 }
vcoubard 541:884f95bf5351 248 error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params);
vcoubard 541:884f95bf5351 249 if (error != ERROR_NONE) {
vcoubard 541:884f95bf5351 250 switch (error) {
vcoubard 541:884f95bf5351 251 case ERROR_BLE_NO_TX_BUFFERS: /* Notifications consume application buffers. The return value can be used for resending notifications. */
vcoubard 541:884f95bf5351 252 case ERROR_BUSY:
vcoubard 541:884f95bf5351 253 returnValue = BLE_STACK_BUSY;
vcoubard 541:884f95bf5351 254 break;
vcoubard 541:884f95bf5351 255
vcoubard 541:884f95bf5351 256 case ERROR_INVALID_STATE:
vcoubard 541:884f95bf5351 257 case ERROR_BLEGATTS_SYS_ATTR_MISSING:
vcoubard 541:884f95bf5351 258 returnValue = BLE_ERROR_INVALID_STATE;
vcoubard 541:884f95bf5351 259 break;
vcoubard 541:884f95bf5351 260
vcoubard 541:884f95bf5351 261 default :
vcoubard 541:884f95bf5351 262 ASSERT_INT( ERROR_NONE,
vcoubard 541:884f95bf5351 263 sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
vcoubard 541:884f95bf5351 264 BLE_ERROR_PARAM_OUT_OF_RANGE );
vcoubard 541:884f95bf5351 265
vcoubard 541:884f95bf5351 266 /* Notifications consume application buffers. The return value can
vcoubard 541:884f95bf5351 267 * be used for resending notifications. */
vcoubard 541:884f95bf5351 268 returnValue = BLE_STACK_BUSY;
vcoubard 541:884f95bf5351 269 break;
vcoubard 541:884f95bf5351 270 }
vcoubard 541:884f95bf5351 271 }
vcoubard 541:884f95bf5351 272 } else {
vcoubard 541:884f95bf5351 273 returnValue = BLE_ERROR_INVALID_STATE; // if assert is not used
vcoubard 541:884f95bf5351 274 ASSERT_INT( ERROR_NONE,
vcoubard 541:884f95bf5351 275 sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
vcoubard 541:884f95bf5351 276 BLE_ERROR_PARAM_OUT_OF_RANGE );
vcoubard 541:884f95bf5351 277 }
vcoubard 541:884f95bf5351 278
vcoubard 541:884f95bf5351 279 return returnValue;
vcoubard 541:884f95bf5351 280 }
vcoubard 541:884f95bf5351 281
vcoubard 541:884f95bf5351 282 ble_error_t nRF5xGattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP)
vcoubard 541:884f95bf5351 283 {
vcoubard 541:884f95bf5351 284 /* Forward the call with the default connection handle. */
vcoubard 541:884f95bf5351 285 return areUpdatesEnabled(nRF5xGap::getInstance().getConnectionHandle(), characteristic, enabledP);
vcoubard 541:884f95bf5351 286 }
vcoubard 541:884f95bf5351 287
vcoubard 541:884f95bf5351 288 ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP)
vcoubard 541:884f95bf5351 289 {
vcoubard 541:884f95bf5351 290 int characteristicIndex = resolveValueHandleToCharIndex(characteristic.getValueHandle());
vcoubard 541:884f95bf5351 291 if (characteristicIndex == -1) {
vcoubard 541:884f95bf5351 292 return BLE_ERROR_INVALID_PARAM;
vcoubard 541:884f95bf5351 293 }
vcoubard 541:884f95bf5351 294
vcoubard 541:884f95bf5351 295 /* Read the cccd value from the GATT server. */
vcoubard 541:884f95bf5351 296 GattAttribute::Handle_t cccdHandle = nrfCharacteristicHandles[characteristicIndex].cccd_handle;
vcoubard 541:884f95bf5351 297 uint16_t cccdValue;
vcoubard 541:884f95bf5351 298 uint16_t length = sizeof(cccdValue);
vcoubard 541:884f95bf5351 299 ble_error_t rc = read(connectionHandle, cccdHandle, reinterpret_cast<uint8_t *>(&cccdValue), &length);
vcoubard 541:884f95bf5351 300 if (rc != BLE_ERROR_NONE) {
vcoubard 541:884f95bf5351 301 return rc;
vcoubard 541:884f95bf5351 302 }
vcoubard 541:884f95bf5351 303 if (length != sizeof(cccdValue)) {
vcoubard 541:884f95bf5351 304 return BLE_ERROR_INVALID_STATE;
vcoubard 541:884f95bf5351 305 }
vcoubard 541:884f95bf5351 306
vcoubard 541:884f95bf5351 307 /* Check for NOTFICATION or INDICATION in CCCD. */
vcoubard 541:884f95bf5351 308 if ((cccdValue & BLE_GATT_HVX_NOTIFICATION) || (cccdValue & BLE_GATT_HVX_INDICATION)) {
vcoubard 541:884f95bf5351 309 *enabledP = true;
vcoubard 541:884f95bf5351 310 }
vcoubard 541:884f95bf5351 311
vcoubard 541:884f95bf5351 312 return BLE_ERROR_NONE;
vcoubard 541:884f95bf5351 313 }
vcoubard 541:884f95bf5351 314
vcoubard 541:884f95bf5351 315 /**************************************************************************/
vcoubard 541:884f95bf5351 316 /*!
vcoubard 561:613dbbdeed27 317 @brief Clear nRF5xGattServer's state.
vcoubard 561:613dbbdeed27 318
vcoubard 561:613dbbdeed27 319 @returns ble_error_t
vcoubard 561:613dbbdeed27 320
vcoubard 561:613dbbdeed27 321 @retval BLE_ERROR_NONE
vcoubard 561:613dbbdeed27 322 Everything executed properly
vcoubard 561:613dbbdeed27 323 */
vcoubard 561:613dbbdeed27 324 /**************************************************************************/
vcoubard 561:613dbbdeed27 325 ble_error_t nRF5xGattServer::cleanup(void)
vcoubard 561:613dbbdeed27 326 {
vcoubard 561:613dbbdeed27 327 /* Clear all state that is from the parent, including private members */
vcoubard 561:613dbbdeed27 328 if (GattServer::cleanup() != BLE_ERROR_NONE) {
vcoubard 561:613dbbdeed27 329 return BLE_ERROR_INVALID_STATE;
vcoubard 561:613dbbdeed27 330 }
vcoubard 561:613dbbdeed27 331
vcoubard 561:613dbbdeed27 332 /* Clear derived class members */
vcoubard 561:613dbbdeed27 333 memset(p_characteristics, 0, sizeof(p_characteristics));
vcoubard 561:613dbbdeed27 334 memset(p_descriptors, 0, sizeof(p_descriptors));
vcoubard 561:613dbbdeed27 335 memset(nrfCharacteristicHandles, 0, sizeof(ble_gatts_char_handles_t));
vcoubard 561:613dbbdeed27 336 memset(nrfDescriptorHandles, 0, sizeof(nrfDescriptorHandles));
vcoubard 561:613dbbdeed27 337 descriptorCount = 0;
vcoubard 561:613dbbdeed27 338
vcoubard 561:613dbbdeed27 339 return BLE_ERROR_NONE;
vcoubard 561:613dbbdeed27 340 }
vcoubard 561:613dbbdeed27 341
vcoubard 561:613dbbdeed27 342 /**************************************************************************/
vcoubard 561:613dbbdeed27 343 /*!
vcoubard 541:884f95bf5351 344 @brief Callback handler for events getting pushed up from the SD
vcoubard 541:884f95bf5351 345 */
vcoubard 541:884f95bf5351 346 /**************************************************************************/
vcoubard 541:884f95bf5351 347 void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt)
vcoubard 541:884f95bf5351 348 {
vcoubard 541:884f95bf5351 349 GattAttribute::Handle_t handle_value;
vcoubard 541:884f95bf5351 350 GattServerEvents::gattEvent_t eventType;
vcoubard 541:884f95bf5351 351 const ble_gatts_evt_t *gattsEventP = &p_ble_evt->evt.gatts_evt;
vcoubard 541:884f95bf5351 352
vcoubard 541:884f95bf5351 353 switch (p_ble_evt->header.evt_id) {
vcoubard 541:884f95bf5351 354 case BLE_GATTS_EVT_WRITE: {
vcoubard 541:884f95bf5351 355 /* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */
vcoubard 541:884f95bf5351 356
vcoubard 541:884f95bf5351 357 /* 1.) Handle CCCD changes */
vcoubard 541:884f95bf5351 358 handle_value = gattsEventP->params.write.handle;
vcoubard 541:884f95bf5351 359 int characteristicIndex = resolveCCCDHandleToCharIndex(handle_value);
vcoubard 541:884f95bf5351 360 if ((characteristicIndex != -1) &&
vcoubard 541:884f95bf5351 361 (p_characteristics[characteristicIndex]->getProperties() &
vcoubard 541:884f95bf5351 362 (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) {
vcoubard 541:884f95bf5351 363
vcoubard 541:884f95bf5351 364 uint16_t cccd_value = (gattsEventP->params.write.data[1] << 8) | gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */
vcoubard 541:884f95bf5351 365
vcoubard 541:884f95bf5351 366 if (((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) ||
vcoubard 541:884f95bf5351 367 ((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) {
vcoubard 541:884f95bf5351 368 eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
vcoubard 541:884f95bf5351 369 } else {
vcoubard 541:884f95bf5351 370 eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
vcoubard 541:884f95bf5351 371 }
vcoubard 541:884f95bf5351 372
vcoubard 541:884f95bf5351 373 handleEvent(eventType, p_characteristics[characteristicIndex]->getValueHandle());
vcoubard 541:884f95bf5351 374 return;
vcoubard 541:884f95bf5351 375 }
vcoubard 541:884f95bf5351 376
vcoubard 541:884f95bf5351 377 /* 2.) Changes to the characteristic value will be handled with other events below */
vcoubard 541:884f95bf5351 378 eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
vcoubard 541:884f95bf5351 379 }
vcoubard 541:884f95bf5351 380 break;
vcoubard 541:884f95bf5351 381
vcoubard 541:884f95bf5351 382 case BLE_GATTS_EVT_HVC:
vcoubard 541:884f95bf5351 383 /* Indication confirmation received */
vcoubard 541:884f95bf5351 384 eventType = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED;
vcoubard 541:884f95bf5351 385 handle_value = gattsEventP->params.hvc.handle;
vcoubard 541:884f95bf5351 386 break;
vcoubard 541:884f95bf5351 387
vcoubard 541:884f95bf5351 388 case BLE_EVT_TX_COMPLETE: {
vcoubard 541:884f95bf5351 389 handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count);
vcoubard 541:884f95bf5351 390 return;
vcoubard 541:884f95bf5351 391 }
vcoubard 541:884f95bf5351 392
vcoubard 541:884f95bf5351 393 case BLE_GATTS_EVT_SYS_ATTR_MISSING:
vcoubard 541:884f95bf5351 394 sd_ble_gatts_sys_attr_set(gattsEventP->conn_handle, NULL, 0, 0);
vcoubard 541:884f95bf5351 395 return;
vcoubard 541:884f95bf5351 396
vcoubard 541:884f95bf5351 397 case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
vcoubard 541:884f95bf5351 398 switch (gattsEventP->params.authorize_request.type) {
vcoubard 541:884f95bf5351 399 case BLE_GATTS_AUTHORIZE_TYPE_READ:
vcoubard 541:884f95bf5351 400 eventType = GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ;
vcoubard 541:884f95bf5351 401 handle_value = gattsEventP->params.authorize_request.request.read.handle;
vcoubard 541:884f95bf5351 402 break;
vcoubard 541:884f95bf5351 403 case BLE_GATTS_AUTHORIZE_TYPE_WRITE:
vcoubard 541:884f95bf5351 404 eventType = GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ;
vcoubard 541:884f95bf5351 405 handle_value = gattsEventP->params.authorize_request.request.write.handle;
vcoubard 541:884f95bf5351 406 break;
vcoubard 541:884f95bf5351 407 default:
vcoubard 541:884f95bf5351 408 return;
vcoubard 541:884f95bf5351 409 }
vcoubard 541:884f95bf5351 410 break;
vcoubard 541:884f95bf5351 411
vcoubard 541:884f95bf5351 412 default:
vcoubard 541:884f95bf5351 413 return;
vcoubard 541:884f95bf5351 414 }
vcoubard 541:884f95bf5351 415
vcoubard 541:884f95bf5351 416 int characteristicIndex = resolveValueHandleToCharIndex(handle_value);
vcoubard 541:884f95bf5351 417 if (characteristicIndex == -1) {
vcoubard 541:884f95bf5351 418 return;
vcoubard 541:884f95bf5351 419 }
vcoubard 541:884f95bf5351 420
vcoubard 541:884f95bf5351 421 /* Find index (charHandle) in the pool */
vcoubard 541:884f95bf5351 422 switch (eventType) {
vcoubard 541:884f95bf5351 423 case GattServerEvents::GATT_EVENT_DATA_WRITTEN: {
vcoubard 541:884f95bf5351 424 GattWriteCallbackParams cbParams = {
vcoubard 541:884f95bf5351 425 .connHandle = gattsEventP->conn_handle,
vcoubard 541:884f95bf5351 426 .handle = handle_value,
vcoubard 541:884f95bf5351 427 .writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.write.op),
vcoubard 541:884f95bf5351 428 .offset = gattsEventP->params.write.offset,
vcoubard 541:884f95bf5351 429 .len = gattsEventP->params.write.len,
vcoubard 541:884f95bf5351 430 .data = gattsEventP->params.write.data
vcoubard 541:884f95bf5351 431 };
vcoubard 541:884f95bf5351 432 handleDataWrittenEvent(&cbParams);
vcoubard 541:884f95bf5351 433 break;
vcoubard 541:884f95bf5351 434 }
vcoubard 541:884f95bf5351 435 case GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ: {
vcoubard 541:884f95bf5351 436 GattWriteAuthCallbackParams cbParams = {
vcoubard 541:884f95bf5351 437 .connHandle = gattsEventP->conn_handle,
vcoubard 541:884f95bf5351 438 .handle = handle_value,
vcoubard 541:884f95bf5351 439 .offset = gattsEventP->params.authorize_request.request.write.offset,
vcoubard 541:884f95bf5351 440 .len = gattsEventP->params.authorize_request.request.write.len,
vcoubard 541:884f95bf5351 441 .data = gattsEventP->params.authorize_request.request.write.data,
vcoubard 541:884f95bf5351 442 .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member
vcoubard 541:884f95bf5351 443 * set to AUTH_CALLBACK_REPLY_SUCCESS if the client
vcoubard 541:884f95bf5351 444 * request is to proceed. */
vcoubard 541:884f95bf5351 445 };
vcoubard 541:884f95bf5351 446 ble_gatts_rw_authorize_reply_params_t reply = {
vcoubard 541:884f95bf5351 447 .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
vcoubard 541:884f95bf5351 448 .params = {
vcoubard 541:884f95bf5351 449 .write = {
vcoubard 541:884f95bf5351 450 .gatt_status = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams)
vcoubard 541:884f95bf5351 451 }
vcoubard 541:884f95bf5351 452 }
vcoubard 541:884f95bf5351 453 };
vcoubard 541:884f95bf5351 454 sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply);
vcoubard 541:884f95bf5351 455
vcoubard 541:884f95bf5351 456 /*
vcoubard 541:884f95bf5351 457 * If write-authorization is enabled for a characteristic,
vcoubard 541:884f95bf5351 458 * AUTHORIZATION_REQ event (if replied with true) is *not*
vcoubard 541:884f95bf5351 459 * followed by another DATA_WRITTEN event; so we still need
vcoubard 541:884f95bf5351 460 * to invoke handleDataWritten(), much the same as we would
vcoubard 541:884f95bf5351 461 * have done if write-authorization had not been enabled.
vcoubard 541:884f95bf5351 462 */
vcoubard 541:884f95bf5351 463 if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) {
vcoubard 541:884f95bf5351 464 GattWriteCallbackParams cbParams = {
vcoubard 541:884f95bf5351 465 .connHandle = gattsEventP->conn_handle,
vcoubard 541:884f95bf5351 466 .handle = handle_value,
vcoubard 541:884f95bf5351 467 .writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.authorize_request.request.write.op),
vcoubard 541:884f95bf5351 468 .offset = gattsEventP->params.authorize_request.request.write.offset,
vcoubard 541:884f95bf5351 469 .len = gattsEventP->params.authorize_request.request.write.len,
vcoubard 541:884f95bf5351 470 .data = gattsEventP->params.authorize_request.request.write.data,
vcoubard 541:884f95bf5351 471 };
vcoubard 541:884f95bf5351 472 handleDataWrittenEvent(&cbParams);
vcoubard 541:884f95bf5351 473 }
vcoubard 541:884f95bf5351 474 break;
vcoubard 541:884f95bf5351 475 }
vcoubard 541:884f95bf5351 476 case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: {
vcoubard 541:884f95bf5351 477 GattReadAuthCallbackParams cbParams = {
vcoubard 541:884f95bf5351 478 .connHandle = gattsEventP->conn_handle,
vcoubard 541:884f95bf5351 479 .handle = handle_value,
vcoubard 541:884f95bf5351 480 .offset = gattsEventP->params.authorize_request.request.read.offset,
vcoubard 541:884f95bf5351 481 .len = 0,
vcoubard 541:884f95bf5351 482 .data = NULL,
vcoubard 541:884f95bf5351 483 .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member
vcoubard 541:884f95bf5351 484 * set to AUTH_CALLBACK_REPLY_SUCCESS if the client
vcoubard 541:884f95bf5351 485 * request is to proceed. */
vcoubard 541:884f95bf5351 486 };
vcoubard 541:884f95bf5351 487
vcoubard 541:884f95bf5351 488 ble_gatts_rw_authorize_reply_params_t reply = {
vcoubard 541:884f95bf5351 489 .type = BLE_GATTS_AUTHORIZE_TYPE_READ,
vcoubard 541:884f95bf5351 490 .params = {
vcoubard 541:884f95bf5351 491 .read = {
vcoubard 541:884f95bf5351 492 .gatt_status = p_characteristics[characteristicIndex]->authorizeRead(&cbParams)
vcoubard 541:884f95bf5351 493 }
vcoubard 541:884f95bf5351 494 }
vcoubard 541:884f95bf5351 495 };
vcoubard 541:884f95bf5351 496
vcoubard 541:884f95bf5351 497 if (cbParams.authorizationReply == BLE_GATT_STATUS_SUCCESS) {
vcoubard 541:884f95bf5351 498 if (cbParams.data != NULL) {
vcoubard 541:884f95bf5351 499 reply.params.read.update = 1;
vcoubard 541:884f95bf5351 500 reply.params.read.offset = cbParams.offset;
vcoubard 541:884f95bf5351 501 reply.params.read.len = cbParams.len;
vcoubard 541:884f95bf5351 502 reply.params.read.p_data = cbParams.data;
vcoubard 541:884f95bf5351 503 }
vcoubard 541:884f95bf5351 504 }
vcoubard 541:884f95bf5351 505
vcoubard 541:884f95bf5351 506 sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply);
vcoubard 541:884f95bf5351 507 break;
vcoubard 541:884f95bf5351 508 }
vcoubard 541:884f95bf5351 509
vcoubard 541:884f95bf5351 510 default:
vcoubard 541:884f95bf5351 511 handleEvent(eventType, handle_value);
vcoubard 541:884f95bf5351 512 break;
vcoubard 541:884f95bf5351 513 }
rgrover1 388:db85a09c27ef 514 }