Changed the device name.

Dependents:   BLE_Health_Thermometer_HeartRateMonitor

Fork of BLE_API_Native_IRC by Yoshihiro TSUBOI

Committer:
ktownsend
Date:
Fri Feb 21 09:33:31 2014 +0000
Revision:
17:d5600677d532
Added GATT callback support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ktownsend 17:d5600677d532 1 /* mbed Microcontroller Library
ktownsend 17:d5600677d532 2 * Copyright (c) 2006-2013 ARM Limited
ktownsend 17:d5600677d532 3 *
ktownsend 17:d5600677d532 4 * Licensed under the Apache License, Version 2.0 (the "License");
ktownsend 17:d5600677d532 5 * you may not use this file except in compliance with the License.
ktownsend 17:d5600677d532 6 * You may obtain a copy of the License at
ktownsend 17:d5600677d532 7 *
ktownsend 17:d5600677d532 8 * http://www.apache.org/licenses/LICENSE-2.0
ktownsend 17:d5600677d532 9 *
ktownsend 17:d5600677d532 10 * Unless required by applicable law or agreed to in writing, software
ktownsend 17:d5600677d532 11 * distributed under the License is distributed on an "AS IS" BASIS,
ktownsend 17:d5600677d532 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ktownsend 17:d5600677d532 13 * See the License for the specific language governing permissions and
ktownsend 17:d5600677d532 14 * limitations under the License.
ktownsend 17:d5600677d532 15 */
ktownsend 17:d5600677d532 16
ktownsend 17:d5600677d532 17 #include "nRF51GattServer.h"
ktownsend 17:d5600677d532 18 #include "mbed.h"
ktownsend 17:d5600677d532 19
ktownsend 17:d5600677d532 20 #include "common/common.h"
ktownsend 17:d5600677d532 21 #include "btle/custom/custom_helper.h"
ktownsend 17:d5600677d532 22
ktownsend 17:d5600677d532 23 /**************************************************************************/
ktownsend 17:d5600677d532 24 /*!
ktownsend 17:d5600677d532 25 @brief Adds a new service to the GATT table on the peripheral
ktownsend 17:d5600677d532 26
ktownsend 17:d5600677d532 27 @returns ble_error_t
ktownsend 17:d5600677d532 28
ktownsend 17:d5600677d532 29 @retval BLE_ERROR_NONE
ktownsend 17:d5600677d532 30 Everything executed properly
ktownsend 17:d5600677d532 31
ktownsend 17:d5600677d532 32 @section EXAMPLE
ktownsend 17:d5600677d532 33
ktownsend 17:d5600677d532 34 @code
ktownsend 17:d5600677d532 35
ktownsend 17:d5600677d532 36 @endcode
ktownsend 17:d5600677d532 37 */
ktownsend 17:d5600677d532 38 /**************************************************************************/
ktownsend 17:d5600677d532 39 ble_error_t nRF51GattServer::addService(GattService & service)
ktownsend 17:d5600677d532 40 {
ktownsend 17:d5600677d532 41 /* ToDo: Make sure we don't overflow the array, etc. */
ktownsend 17:d5600677d532 42 /* ToDo: Make sure this service UUID doesn't already exist (?) */
ktownsend 17:d5600677d532 43 /* ToDo: Basic validation */
ktownsend 17:d5600677d532 44
ktownsend 17:d5600677d532 45 /* Add the service to the nRF51 */
ktownsend 17:d5600677d532 46 ble_uuid_t uuid;
ktownsend 17:d5600677d532 47
ktownsend 17:d5600677d532 48 if (service.primaryServiceID.type == UUID::UUID_TYPE_SHORT)
ktownsend 17:d5600677d532 49 {
ktownsend 17:d5600677d532 50 /* 16-bit BLE UUID */
ktownsend 17:d5600677d532 51 uuid.type = BLE_UUID_TYPE_BLE;
ktownsend 17:d5600677d532 52 }
ktownsend 17:d5600677d532 53 else
ktownsend 17:d5600677d532 54 {
ktownsend 17:d5600677d532 55 /* 128-bit Custom UUID */
ktownsend 17:d5600677d532 56 uuid.type = custom_add_uuid_base( service.primaryServiceID.base );
ktownsend 17:d5600677d532 57 }
ktownsend 17:d5600677d532 58
ktownsend 17:d5600677d532 59 uuid.uuid = service.primaryServiceID.value;
ktownsend 17:d5600677d532 60
ktownsend 17:d5600677d532 61 ASSERT( ERROR_NONE == sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &uuid, &service.handle), BLE_ERROR_PARAM_OUT_OF_RANGE );
ktownsend 17:d5600677d532 62
ktownsend 17:d5600677d532 63 /* Add characteristics to the service */
ktownsend 17:d5600677d532 64 for (uint8_t i = 0; i < service.characteristicCount; i++)
ktownsend 17:d5600677d532 65 {
ktownsend 17:d5600677d532 66 GattCharacteristic * p_char = service.characteristics[i];
ktownsend 17:d5600677d532 67
ktownsend 17:d5600677d532 68 uuid.uuid = p_char->uuid;
ktownsend 17:d5600677d532 69 ASSERT ( ERROR_NONE == custom_add_in_characteristic(service.handle, &uuid, p_char->properties,
ktownsend 17:d5600677d532 70 NULL, p_char->lenMin, p_char->lenMax, &nrfCharacteristicHandles[characteristicCount]), BLE_ERROR_PARAM_OUT_OF_RANGE );
ktownsend 17:d5600677d532 71
ktownsend 17:d5600677d532 72 /* Update the characteristic handle */
ktownsend 17:d5600677d532 73 p_char->handle = characteristicCount;
ktownsend 17:d5600677d532 74 p_characteristics[characteristicCount++] = p_char;
ktownsend 17:d5600677d532 75 }
ktownsend 17:d5600677d532 76
ktownsend 17:d5600677d532 77 serviceCount++;
ktownsend 17:d5600677d532 78
ktownsend 17:d5600677d532 79 return BLE_ERROR_NONE;
ktownsend 17:d5600677d532 80 }
ktownsend 17:d5600677d532 81
ktownsend 17:d5600677d532 82 /**************************************************************************/
ktownsend 17:d5600677d532 83 /*!
ktownsend 17:d5600677d532 84 @brief Reads the value of a characteristic, based on the service
ktownsend 17:d5600677d532 85 and characteristic index fields
ktownsend 17:d5600677d532 86
ktownsend 17:d5600677d532 87 @param[in] charHandle
ktownsend 17:d5600677d532 88 The handle of the GattCharacteristic to read from
ktownsend 17:d5600677d532 89 @param[in] buffer
ktownsend 17:d5600677d532 90 Buffer to hold the the characteristic's value
ktownsend 17:d5600677d532 91 (raw byte array in LSB format)
ktownsend 17:d5600677d532 92 @param[in] len
ktownsend 17:d5600677d532 93 The number of bytes read into the buffer
ktownsend 17:d5600677d532 94
ktownsend 17:d5600677d532 95 @returns ble_error_t
ktownsend 17:d5600677d532 96
ktownsend 17:d5600677d532 97 @retval BLE_ERROR_NONE
ktownsend 17:d5600677d532 98 Everything executed properly
ktownsend 17:d5600677d532 99
ktownsend 17:d5600677d532 100 @section EXAMPLE
ktownsend 17:d5600677d532 101
ktownsend 17:d5600677d532 102 @code
ktownsend 17:d5600677d532 103
ktownsend 17:d5600677d532 104 @endcode
ktownsend 17:d5600677d532 105 */
ktownsend 17:d5600677d532 106 /**************************************************************************/
ktownsend 17:d5600677d532 107 ble_error_t nRF51GattServer::readValue(uint16_t charHandle, uint8_t buffer[], uint16_t len)
ktownsend 17:d5600677d532 108 {
ktownsend 17:d5600677d532 109 ASSERT( ERROR_NONE == sd_ble_gatts_value_get(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE);
ktownsend 17:d5600677d532 110
ktownsend 17:d5600677d532 111 return BLE_ERROR_NONE;
ktownsend 17:d5600677d532 112 }
ktownsend 17:d5600677d532 113
ktownsend 17:d5600677d532 114 /**************************************************************************/
ktownsend 17:d5600677d532 115 /*!
ktownsend 17:d5600677d532 116 @brief Updates the value of a characteristic, based on the service
ktownsend 17:d5600677d532 117 and characteristic index fields
ktownsend 17:d5600677d532 118
ktownsend 17:d5600677d532 119 @param[in] charHandle
ktownsend 17:d5600677d532 120 The handle of the GattCharacteristic to write to
ktownsend 17:d5600677d532 121 @param[in] buffer
ktownsend 17:d5600677d532 122 Data to use when updating the characteristic's value
ktownsend 17:d5600677d532 123 (raw byte array in LSB format)
ktownsend 17:d5600677d532 124 @param[in] len
ktownsend 17:d5600677d532 125 The number of bytes in buffer
ktownsend 17:d5600677d532 126
ktownsend 17:d5600677d532 127 @returns ble_error_t
ktownsend 17:d5600677d532 128
ktownsend 17:d5600677d532 129 @retval BLE_ERROR_NONE
ktownsend 17:d5600677d532 130 Everything executed properly
ktownsend 17:d5600677d532 131
ktownsend 17:d5600677d532 132 @section EXAMPLE
ktownsend 17:d5600677d532 133
ktownsend 17:d5600677d532 134 @code
ktownsend 17:d5600677d532 135
ktownsend 17:d5600677d532 136 @endcode
ktownsend 17:d5600677d532 137 */
ktownsend 17:d5600677d532 138 /**************************************************************************/
ktownsend 17:d5600677d532 139 ble_error_t nRF51GattServer::updateValue(uint16_t charHandle, uint8_t buffer[], uint16_t len)
ktownsend 17:d5600677d532 140 {
ktownsend 17:d5600677d532 141 if ((p_characteristics[charHandle]->properties & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) &&
ktownsend 17:d5600677d532 142 (m_connectionHandle != BLE_CONN_HANDLE_INVALID) )
ktownsend 17:d5600677d532 143 {
ktownsend 17:d5600677d532 144 /* HVX update for the characteristic value */
ktownsend 17:d5600677d532 145 ble_gatts_hvx_params_t hvx_params;
ktownsend 17:d5600677d532 146
ktownsend 17:d5600677d532 147 hvx_params.handle = nrfCharacteristicHandles[charHandle].value_handle;
ktownsend 17:d5600677d532 148 hvx_params.type = (p_characteristics[charHandle]->properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION;
ktownsend 17:d5600677d532 149 hvx_params.offset = 0;
ktownsend 17:d5600677d532 150 hvx_params.p_data = buffer;
ktownsend 17:d5600677d532 151 hvx_params.p_len = &len;
ktownsend 17:d5600677d532 152
ktownsend 17:d5600677d532 153 error_t error = (error_t) sd_ble_gatts_hvx(m_connectionHandle, &hvx_params);
ktownsend 17:d5600677d532 154
ktownsend 17:d5600677d532 155 /* ERROR_INVALID_STATE, ERROR_BUSY, ERROR_GATTS_SYS_ATTR_MISSING and ERROR_NO_TX_BUFFERS the ATT table has been updated. */
ktownsend 17:d5600677d532 156 if ( (error != ERROR_NONE ) && (error != ERROR_INVALID_STATE) &&
ktownsend 17:d5600677d532 157 (error != ERROR_BLE_NO_TX_BUFFERS ) && (error != ERROR_BUSY ) &&
ktownsend 17:d5600677d532 158 (error != ERROR_BLEGATTS_SYS_ATTR_MISSING ) )
ktownsend 17:d5600677d532 159 {
ktownsend 17:d5600677d532 160 ASSERT_INT( ERROR_NONE, sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE );
ktownsend 17:d5600677d532 161 }
ktownsend 17:d5600677d532 162 } else
ktownsend 17:d5600677d532 163 {
ktownsend 17:d5600677d532 164 ASSERT_INT( ERROR_NONE, sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), BLE_ERROR_PARAM_OUT_OF_RANGE );
ktownsend 17:d5600677d532 165 }
ktownsend 17:d5600677d532 166
ktownsend 17:d5600677d532 167 return BLE_ERROR_NONE;
ktownsend 17:d5600677d532 168 }
ktownsend 17:d5600677d532 169
ktownsend 17:d5600677d532 170 /**************************************************************************/
ktownsend 17:d5600677d532 171 /*!
ktownsend 17:d5600677d532 172 @brief Callback handler for events getting pushed up from the SD
ktownsend 17:d5600677d532 173 */
ktownsend 17:d5600677d532 174 /**************************************************************************/
ktownsend 17:d5600677d532 175 void nRF51GattServer::hwCallback(ble_evt_t * p_ble_evt)
ktownsend 17:d5600677d532 176 {
ktownsend 17:d5600677d532 177 uint16_t handle_value;
ktownsend 17:d5600677d532 178 GattServerEvents::gattEvent_t event;
ktownsend 17:d5600677d532 179
ktownsend 17:d5600677d532 180 switch (p_ble_evt->header.evt_id)
ktownsend 17:d5600677d532 181 {
ktownsend 17:d5600677d532 182 case BLE_GATTS_EVT_WRITE:
ktownsend 17:d5600677d532 183 /* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */
ktownsend 17:d5600677d532 184
ktownsend 17:d5600677d532 185 /* 1.) Handle CCCD changes */
ktownsend 17:d5600677d532 186 handle_value = p_ble_evt->evt.gatts_evt.params.write.handle;
ktownsend 17:d5600677d532 187 for(uint8_t i=0; i<characteristicCount; i++)
ktownsend 17:d5600677d532 188 {
ktownsend 17:d5600677d532 189 if ( (p_characteristics[i]->properties & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) &&
ktownsend 17:d5600677d532 190 (nrfCharacteristicHandles[i].cccd_handle == handle_value) )
ktownsend 17:d5600677d532 191 {
ktownsend 17:d5600677d532 192 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 */
ktownsend 17:d5600677d532 193
ktownsend 17:d5600677d532 194 if ( ((p_characteristics[i]->properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION )) ||
ktownsend 17:d5600677d532 195 ((p_characteristics[i]->properties & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY ) && (cccd_value & BLE_GATT_HVX_NOTIFICATION)))
ktownsend 17:d5600677d532 196 {
ktownsend 17:d5600677d532 197 event = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
ktownsend 17:d5600677d532 198 } else
ktownsend 17:d5600677d532 199 {
ktownsend 17:d5600677d532 200 event = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
ktownsend 17:d5600677d532 201 }
ktownsend 17:d5600677d532 202
ktownsend 17:d5600677d532 203 handleEvent(event, i);
ktownsend 17:d5600677d532 204 return;
ktownsend 17:d5600677d532 205 }
ktownsend 17:d5600677d532 206 }
ktownsend 17:d5600677d532 207
ktownsend 17:d5600677d532 208 /* 2.) Changes to the characteristic value will be handled with other events below */
ktownsend 17:d5600677d532 209 event = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
ktownsend 17:d5600677d532 210 break;
ktownsend 17:d5600677d532 211
ktownsend 17:d5600677d532 212 case BLE_GATTS_EVT_HVC:
ktownsend 17:d5600677d532 213 /* Indication confirmation received */
ktownsend 17:d5600677d532 214 event = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED;
ktownsend 17:d5600677d532 215 handle_value = p_ble_evt->evt.gatts_evt.params.hvc.handle;
ktownsend 17:d5600677d532 216 break;
ktownsend 17:d5600677d532 217
ktownsend 17:d5600677d532 218 default:
ktownsend 17:d5600677d532 219 return;
ktownsend 17:d5600677d532 220 }
ktownsend 17:d5600677d532 221
ktownsend 17:d5600677d532 222 /* Find index (charHandle) in the pool */
ktownsend 17:d5600677d532 223 for(uint8_t i=0; i<characteristicCount; i++)
ktownsend 17:d5600677d532 224 {
ktownsend 17:d5600677d532 225 if (nrfCharacteristicHandles[i].value_handle == handle_value)
ktownsend 17:d5600677d532 226 {
ktownsend 17:d5600677d532 227 handleEvent(event, i);
ktownsend 17:d5600677d532 228 break;
ktownsend 17:d5600677d532 229 }
ktownsend 17:d5600677d532 230 }
ktownsend 17:d5600677d532 231 }