nordic

Fork of nRF51822 by Nordic Semiconductor

Committer:
vcoubard
Date:
Tue Jan 12 19:58:03 2016 +0000
Revision:
616:1751e2e2637a
Parent:
579:78f69f1be114
Synchronized with git rev 78b4ea55
Author: Vincent Coubard
Merge pull request #106 from ARMmbed/develop

merge version

Who changed what in which revision?

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