No changes

Fork of nRF51822 by Nordic Semiconductor

Committer:
vcoubard
Date:
Fri Apr 08 11:05:55 2016 +0100
Revision:
621:1d79da5c393e
Parent:
578:78f69f1be114
Child:
630:435a3d9e6456
Synchronized with git rev a18eb4a3
Author: Vincent Coubard
Fix incorrect handles of characteristics descriptors.

The variable descriptorCount is used as an index, and this index is used to set
the handle of the last registered descriptor.

Prior to this fix, descriptorCount was incremented before the handle the update
of the handle of a characteristics.

Short story, all characteristics descriptors handle were equaols to 0 instead
of the actual value.

Who changed what in which revision?

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