PBL mbed final

Fork of nRF51822 by Shuta Nakamae

Committer:
rgrover1
Date:
Tue Jul 21 13:23:45 2015 +0100
Revision:
391:8cc3528a1233
Parent:
389:5982ee136c47
Synchronized with git rev 4ec44d75
Author: Andrew Fernandes
Change DiscoveredCharacteristic API to return long or short UUIDs.

Who changed what in which revision?

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