Sergey Solodunov / nRF51822

Dependencies:   nrf51-sdk

Fork of nRF51822 by Nordic Semiconductor

Committer:
rgrover1
Date:
Mon Jul 06 10:13:27 2015 +0100
Revision:
371:8f7d2137727a
Parent:
370:295f76db798e
Synchronized with git rev 2716309c
Author: Rohit Grover
Release 0.4.0
=============

This is a major release which introduces the GATT Client functionality. It
aligns with release 0.4.0 of BLE_API.

Enhancements
~~~~~~~~~~~~

* Introduce GattClient. This includes functionality for service-discovery,
connections, and attribute-reads and writes. You'll find a demo program for
LEDBlinker on the mbed.org Bluetooth team page to use the new APIs. Some of
the GATT client functionality hasn't been implemented yet, but the APIs have
been added.

* We've added an implementation for the abstract base class for
SecurityManager. All security related APIs have been moved into that.

* There has been a major cleanup of APIs under BLE. APIs have now been
categorized as belonging to Gap, GattServer, GattClient, or SecurityManager.
There are accessors to get references for Gap, GattServer, GattClient, and
SecurityManager. A former call to ble.setAddress(...) is now expected to be
achieved with ble.gap().setAddress(...).

* We've cleaned up our APIs, and this has resulted in dropping some APIs like
BLE::reset().

* We've also dropped GattServer::initializeGattDatabase(). THis was added at
some point to support controllers where a commit point was needed to
indicate when the application had finished constructing the GATT database.
This API would get called internally before Gap::startAdvertising(). We now
expect the underlying port to do the equivalent of initializeGattDatabase()
implicitly upon Gap::startAdvertising().

* We've added a version of Gap::disconnect() which takes a connection handle.
The previous API (which did not take a connection handle) has been
deprecated; it will still work for situations where there's only a single
active connection. We hold on to that API to allow existing code to migrate
to the new API.

Bugfixes
~~~~~~~~

* None.

Who changed what in which revision?

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