For with fix for disconnection notifications

Fork of nRF51822 by Nordic Semiconductor

Committer:
mbed_official
Date:
Thu Apr 03 01:45:38 2014 +0100
Revision:
1:f84abedbf4fb
Parent:
0:eff01767de02
Child:
2:49e7ee9e88ab
Synchronized with git revision 348e2de6c8b2badc1fd1fe7ae044c24c25244a11

Full URL: https://github.com/mbedmicro/mbed/commit/348e2de6c8b2badc1fd1fe7ae044c24c25244a11/

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 */
bogdanm 0:eff01767de02 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 1:f84abedbf4fb 23 #include "hw/nRF51822n/nRF51Gap.h"
mbed_official 1:f84abedbf4fb 24
bogdanm 0:eff01767de02 25 /**************************************************************************/
bogdanm 0:eff01767de02 26 /*!
bogdanm 0:eff01767de02 27 @brief Adds a new service to the GATT table on the peripheral
bogdanm 0:eff01767de02 28
bogdanm 0:eff01767de02 29 @returns ble_error_t
bogdanm 0:eff01767de02 30
bogdanm 0:eff01767de02 31 @retval BLE_ERROR_NONE
bogdanm 0:eff01767de02 32 Everything executed properly
bogdanm 0:eff01767de02 33
bogdanm 0:eff01767de02 34 @section EXAMPLE
bogdanm 0:eff01767de02 35
bogdanm 0:eff01767de02 36 @code
bogdanm 0:eff01767de02 37
bogdanm 0:eff01767de02 38 @endcode
bogdanm 0:eff01767de02 39 */
bogdanm 0:eff01767de02 40 /**************************************************************************/
bogdanm 0:eff01767de02 41 ble_error_t nRF51GattServer::addService(GattService & service)
bogdanm 0:eff01767de02 42 {
bogdanm 0:eff01767de02 43 /* ToDo: Make sure we don't overflow the array, etc. */
bogdanm 0:eff01767de02 44 /* ToDo: Make sure this service UUID doesn't already exist (?) */
bogdanm 0:eff01767de02 45 /* ToDo: Basic validation */
bogdanm 0:eff01767de02 46
bogdanm 0:eff01767de02 47 /* Add the service to the nRF51 */
bogdanm 0:eff01767de02 48 ble_uuid_t uuid;
bogdanm 0:eff01767de02 49
bogdanm 0:eff01767de02 50 if (service.primaryServiceID.type == UUID::UUID_TYPE_SHORT)
bogdanm 0:eff01767de02 51 {
bogdanm 0:eff01767de02 52 /* 16-bit BLE UUID */
bogdanm 0:eff01767de02 53 uuid.type = BLE_UUID_TYPE_BLE;
bogdanm 0:eff01767de02 54 }
bogdanm 0:eff01767de02 55 else
bogdanm 0:eff01767de02 56 {
bogdanm 0:eff01767de02 57 /* 128-bit Custom UUID */
bogdanm 0:eff01767de02 58 uuid.type = custom_add_uuid_base( service.primaryServiceID.base );
bogdanm 0:eff01767de02 59 }
bogdanm 0:eff01767de02 60
bogdanm 0:eff01767de02 61 uuid.uuid = service.primaryServiceID.value;
bogdanm 0:eff01767de02 62
bogdanm 0:eff01767de02 63 ASSERT( ERROR_NONE == sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &uuid, &service.handle), BLE_ERROR_PARAM_OUT_OF_RANGE );
bogdanm 0:eff01767de02 64
bogdanm 0:eff01767de02 65 /* Add characteristics to the service */
bogdanm 0:eff01767de02 66 for (uint8_t i = 0; i < service.characteristicCount; i++)
bogdanm 0:eff01767de02 67 {
bogdanm 0:eff01767de02 68 GattCharacteristic * p_char = service.characteristics[i];
bogdanm 0:eff01767de02 69
bogdanm 0:eff01767de02 70 uuid.uuid = p_char->uuid;
bogdanm 0:eff01767de02 71 ASSERT ( ERROR_NONE == custom_add_in_characteristic(service.handle, &uuid, p_char->properties,
bogdanm 0:eff01767de02 72 NULL, p_char->lenMin, p_char->lenMax, &nrfCharacteristicHandles[characteristicCount]), BLE_ERROR_PARAM_OUT_OF_RANGE );
bogdanm 0:eff01767de02 73
bogdanm 0:eff01767de02 74 /* Update the characteristic handle */
bogdanm 0:eff01767de02 75 p_char->handle = characteristicCount;
bogdanm 0:eff01767de02 76 p_characteristics[characteristicCount++] = p_char;
bogdanm 0:eff01767de02 77 }
bogdanm 0:eff01767de02 78
bogdanm 0:eff01767de02 79 serviceCount++;
bogdanm 0:eff01767de02 80
bogdanm 0:eff01767de02 81 return BLE_ERROR_NONE;
bogdanm 0:eff01767de02 82 }
bogdanm 0:eff01767de02 83
bogdanm 0:eff01767de02 84 /**************************************************************************/
bogdanm 0:eff01767de02 85 /*!
bogdanm 0:eff01767de02 86 @brief Reads the value of a characteristic, based on the service
bogdanm 0:eff01767de02 87 and characteristic index fields
bogdanm 0:eff01767de02 88
bogdanm 0:eff01767de02 89 @param[in] charHandle
bogdanm 0:eff01767de02 90 The handle of the GattCharacteristic to read from
bogdanm 0:eff01767de02 91 @param[in] buffer
bogdanm 0:eff01767de02 92 Buffer to hold the the characteristic's value
bogdanm 0:eff01767de02 93 (raw byte array in LSB format)
bogdanm 0:eff01767de02 94 @param[in] len
bogdanm 0:eff01767de02 95 The number of bytes read into the buffer
bogdanm 0:eff01767de02 96
bogdanm 0:eff01767de02 97 @returns ble_error_t
bogdanm 0:eff01767de02 98
bogdanm 0:eff01767de02 99 @retval BLE_ERROR_NONE
bogdanm 0:eff01767de02 100 Everything executed properly
bogdanm 0:eff01767de02 101
bogdanm 0:eff01767de02 102 @section EXAMPLE
bogdanm 0:eff01767de02 103
bogdanm 0:eff01767de02 104 @code
bogdanm 0:eff01767de02 105
bogdanm 0:eff01767de02 106 @endcode
bogdanm 0:eff01767de02 107 */
bogdanm 0:eff01767de02 108 /**************************************************************************/
bogdanm 0:eff01767de02 109 ble_error_t nRF51GattServer::readValue(uint16_t charHandle, uint8_t buffer[], uint16_t len)
bogdanm 0:eff01767de02 110 {
bogdanm 0:eff01767de02 111 ASSERT( ERROR_NONE == sd_ble_gatts_value_get(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE);
bogdanm 0:eff01767de02 112
bogdanm 0:eff01767de02 113 return BLE_ERROR_NONE;
bogdanm 0:eff01767de02 114 }
bogdanm 0:eff01767de02 115
bogdanm 0:eff01767de02 116 /**************************************************************************/
bogdanm 0:eff01767de02 117 /*!
bogdanm 0:eff01767de02 118 @brief Updates the value of a characteristic, based on the service
bogdanm 0:eff01767de02 119 and characteristic index fields
bogdanm 0:eff01767de02 120
bogdanm 0:eff01767de02 121 @param[in] charHandle
bogdanm 0:eff01767de02 122 The handle of the GattCharacteristic to write to
bogdanm 0:eff01767de02 123 @param[in] buffer
bogdanm 0:eff01767de02 124 Data to use when updating the characteristic's value
bogdanm 0:eff01767de02 125 (raw byte array in LSB format)
bogdanm 0:eff01767de02 126 @param[in] len
bogdanm 0:eff01767de02 127 The number of bytes in buffer
bogdanm 0:eff01767de02 128
bogdanm 0:eff01767de02 129 @returns ble_error_t
bogdanm 0:eff01767de02 130
bogdanm 0:eff01767de02 131 @retval BLE_ERROR_NONE
bogdanm 0:eff01767de02 132 Everything executed properly
bogdanm 0:eff01767de02 133
bogdanm 0:eff01767de02 134 @section EXAMPLE
bogdanm 0:eff01767de02 135
bogdanm 0:eff01767de02 136 @code
bogdanm 0:eff01767de02 137
bogdanm 0:eff01767de02 138 @endcode
bogdanm 0:eff01767de02 139 */
bogdanm 0:eff01767de02 140 /**************************************************************************/
bogdanm 0:eff01767de02 141 ble_error_t nRF51GattServer::updateValue(uint16_t charHandle, uint8_t buffer[], uint16_t len, bool localOnly)
bogdanm 0:eff01767de02 142 {
mbed_official 1:f84abedbf4fb 143 uint16_t gapConnectionHandle = nRF51Gap::getInstance().getConnectionHandle();
mbed_official 1:f84abedbf4fb 144
bogdanm 0:eff01767de02 145 if (localOnly)
bogdanm 0:eff01767de02 146 {
bogdanm 0:eff01767de02 147 /* Only update locally regardless of notify/indicate */
bogdanm 0:eff01767de02 148 ASSERT_INT( ERROR_NONE, sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE );
bogdanm 0:eff01767de02 149 }
mbed_official 1:f84abedbf4fb 150
bogdanm 0:eff01767de02 151 if ((p_characteristics[charHandle]->properties & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) &&
mbed_official 1:f84abedbf4fb 152 (gapConnectionHandle != BLE_CONN_HANDLE_INVALID) )
bogdanm 0:eff01767de02 153 {
bogdanm 0:eff01767de02 154 /* HVX update for the characteristic value */
bogdanm 0:eff01767de02 155 ble_gatts_hvx_params_t hvx_params;
bogdanm 0:eff01767de02 156
bogdanm 0:eff01767de02 157 hvx_params.handle = nrfCharacteristicHandles[charHandle].value_handle;
bogdanm 0:eff01767de02 158 hvx_params.type = (p_characteristics[charHandle]->properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION;
bogdanm 0:eff01767de02 159 hvx_params.offset = 0;
bogdanm 0:eff01767de02 160 hvx_params.p_data = buffer;
bogdanm 0:eff01767de02 161 hvx_params.p_len = &len;
bogdanm 0:eff01767de02 162
mbed_official 1:f84abedbf4fb 163 error_t error = (error_t) sd_ble_gatts_hvx(gapConnectionHandle, &hvx_params);
bogdanm 0:eff01767de02 164
bogdanm 0:eff01767de02 165 /* ERROR_INVALID_STATE, ERROR_BUSY, ERROR_GATTS_SYS_ATTR_MISSING and ERROR_NO_TX_BUFFERS the ATT table has been updated. */
bogdanm 0:eff01767de02 166 if ( (error != ERROR_NONE ) && (error != ERROR_INVALID_STATE) &&
bogdanm 0:eff01767de02 167 (error != ERROR_BLE_NO_TX_BUFFERS ) && (error != ERROR_BUSY ) &&
bogdanm 0:eff01767de02 168 (error != ERROR_BLEGATTS_SYS_ATTR_MISSING ) )
bogdanm 0:eff01767de02 169 {
bogdanm 0:eff01767de02 170 ASSERT_INT( ERROR_NONE, sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE );
bogdanm 0:eff01767de02 171 }
bogdanm 0:eff01767de02 172 } else
bogdanm 0:eff01767de02 173 {
bogdanm 0:eff01767de02 174 ASSERT_INT( ERROR_NONE, sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE );
bogdanm 0:eff01767de02 175 }
bogdanm 0:eff01767de02 176
bogdanm 0:eff01767de02 177 return BLE_ERROR_NONE;
bogdanm 0:eff01767de02 178 }
bogdanm 0:eff01767de02 179
bogdanm 0:eff01767de02 180 /**************************************************************************/
bogdanm 0:eff01767de02 181 /*!
bogdanm 0:eff01767de02 182 @brief Callback handler for events getting pushed up from the SD
bogdanm 0:eff01767de02 183 */
bogdanm 0:eff01767de02 184 /**************************************************************************/
bogdanm 0:eff01767de02 185 void nRF51GattServer::hwCallback(ble_evt_t * p_ble_evt)
bogdanm 0:eff01767de02 186 {
bogdanm 0:eff01767de02 187 uint16_t handle_value;
bogdanm 0:eff01767de02 188 GattServerEvents::gattEvent_t event;
bogdanm 0:eff01767de02 189
bogdanm 0:eff01767de02 190 switch (p_ble_evt->header.evt_id)
bogdanm 0:eff01767de02 191 {
bogdanm 0:eff01767de02 192 case BLE_GATTS_EVT_WRITE:
bogdanm 0:eff01767de02 193 /* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */
bogdanm 0:eff01767de02 194
bogdanm 0:eff01767de02 195 /* 1.) Handle CCCD changes */
bogdanm 0:eff01767de02 196 handle_value = p_ble_evt->evt.gatts_evt.params.write.handle;
bogdanm 0:eff01767de02 197 for(uint8_t i=0; i<characteristicCount; i++)
bogdanm 0:eff01767de02 198 {
bogdanm 0:eff01767de02 199 if ( (p_characteristics[i]->properties & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) &&
bogdanm 0:eff01767de02 200 (nrfCharacteristicHandles[i].cccd_handle == handle_value) )
bogdanm 0:eff01767de02 201 {
bogdanm 0:eff01767de02 202 uint16_t cccd_value = (p_ble_evt->evt.gatts_evt.params.write.data[1] << 8) | p_ble_evt->evt.gatts_evt.params.write.data[0]; /* Little Endian but M0 may be mis-aligned */
bogdanm 0:eff01767de02 203
bogdanm 0:eff01767de02 204 if ( ((p_characteristics[i]->properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION )) ||
bogdanm 0:eff01767de02 205 ((p_characteristics[i]->properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY ) && (cccd_value & BLE_GATT_HVX_NOTIFICATION)))
bogdanm 0:eff01767de02 206 {
bogdanm 0:eff01767de02 207 event = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
bogdanm 0:eff01767de02 208 } else
bogdanm 0:eff01767de02 209 {
bogdanm 0:eff01767de02 210 event = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
bogdanm 0:eff01767de02 211 }
bogdanm 0:eff01767de02 212
bogdanm 0:eff01767de02 213 handleEvent(event, i);
bogdanm 0:eff01767de02 214 return;
bogdanm 0:eff01767de02 215 }
bogdanm 0:eff01767de02 216 }
bogdanm 0:eff01767de02 217
bogdanm 0:eff01767de02 218 /* 2.) Changes to the characteristic value will be handled with other events below */
bogdanm 0:eff01767de02 219 event = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
bogdanm 0:eff01767de02 220 break;
bogdanm 0:eff01767de02 221
bogdanm 0:eff01767de02 222 case BLE_GATTS_EVT_HVC:
bogdanm 0:eff01767de02 223 /* Indication confirmation received */
bogdanm 0:eff01767de02 224 event = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED;
bogdanm 0:eff01767de02 225 handle_value = p_ble_evt->evt.gatts_evt.params.hvc.handle;
bogdanm 0:eff01767de02 226 break;
bogdanm 0:eff01767de02 227
bogdanm 0:eff01767de02 228 default:
bogdanm 0:eff01767de02 229 return;
bogdanm 0:eff01767de02 230 }
bogdanm 0:eff01767de02 231
bogdanm 0:eff01767de02 232 /* Find index (charHandle) in the pool */
bogdanm 0:eff01767de02 233 for(uint8_t i=0; i<characteristicCount; i++)
bogdanm 0:eff01767de02 234 {
bogdanm 0:eff01767de02 235 if (nrfCharacteristicHandles[i].value_handle == handle_value)
bogdanm 0:eff01767de02 236 {
bogdanm 0:eff01767de02 237 handleEvent(event, i);
bogdanm 0:eff01767de02 238 break;
bogdanm 0:eff01767de02 239 }
bogdanm 0:eff01767de02 240 }
bogdanm 0:eff01767de02 241 }