library for BLE_GAP_backpack

Dependencies:   nrf51-sdk

Fork of nRF51822 by Nordic Semiconductor

Committer:
vcoubard
Date:
Mon Jan 11 10:19:18 2016 +0000
Revision:
565:cf03471a4ec4
Parent:
563:9c4b96f7be8d
Child:
566:e425ad9e5d6e
Synchronized with git rev 0bcc2e96
Author: Andres Amaya Garcia
Modify shutdown due to BLE API change

The module is updated to comply with the changes to BLE API regarding correct
shutdown functionality. The following changes are introduced to ble-nrf51822:

* Calls to the old static function shutdown in Gap, GattClient, GattServer and
SecurityManager are removed.
* The cleanup function in Gap, GattClient, GattServer and SecurityManager is
renamed to `reset()` and made public.
* The static references inside nRF5xGap, nRF5xGattClient, nRF5xGattServer and
nRF5xSecurityManager to objects of their own class are moved to nRF5xn.
* The static getInstance accessors in nRF5xGap, nRF5xGattClient,
nRF5xGattServer and nRF5xSecurityManager are removed and their functionality is
moved to the implemented virtual accessors in nRF5xn i.e. getGap(),
getGattClient, etc.
* A static function Instance is added to nRF5xn class to make the transport
object accessible across the module.

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