test code 123

Dependencies:   mbed

Fork of LinkNode-Test by Qi Yao

Committer:
youkee
Date:
Fri Oct 28 13:04:10 2016 +0000
Revision:
1:b0d4fbbdb244
Parent:
0:1ad0e04b1bc5
ghhbfdd

Who changed what in which revision?

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