Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nRF51822 by
nRF51GattServer.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "nRF51GattServer.h" 00018 #include "mbed.h" 00019 00020 #include "common/common.h" 00021 #include "btle/custom/custom_helper.h" 00022 00023 #include "nRF51Gap.h" 00024 00025 /**************************************************************************/ 00026 /*! 00027 @brief Adds a new service to the GATT table on the peripheral 00028 00029 @returns ble_error_t 00030 00031 @retval BLE_ERROR_NONE 00032 Everything executed properly 00033 00034 @section EXAMPLE 00035 00036 @code 00037 00038 @endcode 00039 */ 00040 /**************************************************************************/ 00041 ble_error_t nRF51GattServer::addService(GattService &service) 00042 { 00043 /* ToDo: Make sure we don't overflow the array, etc. */ 00044 /* ToDo: Make sure this service UUID doesn't already exist (?) */ 00045 /* ToDo: Basic validation */ 00046 00047 /* Add the service to the nRF51 */ 00048 ble_uuid_t nordicUUID; 00049 nordicUUID = custom_convert_to_nordic_uuid(service.getUUID()); 00050 00051 uint16_t serviceHandle; 00052 ASSERT( ERROR_NONE == 00053 sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, 00054 &nordicUUID, 00055 &serviceHandle), 00056 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00057 service.setHandle(serviceHandle); 00058 00059 /* Add characteristics to the service */ 00060 for (uint8_t i = 0; i < service.getCharacteristicCount(); i++) { 00061 GattCharacteristic *p_char = service.getCharacteristic(i); 00062 00063 /* Skip any incompletely defined, read-only characteristics. */ 00064 if ((p_char->getValueAttribute().getValuePtr() == NULL) && 00065 (p_char->getValueAttribute().getInitialLength() == 0) && 00066 (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) { 00067 continue; 00068 } 00069 00070 nordicUUID = custom_convert_to_nordic_uuid(p_char->getValueAttribute().getUUID()); 00071 00072 ASSERT ( ERROR_NONE == 00073 custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID, 00074 &nordicUUID, 00075 p_char->getProperties(), 00076 p_char->getValueAttribute().getValuePtr(), 00077 p_char->getValueAttribute().getInitialLength(), 00078 p_char->getValueAttribute().getMaxLength(), 00079 p_char->isReadAuthorizationEnabled(), 00080 p_char->isWriteAuthorizationEnabled(), 00081 &nrfCharacteristicHandles[characteristicCount]), 00082 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00083 00084 /* Update the characteristic handle */ 00085 uint16_t charHandle = characteristicCount; 00086 p_characteristics[characteristicCount++] = p_char; 00087 00088 p_char->getValueAttribute().setHandle(charHandle); 00089 00090 /* Add optional descriptors if any */ 00091 /* ToDo: Make sure we don't overflow the array */ 00092 for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) { 00093 GattAttribute *p_desc = p_char->getDescriptor(j); 00094 00095 nordicUUID = custom_convert_to_nordic_uuid(p_desc->getUUID()); 00096 00097 ASSERT ( ERROR_NONE == 00098 custom_add_in_descriptor(BLE_GATT_HANDLE_INVALID, 00099 &nordicUUID, 00100 p_desc->getValuePtr(), 00101 p_desc->getInitialLength(), 00102 p_desc->getMaxLength(), 00103 &nrfDescriptorHandles[descriptorCount]), 00104 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00105 00106 uint16_t descHandle = descriptorCount; 00107 p_descriptors[descriptorCount++] = p_desc; 00108 p_desc->setHandle(descHandle); 00109 } 00110 } 00111 00112 serviceCount++; 00113 00114 return BLE_ERROR_NONE; 00115 } 00116 00117 /**************************************************************************/ 00118 /*! 00119 @brief Reads the value of a characteristic, based on the service 00120 and characteristic index fields 00121 00122 @param[in] charHandle 00123 The handle of the GattCharacteristic to read from 00124 @param[in] buffer 00125 Buffer to hold the the characteristic's value 00126 (raw byte array in LSB format) 00127 @param[in] len 00128 The number of bytes read into the buffer 00129 00130 @returns ble_error_t 00131 00132 @retval BLE_ERROR_NONE 00133 Everything executed properly 00134 00135 @section EXAMPLE 00136 00137 @code 00138 00139 @endcode 00140 */ 00141 /**************************************************************************/ 00142 ble_error_t nRF51GattServer::readValue(GattAttribute::Handle_t charHandle, uint8_t buffer[], uint16_t *const lengthP) 00143 { 00144 ASSERT( ERROR_NONE == 00145 sd_ble_gatts_value_get(nrfCharacteristicHandles[charHandle].value_handle, 0, lengthP, buffer), 00146 BLE_ERROR_PARAM_OUT_OF_RANGE); 00147 00148 return BLE_ERROR_NONE; 00149 } 00150 00151 /**************************************************************************/ 00152 /*! 00153 @brief Updates the value of a characteristic, based on the service 00154 and characteristic index fields 00155 00156 @param[in] charHandle 00157 The handle of the GattCharacteristic to write to 00158 @param[in] buffer 00159 Data to use when updating the characteristic's value 00160 (raw byte array in LSB format) 00161 @param[in] len 00162 The number of bytes in buffer 00163 00164 @returns ble_error_t 00165 00166 @retval BLE_ERROR_NONE 00167 Everything executed properly 00168 00169 @section EXAMPLE 00170 00171 @code 00172 00173 @endcode 00174 */ 00175 /**************************************************************************/ 00176 ble_error_t nRF51GattServer::updateValue(GattAttribute::Handle_t charHandle, const uint8_t buffer[], uint16_t len, bool localOnly) 00177 { 00178 uint16_t gapConnectionHandle = nRF51Gap::getInstance().getConnectionHandle(); 00179 ble_error_t returnValue = BLE_ERROR_NONE; 00180 00181 if (localOnly) { 00182 /* Only update locally regardless of notify/indicate */ 00183 ASSERT_INT( ERROR_NONE, 00184 sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), 00185 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00186 return BLE_ERROR_NONE; 00187 } 00188 00189 if ((p_characteristics[charHandle]->getProperties() & 00190 (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | 00191 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) && 00192 (gapConnectionHandle != BLE_CONN_HANDLE_INVALID)) { 00193 /* HVX update for the characteristic value */ 00194 ble_gatts_hvx_params_t hvx_params; 00195 00196 hvx_params.handle = nrfCharacteristicHandles[charHandle].value_handle; 00197 hvx_params.type = 00198 (p_characteristics[charHandle]->getProperties() & 00199 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? 00200 BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION; 00201 hvx_params.offset = 0; 00202 hvx_params.p_data = const_cast<uint8_t *>(buffer); 00203 hvx_params.p_len = &len; 00204 00205 error_t error = (error_t) sd_ble_gatts_hvx(gapConnectionHandle, &hvx_params); 00206 00207 /* ERROR_INVALID_STATE, ERROR_BUSY, ERROR_GATTS_SYS_ATTR_MISSING and 00208 *ERROR_NO_TX_BUFFERS the ATT table has been updated. */ 00209 if ((error != ERROR_NONE) && (error != ERROR_INVALID_STATE) && 00210 (error != ERROR_BLE_NO_TX_BUFFERS) && (error != ERROR_BUSY) && 00211 (error != ERROR_BLEGATTS_SYS_ATTR_MISSING)) { 00212 ASSERT_INT( ERROR_NONE, 00213 sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), 00214 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00215 } 00216 00217 /* Notifications consume application buffers. The return value can 00218 be used for resending notifications. 00219 */ 00220 if (error != ERROR_NONE) { 00221 returnValue = BLE_STACK_BUSY; 00222 } 00223 } else { 00224 ASSERT_INT( ERROR_NONE, 00225 sd_ble_gatts_value_set(nrfCharacteristicHandles[charHandle].value_handle, 0, &len, buffer), 00226 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00227 } 00228 00229 return returnValue; 00230 } 00231 00232 /**************************************************************************/ 00233 /*! 00234 @brief Callback handler for events getting pushed up from the SD 00235 */ 00236 /**************************************************************************/ 00237 void nRF51GattServer::hwCallback(ble_evt_t *p_ble_evt) 00238 { 00239 uint16_t handle_value; 00240 GattServerEvents::gattEvent_t eventType; 00241 const ble_gatts_evt_t *gattsEventP = &p_ble_evt->evt.gatts_evt; 00242 00243 switch (p_ble_evt->header.evt_id) { 00244 case BLE_GATTS_EVT_WRITE: 00245 /* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */ 00246 00247 /* 1.) Handle CCCD changes */ 00248 handle_value = gattsEventP->params.write.handle; 00249 for (uint8_t i = 0; i<characteristicCount; i++) { 00250 if ((p_characteristics[i]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) && 00251 (nrfCharacteristicHandles[i].cccd_handle == handle_value)) { 00252 uint16_t cccd_value = 00253 (gattsEventP->params.write.data[1] << 8) | 00254 gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */ 00255 00256 if (((p_characteristics[i]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) || 00257 ((p_characteristics[i]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) { 00258 eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED; 00259 } else { 00260 eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED; 00261 } 00262 00263 handleEvent(eventType, i); 00264 return; 00265 } 00266 } 00267 00268 /* 2.) Changes to the characteristic value will be handled with other events below */ 00269 eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN; 00270 break; 00271 00272 case BLE_GATTS_EVT_HVC: 00273 /* Indication confirmation received */ 00274 eventType = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED; 00275 handle_value = gattsEventP->params.hvc.handle; 00276 break; 00277 00278 case BLE_EVT_TX_COMPLETE: { 00279 handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count); 00280 return; 00281 } 00282 00283 case BLE_GATTS_EVT_SYS_ATTR_MISSING: 00284 sd_ble_gatts_sys_attr_set(gattsEventP->conn_handle, NULL, 0); 00285 return; 00286 00287 case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: 00288 switch (gattsEventP->params.authorize_request.type) { 00289 case BLE_GATTS_AUTHORIZE_TYPE_READ: 00290 eventType = GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ; 00291 handle_value = gattsEventP->params.authorize_request.request.read.handle; 00292 break; 00293 case BLE_GATTS_AUTHORIZE_TYPE_WRITE: 00294 eventType = GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ; 00295 handle_value = gattsEventP->params.authorize_request.request.write.handle; 00296 break; 00297 default: 00298 return; 00299 } 00300 break; 00301 00302 default: 00303 return; 00304 } 00305 00306 /* Find index (charHandle) in the pool */ 00307 for (uint8_t i = 0; i < characteristicCount; i++) { 00308 if (nrfCharacteristicHandles[i].value_handle == handle_value) { 00309 switch (eventType) { 00310 case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { 00311 GattCharacteristicWriteCBParams cbParams = { 00312 .charHandle = i, 00313 .op = static_cast<GattCharacteristicWriteCBParams::Type>(gattsEventP->params.write.op), 00314 .offset = gattsEventP->params.write.offset, 00315 .len = gattsEventP->params.write.len, 00316 .data = gattsEventP->params.write.data 00317 }; 00318 handleDataWrittenEvent(&cbParams); 00319 break; 00320 } 00321 case GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ: { 00322 GattCharacteristicWriteAuthCBParams cbParams = { 00323 .charHandle = i, 00324 .offset = gattsEventP->params.authorize_request.request.write.offset, 00325 .len = gattsEventP->params.authorize_request.request.write.len, 00326 .data = gattsEventP->params.authorize_request.request.write.data, 00327 }; 00328 ble_gatts_rw_authorize_reply_params_t reply = { 00329 .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, 00330 .params = { 00331 .write = { 00332 .gatt_status = p_characteristics[i]->authorizeWrite(&cbParams) 00333 } 00334 } 00335 }; 00336 sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); 00337 00338 /* 00339 * If write-authorization is enabled for a characteristic, 00340 * AUTHORIZATION_REQ event (if replied with true) is *not* 00341 * followed by another DATA_WRITTEN event; so we still need 00342 * to invoke handleDataWritten(), much the same as we would 00343 * have done if write-authorization had not been enabled. 00344 */ 00345 if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { 00346 GattCharacteristicWriteCBParams cbParams = { 00347 .charHandle = i, 00348 .op = static_cast<GattCharacteristicWriteCBParams::Type>(gattsEventP->params.authorize_request.request.write.op), 00349 .offset = gattsEventP->params.authorize_request.request.write.offset, 00350 .len = gattsEventP->params.authorize_request.request.write.len, 00351 .data = gattsEventP->params.authorize_request.request.write.data, 00352 }; 00353 handleDataWrittenEvent(&cbParams); 00354 } 00355 break; 00356 } 00357 case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: { 00358 GattCharacteristicReadAuthCBParams cbParams = { 00359 .charHandle = i, 00360 .offset = gattsEventP->params.authorize_request.request.read.offset, 00361 .len = 0, 00362 .data = NULL 00363 }; 00364 00365 ble_gatts_rw_authorize_reply_params_t reply = { 00366 .type = BLE_GATTS_AUTHORIZE_TYPE_READ, 00367 .params = { 00368 .read = { 00369 .gatt_status = p_characteristics[i]->authorizeRead(&cbParams) 00370 } 00371 } 00372 }; 00373 00374 if (cbParams.authorizationReply == BLE_GATT_STATUS_SUCCESS) { 00375 if (cbParams.data != NULL) { 00376 reply.params.read.update = 1; 00377 reply.params.read.offset = cbParams.offset; 00378 reply.params.read.len = cbParams.len; 00379 reply.params.read.p_data = cbParams.data; 00380 } 00381 } 00382 00383 sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); 00384 break; 00385 } 00386 00387 default: 00388 handleEvent(eventType, i); 00389 break; 00390 } 00391 } 00392 } 00393 } 00394 00395 ble_error_t 00396 nRF51GattServer::initializeGATTDatabase(void) 00397 { 00398 /* Empty. Services are populated in the GattDatabase through addService(). */ 00399 return BLE_ERROR_NONE; 00400 }
Generated on Tue Jul 12 2022 16:21:03 by
