Official Sheffield ARMBand micro:bit program

Committer:
MrBedfordVan
Date:
Mon Oct 17 12:41:20 2016 +0000
Revision:
0:b9164b348919
Official Sheffield ARMBand Micro:bit program

Who changed what in which revision?

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