For with fix for disconnection notifications

Fork of nRF51822 by Nordic Semiconductor

Committer:
Rohit Grover
Date:
Wed May 28 16:45:23 2014 +0100
Revision:
7:dd6465921aaa
Parent:
6:bbb4357dc135
Child:
8:2214f1df6a6a
add default implementation for custom_convert_to_transport_uuid()

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 0:eff01767de02 1 /* mbed Microcontroller Library
bogdanm 0:eff01767de02 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 0:eff01767de02 3 *
bogdanm 0:eff01767de02 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 0:eff01767de02 5 * you may not use this file except in compliance with the License.
bogdanm 0:eff01767de02 6 * You may obtain a copy of the License at
bogdanm 0:eff01767de02 7 *
bogdanm 0:eff01767de02 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 0:eff01767de02 9 *
bogdanm 0:eff01767de02 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 0:eff01767de02 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 0:eff01767de02 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 0:eff01767de02 13 * See the License for the specific language governing permissions and
bogdanm 0:eff01767de02 14 * limitations under the License.
bogdanm 0:eff01767de02 15 */
Rohit Grover 6:bbb4357dc135 16
bogdanm 0:eff01767de02 17 #include "nRF51GattServer.h"
bogdanm 0:eff01767de02 18 #include "mbed.h"
bogdanm 0:eff01767de02 19
bogdanm 0:eff01767de02 20 #include "common/common.h"
bogdanm 0:eff01767de02 21 #include "btle/custom/custom_helper.h"
bogdanm 0:eff01767de02 22
mbed_official 2:49e7ee9e88ab 23 #include "nRF51Gap.h"
mbed_official 1:f84abedbf4fb 24
Rohit Grover 7:dd6465921aaa 25 /**
Rohit Grover 7:dd6465921aaa 26 * The nRF transport has its own 3-byte representation of a UUID. If the user-
Rohit Grover 7:dd6465921aaa 27 * specified UUID is 128-bits wide, then the UUID base needs to be added to the
Rohit Grover 7:dd6465921aaa 28 * soft-device and converted to a 3-byte handle before being used further. This
Rohit Grover 7:dd6465921aaa 29 * function is responsible for this translation of user-specified UUIDs into
Rohit Grover 7:dd6465921aaa 30 * nRF's representation.
Rohit Grover 7:dd6465921aaa 31 *
Rohit Grover 7:dd6465921aaa 32 * @param[in] uuid
Rohit Grover 7:dd6465921aaa 33 * user-specified UUID
Rohit Grover 7:dd6465921aaa 34 * @return nRF
Rohit Grover 7:dd6465921aaa 35 * 3-byte UUID (containing a type and 16-bit UUID) representation
Rohit Grover 7:dd6465921aaa 36 * to be used with SVC calls.
Rohit Grover 7:dd6465921aaa 37 */
Rohit Grover 7:dd6465921aaa 38 static ble_uuid_t
Rohit Grover 7:dd6465921aaa 39 custom_convert_to_transport_uuid(const uint16_t uuid)
Rohit Grover 7:dd6465921aaa 40 {
Rohit Grover 7:dd6465921aaa 41 ble_uuid_t transportUUID = { /* presently we only deal with 16-bit uuids. */
Rohit Grover 7:dd6465921aaa 42 .type = BLE_UUID_TYPE_BLE,
Rohit Grover 7:dd6465921aaa 43 .uuid = uuid
Rohit Grover 7:dd6465921aaa 44 };
Rohit Grover 7:dd6465921aaa 45
Rohit Grover 7:dd6465921aaa 46 return transportUUID;
Rohit Grover 7:dd6465921aaa 47 }
Rohit Grover 7:dd6465921aaa 48
bogdanm 0:eff01767de02 49 /**************************************************************************/
bogdanm 0:eff01767de02 50 /*!
bogdanm 0:eff01767de02 51 @brief Adds a new service to the GATT table on the peripheral
Rohit Grover 6:bbb4357dc135 52
bogdanm 0:eff01767de02 53 @returns ble_error_t
Rohit Grover 6:bbb4357dc135 54
bogdanm 0:eff01767de02 55 @retval BLE_ERROR_NONE
bogdanm 0:eff01767de02 56 Everything executed properly
Rohit Grover 6:bbb4357dc135 57
bogdanm 0:eff01767de02 58 @section EXAMPLE
bogdanm 0:eff01767de02 59
bogdanm 0:eff01767de02 60 @code
bogdanm 0:eff01767de02 61
bogdanm 0:eff01767de02 62 @endcode
bogdanm 0:eff01767de02 63 */
bogdanm 0:eff01767de02 64 /**************************************************************************/
bogdanm 0:eff01767de02 65 ble_error_t nRF51GattServer::addService(GattService & service)
bogdanm 0:eff01767de02 66 {
bogdanm 0:eff01767de02 67 /* ToDo: Make sure we don't overflow the array, etc. */
bogdanm 0:eff01767de02 68 /* ToDo: Make sure this service UUID doesn't already exist (?) */
bogdanm 0:eff01767de02 69 /* ToDo: Basic validation */
Rohit Grover 6:bbb4357dc135 70
bogdanm 0:eff01767de02 71 /* Add the service to the nRF51 */
bogdanm 0:eff01767de02 72 ble_uuid_t uuid;
bogdanm 0:eff01767de02 73
Rohit Grover 6:bbb4357dc135 74 if (service.primaryServiceID.type == UUID::UUID_TYPE_SHORT) {
Rohit Grover 6:bbb4357dc135 75 /* 16-bit BLE UUID */
Rohit Grover 6:bbb4357dc135 76 uuid.type = BLE_UUID_TYPE_BLE;
Rohit Grover 6:bbb4357dc135 77 } else {
Rohit Grover 6:bbb4357dc135 78 /* 128-bit Custom UUID */
Rohit Grover 6:bbb4357dc135 79 uuid.type = custom_add_uuid_base( service.primaryServiceID.base );
bogdanm 0:eff01767de02 80 }
bogdanm 0:eff01767de02 81
bogdanm 0:eff01767de02 82 uuid.uuid = service.primaryServiceID.value;
bogdanm 0:eff01767de02 83
Rohit Grover 6:bbb4357dc135 84 ASSERT( ERROR_NONE ==
Rohit Grover 6:bbb4357dc135 85 sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
Rohit Grover 6:bbb4357dc135 86 &uuid,
Rohit Grover 6:bbb4357dc135 87 &service.handle),
Rohit Grover 6:bbb4357dc135 88 BLE_ERROR_PARAM_OUT_OF_RANGE );
bogdanm 0:eff01767de02 89
bogdanm 0:eff01767de02 90 /* Add characteristics to the service */
Rohit Grover 6:bbb4357dc135 91 for (uint8_t i = 0; i < service.characteristicCount; i++) {
Rohit Grover 6:bbb4357dc135 92 GattCharacteristic *p_char = service.characteristics[i];
bogdanm 0:eff01767de02 93
Rohit Grover 7:dd6465921aaa 94 uuid = custom_convert_to_transport_uuid(p_char->uuid);
Rohit Grover 7:dd6465921aaa 95
Rohit Grover 6:bbb4357dc135 96 uuid.uuid = p_char->uuid;
Rohit Grover 6:bbb4357dc135 97 ASSERT ( ERROR_NONE ==
Rohit Grover 6:bbb4357dc135 98 custom_add_in_characteristic(service.handle,
Rohit Grover 6:bbb4357dc135 99 &uuid,
Rohit Grover 6:bbb4357dc135 100 p_char->properties,
Rohit Grover 6:bbb4357dc135 101 NULL,
Rohit Grover 6:bbb4357dc135 102 p_char->lenMin,
Rohit Grover 6:bbb4357dc135 103 p_char->lenMax,
Rohit Grover 6:bbb4357dc135 104 &nrfCharacteristicHandles[
Rohit Grover 6:bbb4357dc135 105 characteristicCount]),
Rohit Grover 6:bbb4357dc135 106 BLE_ERROR_PARAM_OUT_OF_RANGE );
Rohit Grover 6:bbb4357dc135 107
Rohit Grover 6:bbb4357dc135 108 /* Update the characteristic handle */
Rohit Grover 6:bbb4357dc135 109 p_char->handle = characteristicCount;
Rohit Grover 6:bbb4357dc135 110 p_characteristics[characteristicCount++] = p_char;
bogdanm 0:eff01767de02 111 }
bogdanm 0:eff01767de02 112
bogdanm 0:eff01767de02 113 serviceCount++;
Rohit Grover 6:bbb4357dc135 114
bogdanm 0:eff01767de02 115 return BLE_ERROR_NONE;
bogdanm 0:eff01767de02 116 }
bogdanm 0:eff01767de02 117
bogdanm 0:eff01767de02 118 /**************************************************************************/
bogdanm 0:eff01767de02 119 /*!
bogdanm 0:eff01767de02 120 @brief Reads the value of a characteristic, based on the service
bogdanm 0:eff01767de02 121 and characteristic index fields
bogdanm 0:eff01767de02 122
bogdanm 0:eff01767de02 123 @param[in] charHandle
bogdanm 0:eff01767de02 124 The handle of the GattCharacteristic to read from
bogdanm 0:eff01767de02 125 @param[in] buffer
bogdanm 0:eff01767de02 126 Buffer to hold the the characteristic's value
bogdanm 0:eff01767de02 127 (raw byte array in LSB format)
bogdanm 0:eff01767de02 128 @param[in] len
bogdanm 0:eff01767de02 129 The number of bytes read into the buffer
Rohit Grover 6:bbb4357dc135 130
bogdanm 0:eff01767de02 131 @returns ble_error_t
Rohit Grover 6:bbb4357dc135 132
bogdanm 0:eff01767de02 133 @retval BLE_ERROR_NONE
bogdanm 0:eff01767de02 134 Everything executed properly
Rohit Grover 6:bbb4357dc135 135
bogdanm 0:eff01767de02 136 @section EXAMPLE
bogdanm 0:eff01767de02 137
bogdanm 0:eff01767de02 138 @code
bogdanm 0:eff01767de02 139
bogdanm 0:eff01767de02 140 @endcode
bogdanm 0:eff01767de02 141 */
bogdanm 0:eff01767de02 142 /**************************************************************************/
Rohit Grover 6:bbb4357dc135 143 ble_error_t nRF51GattServer::readValue(uint16_t charHandle,
Rohit Grover 6:bbb4357dc135 144 uint8_t buffer[],
Rohit Grover 6:bbb4357dc135 145 uint16_t len)
bogdanm 0:eff01767de02 146 {
Rohit Grover 6:bbb4357dc135 147 ASSERT( ERROR_NONE ==
Rohit Grover 6:bbb4357dc135 148 sd_ble_gatts_value_get(nrfCharacteristicHandles[charHandle].
Rohit Grover 6:bbb4357dc135 149 value_handle, 0,
Rohit Grover 6:bbb4357dc135 150 &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE);
Rohit Grover 6:bbb4357dc135 151
bogdanm 0:eff01767de02 152 return BLE_ERROR_NONE;
bogdanm 0:eff01767de02 153 }
bogdanm 0:eff01767de02 154
bogdanm 0:eff01767de02 155 /**************************************************************************/
bogdanm 0:eff01767de02 156 /*!
bogdanm 0:eff01767de02 157 @brief Updates the value of a characteristic, based on the service
bogdanm 0:eff01767de02 158 and characteristic index fields
bogdanm 0:eff01767de02 159
bogdanm 0:eff01767de02 160 @param[in] charHandle
bogdanm 0:eff01767de02 161 The handle of the GattCharacteristic to write to
bogdanm 0:eff01767de02 162 @param[in] buffer
bogdanm 0:eff01767de02 163 Data to use when updating the characteristic's value
bogdanm 0:eff01767de02 164 (raw byte array in LSB format)
bogdanm 0:eff01767de02 165 @param[in] len
bogdanm 0:eff01767de02 166 The number of bytes in buffer
Rohit Grover 6:bbb4357dc135 167
bogdanm 0:eff01767de02 168 @returns ble_error_t
Rohit Grover 6:bbb4357dc135 169
bogdanm 0:eff01767de02 170 @retval BLE_ERROR_NONE
bogdanm 0:eff01767de02 171 Everything executed properly
Rohit Grover 6:bbb4357dc135 172
bogdanm 0:eff01767de02 173 @section EXAMPLE
bogdanm 0:eff01767de02 174
bogdanm 0:eff01767de02 175 @code
bogdanm 0:eff01767de02 176
bogdanm 0:eff01767de02 177 @endcode
bogdanm 0:eff01767de02 178 */
bogdanm 0:eff01767de02 179 /**************************************************************************/
Rohit Grover 6:bbb4357dc135 180 ble_error_t nRF51GattServer::updateValue(uint16_t charHandle,
Rohit Grover 6:bbb4357dc135 181 uint8_t buffer[],
Rohit Grover 6:bbb4357dc135 182 uint16_t len,
Rohit Grover 6:bbb4357dc135 183 bool localOnly)
bogdanm 0:eff01767de02 184 {
Rohit Grover 6:bbb4357dc135 185 uint16_t gapConnectionHandle =
Rohit Grover 6:bbb4357dc135 186 nRF51Gap::getInstance().getConnectionHandle();
Rohit Grover 6:bbb4357dc135 187
Rohit Grover 6:bbb4357dc135 188 if (localOnly) {
Rohit Grover 6:bbb4357dc135 189 /* Only update locally regardless of notify/indicate */
Rohit Grover 6:bbb4357dc135 190 ASSERT_INT( ERROR_NONE,
Rohit Grover 6:bbb4357dc135 191 sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].
Rohit Grover 6:bbb4357dc135 192 value_handle,
Rohit Grover 6:bbb4357dc135 193 0,
Rohit Grover 6:bbb4357dc135 194 &len,
Rohit Grover 6:bbb4357dc135 195 buffer),
Rohit Grover 6:bbb4357dc135 196 BLE_ERROR_PARAM_OUT_OF_RANGE );
Rohit Grover 6:bbb4357dc135 197 }
Rohit Grover 6:bbb4357dc135 198
Rohit Grover 6:bbb4357dc135 199 if ((p_characteristics[charHandle]->properties &
Rohit Grover 6:bbb4357dc135 200 (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE |
Rohit Grover 6:bbb4357dc135 201 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) &&
Rohit Grover 6:bbb4357dc135 202 (gapConnectionHandle != BLE_CONN_HANDLE_INVALID)) {
Rohit Grover 6:bbb4357dc135 203 /* HVX update for the characteristic value */
Rohit Grover 6:bbb4357dc135 204 ble_gatts_hvx_params_t hvx_params;
bogdanm 0:eff01767de02 205
Rohit Grover 6:bbb4357dc135 206 hvx_params.handle = nrfCharacteristicHandles[charHandle].value_handle;
Rohit Grover 6:bbb4357dc135 207 hvx_params.type =
Rohit Grover 6:bbb4357dc135 208 (p_characteristics[charHandle]->properties &
Rohit Grover 6:bbb4357dc135 209 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ?
Rohit Grover 6:bbb4357dc135 210 BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION;
Rohit Grover 6:bbb4357dc135 211 hvx_params.offset = 0;
Rohit Grover 6:bbb4357dc135 212 hvx_params.p_data = buffer;
Rohit Grover 6:bbb4357dc135 213 hvx_params.p_len = &len;
bogdanm 0:eff01767de02 214
Rohit Grover 6:bbb4357dc135 215 error_t error = (error_t) sd_ble_gatts_hvx(gapConnectionHandle,
Rohit Grover 6:bbb4357dc135 216 &hvx_params);
bogdanm 0:eff01767de02 217
Rohit Grover 6:bbb4357dc135 218 /* ERROR_INVALID_STATE, ERROR_BUSY, ERROR_GATTS_SYS_ATTR_MISSING and
Rohit Grover 6:bbb4357dc135 219 *ERROR_NO_TX_BUFFERS the ATT table has been updated. */
Rohit Grover 6:bbb4357dc135 220 if ((error != ERROR_NONE) && (error != ERROR_INVALID_STATE) &&
Rohit Grover 6:bbb4357dc135 221 (error != ERROR_BLE_NO_TX_BUFFERS) && (error != ERROR_BUSY) &&
Rohit Grover 6:bbb4357dc135 222 (error != ERROR_BLEGATTS_SYS_ATTR_MISSING)) {
Rohit Grover 6:bbb4357dc135 223 ASSERT_INT( ERROR_NONE,
Rohit Grover 6:bbb4357dc135 224 sd_ble_gatts_value_set(nrfCharacteristicHandles[
Rohit Grover 6:bbb4357dc135 225 charHandle].
Rohit Grover 6:bbb4357dc135 226 value_handle,
Rohit Grover 6:bbb4357dc135 227 0,
Rohit Grover 6:bbb4357dc135 228 &len,
Rohit Grover 6:bbb4357dc135 229 buffer),
Rohit Grover 6:bbb4357dc135 230 BLE_ERROR_PARAM_OUT_OF_RANGE );
Rohit Grover 6:bbb4357dc135 231 }
Rohit Grover 6:bbb4357dc135 232 } else {
Rohit Grover 6:bbb4357dc135 233 ASSERT_INT( ERROR_NONE,
Rohit Grover 6:bbb4357dc135 234 sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].
Rohit Grover 6:bbb4357dc135 235 value_handle,
Rohit Grover 6:bbb4357dc135 236 0,
Rohit Grover 6:bbb4357dc135 237 &len,
Rohit Grover 6:bbb4357dc135 238 buffer),
Rohit Grover 6:bbb4357dc135 239 BLE_ERROR_PARAM_OUT_OF_RANGE );
bogdanm 0:eff01767de02 240 }
Rohit Grover 6:bbb4357dc135 241
Rohit Grover 6:bbb4357dc135 242 return BLE_ERROR_NONE;
bogdanm 0:eff01767de02 243 }
bogdanm 0:eff01767de02 244
bogdanm 0:eff01767de02 245 /**************************************************************************/
bogdanm 0:eff01767de02 246 /*!
bogdanm 0:eff01767de02 247 @brief Callback handler for events getting pushed up from the SD
bogdanm 0:eff01767de02 248 */
bogdanm 0:eff01767de02 249 /**************************************************************************/
Rohit Grover 6:bbb4357dc135 250 void nRF51GattServer::hwCallback(ble_evt_t *p_ble_evt)
bogdanm 0:eff01767de02 251 {
Rohit Grover 6:bbb4357dc135 252 uint16_t handle_value;
Rohit Grover 6:bbb4357dc135 253 GattServerEvents::gattEvent_t event;
bogdanm 0:eff01767de02 254
Rohit Grover 6:bbb4357dc135 255 switch (p_ble_evt->header.evt_id) {
bogdanm 0:eff01767de02 256 case BLE_GATTS_EVT_WRITE:
Rohit Grover 6:bbb4357dc135 257 /* There are 2 use case here: Values being updated & CCCD
Rohit Grover 6:bbb4357dc135 258 *(indicate/notify) enabled */
Rohit Grover 6:bbb4357dc135 259
Rohit Grover 6:bbb4357dc135 260 /* 1.) Handle CCCD changes */
Rohit Grover 6:bbb4357dc135 261 handle_value = p_ble_evt->evt.gatts_evt.params.write.handle;
Rohit Grover 6:bbb4357dc135 262 for (uint8_t i = 0; i<characteristicCount; i++) {
Rohit Grover 6:bbb4357dc135 263 if ((p_characteristics[i]->properties &
Rohit Grover 6:bbb4357dc135 264 (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE |
Rohit Grover 6:bbb4357dc135 265 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) &&
Rohit Grover 6:bbb4357dc135 266 (nrfCharacteristicHandles[i].cccd_handle == handle_value)) {
Rohit Grover 6:bbb4357dc135 267 uint16_t cccd_value =
Rohit Grover 6:bbb4357dc135 268 (p_ble_evt->evt.gatts_evt.params.write.data[1] <<
Rohit Grover 6:bbb4357dc135 269 8) | p_ble_evt->evt.gatts_evt.params.write.data[0]; /*
Rohit Grover 6:bbb4357dc135 270 * Little Endian but M0 may
Rohit Grover 6:bbb4357dc135 271 * be mis-aligned */
bogdanm 0:eff01767de02 272
Rohit Grover 6:bbb4357dc135 273 if (((p_characteristics[i]->properties &
Rohit Grover 6:bbb4357dc135 274 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) &&
Rohit Grover 6:bbb4357dc135 275 (cccd_value & BLE_GATT_HVX_INDICATION)) ||
Rohit Grover 6:bbb4357dc135 276 ((p_characteristics[i]->properties &
Rohit Grover 6:bbb4357dc135 277 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) &&
Rohit Grover 6:bbb4357dc135 278 (cccd_value & BLE_GATT_HVX_NOTIFICATION))) {
Rohit Grover 6:bbb4357dc135 279 event = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
Rohit Grover 6:bbb4357dc135 280 } else {
Rohit Grover 6:bbb4357dc135 281 event = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
Rohit Grover 6:bbb4357dc135 282 }
bogdanm 0:eff01767de02 283
Rohit Grover 6:bbb4357dc135 284 handleEvent(event, i);
Rohit Grover 6:bbb4357dc135 285 return;
Rohit Grover 6:bbb4357dc135 286 }
bogdanm 0:eff01767de02 287 }
bogdanm 0:eff01767de02 288
Rohit Grover 6:bbb4357dc135 289 /* 2.) Changes to the characteristic value will be handled with other
Rohit Grover 6:bbb4357dc135 290 *events below */
Rohit Grover 6:bbb4357dc135 291 event = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
Rohit Grover 6:bbb4357dc135 292 break;
bogdanm 0:eff01767de02 293
bogdanm 0:eff01767de02 294 case BLE_GATTS_EVT_HVC:
Rohit Grover 6:bbb4357dc135 295 /* Indication confirmation received */
Rohit Grover 6:bbb4357dc135 296 event = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED;
Rohit Grover 6:bbb4357dc135 297 handle_value = p_ble_evt->evt.gatts_evt.params.hvc.handle;
Rohit Grover 6:bbb4357dc135 298 break;
bogdanm 0:eff01767de02 299
Rohit Grover 6:bbb4357dc135 300 default:
Rohit Grover 6:bbb4357dc135 301 return;
Rohit Grover 6:bbb4357dc135 302 }
bogdanm 0:eff01767de02 303
Rohit Grover 6:bbb4357dc135 304 /* Find index (charHandle) in the pool */
Rohit Grover 6:bbb4357dc135 305 for (uint8_t i = 0; i<characteristicCount; i++) {
Rohit Grover 6:bbb4357dc135 306 if (nrfCharacteristicHandles[i].value_handle == handle_value) {
Rohit Grover 6:bbb4357dc135 307 handleEvent(event, i);
Rohit Grover 6:bbb4357dc135 308 break;
Rohit Grover 6:bbb4357dc135 309 }
bogdanm 0:eff01767de02 310 }
bogdanm 0:eff01767de02 311 }