test firmware for BLE Micro V1.3 1. test io, vcc and ble 2. act as a UART to BLE bridge

Dependencies:   BLE_API Buffer mbed

Fork of BLE_LEDBlinker by Bluetooth Low Energy

Committer:
arch
Date:
Tue Dec 08 06:02:25 2015 +0000
Revision:
11:c8cbc4bc2c17
test firmware for BLE Micro V1.3

Who changed what in which revision?

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