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 nRF51GattServer &nRF51GattServer::getInstance(void) { 00026 static nRF51GattServer m_instance; 00027 return m_instance; 00028 } 00029 00030 /**************************************************************************/ 00031 /*! 00032 @brief Adds a new service to the GATT table on the peripheral 00033 00034 @returns ble_error_t 00035 00036 @retval BLE_ERROR_NONE 00037 Everything executed properly 00038 00039 @section EXAMPLE 00040 00041 @code 00042 00043 @endcode 00044 */ 00045 /**************************************************************************/ 00046 ble_error_t nRF51GattServer::addService(GattService &service) 00047 { 00048 /* ToDo: Make sure we don't overflow the array, etc. */ 00049 /* ToDo: Make sure this service UUID doesn't already exist (?) */ 00050 /* ToDo: Basic validation */ 00051 00052 /* Add the service to the nRF51 */ 00053 ble_uuid_t nordicUUID; 00054 nordicUUID = custom_convert_to_nordic_uuid(service.getUUID()); 00055 00056 uint16_t serviceHandle; 00057 ASSERT( ERROR_NONE == 00058 sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, 00059 &nordicUUID, 00060 &serviceHandle), 00061 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00062 service.setHandle(serviceHandle); 00063 00064 /* Add characteristics to the service */ 00065 for (uint8_t i = 0; i < service.getCharacteristicCount(); i++) { 00066 GattCharacteristic *p_char = service.getCharacteristic(i); 00067 00068 /* Skip any incompletely defined, read-only characteristics. */ 00069 if ((p_char->getValueAttribute().getValuePtr() == NULL) && 00070 (p_char->getValueAttribute().getInitialLength() == 0) && 00071 (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) { 00072 continue; 00073 } 00074 00075 nordicUUID = custom_convert_to_nordic_uuid(p_char->getValueAttribute().getUUID()); 00076 00077 /* The user-description descriptor is a special case which needs to be 00078 * handled at the time of adding the characteristic. The following block 00079 * is meant to discover its presence. */ 00080 const uint8_t *userDescriptionDescriptorValuePtr = NULL; 00081 uint16_t userDescriptionDescriptorValueLen = 0; 00082 for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) { 00083 GattAttribute *p_desc = p_char->getDescriptor(j); 00084 if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) { 00085 userDescriptionDescriptorValuePtr = p_desc->getValuePtr(); 00086 userDescriptionDescriptorValueLen = p_desc->getLength(); 00087 } 00088 } 00089 00090 ASSERT ( ERROR_NONE == 00091 custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID, 00092 &nordicUUID, 00093 p_char->getProperties(), 00094 p_char->getRequiredSecurity(), 00095 p_char->getValueAttribute().getValuePtr(), 00096 p_char->getValueAttribute().getInitialLength(), 00097 p_char->getValueAttribute().getMaxLength(), 00098 userDescriptionDescriptorValuePtr, 00099 userDescriptionDescriptorValueLen, 00100 p_char->isReadAuthorizationEnabled(), 00101 p_char->isWriteAuthorizationEnabled(), 00102 &nrfCharacteristicHandles[characteristicCount]), 00103 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00104 00105 /* Update the characteristic handle */ 00106 uint16_t charHandle = characteristicCount; 00107 p_characteristics[characteristicCount++] = p_char; 00108 00109 p_char->getValueAttribute().setHandle(charHandle); 00110 00111 /* Add optional descriptors if any */ 00112 /* ToDo: Make sure we don't overflow the array */ 00113 for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) { 00114 GattAttribute *p_desc = p_char->getDescriptor(j); 00115 /* skip the user-description-descriptor here; this has already been handled when adding the characteristic (above). */ 00116 if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) { 00117 continue; 00118 } 00119 00120 nordicUUID = custom_convert_to_nordic_uuid(p_desc->getUUID()); 00121 00122 ASSERT(ERROR_NONE == 00123 custom_add_in_descriptor(BLE_GATT_HANDLE_INVALID, 00124 &nordicUUID, 00125 p_desc->getValuePtr(), 00126 p_desc->getInitialLength(), 00127 p_desc->getMaxLength(), 00128 &nrfDescriptorHandles[descriptorCount]), 00129 BLE_ERROR_PARAM_OUT_OF_RANGE); 00130 00131 uint16_t descHandle = descriptorCount; 00132 p_descriptors[descriptorCount++] = p_desc; 00133 p_desc->setHandle(descHandle); 00134 } 00135 } 00136 00137 serviceCount++; 00138 00139 return BLE_ERROR_NONE; 00140 } 00141 00142 /**************************************************************************/ 00143 /*! 00144 @brief Reads the value of a characteristic, based on the service 00145 and characteristic index fields 00146 00147 @param[in] attributeHandle 00148 The handle of the GattCharacteristic to read from 00149 @param[in] buffer 00150 Buffer to hold the the characteristic's value 00151 (raw byte array in LSB format) 00152 @param[in/out] len 00153 input: Length in bytes to be read. 00154 output: Total length of attribute value upon successful return. 00155 00156 @returns ble_error_t 00157 00158 @retval BLE_ERROR_NONE 00159 Everything executed properly 00160 */ 00161 /**************************************************************************/ 00162 ble_error_t nRF51GattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) 00163 { 00164 return read(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP); 00165 } 00166 00167 ble_error_t nRF51GattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) 00168 { 00169 ble_gatts_value_t value = { 00170 .len = *lengthP, 00171 .offset = 0, 00172 .p_value = buffer, 00173 }; 00174 00175 ASSERT( ERROR_NONE == 00176 sd_ble_gatts_value_get(connectionHandle, nrfCharacteristicHandles[attributeHandle].value_handle, &value), 00177 BLE_ERROR_PARAM_OUT_OF_RANGE); 00178 *lengthP = value.len; 00179 00180 return BLE_ERROR_NONE; 00181 } 00182 00183 /**************************************************************************/ 00184 /*! 00185 @brief Updates the value of a characteristic, based on the service 00186 and characteristic index fields 00187 00188 @param[in] charHandle 00189 The handle of the GattCharacteristic to write to 00190 @param[in] buffer 00191 Data to use when updating the characteristic's value 00192 (raw byte array in LSB format) 00193 @param[in] len 00194 The number of bytes in buffer 00195 00196 @returns ble_error_t 00197 00198 @retval BLE_ERROR_NONE 00199 Everything executed properly 00200 */ 00201 /**************************************************************************/ 00202 ble_error_t nRF51GattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) 00203 { 00204 return write(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, len, localOnly); 00205 } 00206 00207 ble_error_t nRF51GattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) 00208 { 00209 uint16_t gapConnectionHandle = nRF51Gap::getInstance().getConnectionHandle(); 00210 ble_error_t returnValue = BLE_ERROR_NONE; 00211 00212 ble_gatts_value_t value = { 00213 .len = len, 00214 .offset = 0, 00215 .p_value = const_cast<uint8_t *>(buffer), 00216 }; 00217 00218 if (localOnly) { 00219 /* Only update locally regardless of notify/indicate */ 00220 ASSERT_INT( ERROR_NONE, 00221 sd_ble_gatts_value_set(connectionHandle, nrfCharacteristicHandles[attributeHandle].value_handle, &value), 00222 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00223 return BLE_ERROR_NONE; 00224 } 00225 00226 if ((p_characteristics[attributeHandle]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) && 00227 (gapConnectionHandle != connectionHandle)) { 00228 /* HVX update for the characteristic value */ 00229 ble_gatts_hvx_params_t hvx_params; 00230 00231 hvx_params.handle = nrfCharacteristicHandles[attributeHandle].value_handle; 00232 hvx_params.type = 00233 (p_characteristics[attributeHandle]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION; 00234 hvx_params.offset = 0; 00235 hvx_params.p_data = const_cast<uint8_t *>(buffer); 00236 hvx_params.p_len = &len; 00237 00238 error_t error = (error_t) sd_ble_gatts_hvx(gapConnectionHandle, &hvx_params); 00239 00240 /* ERROR_INVALID_STATE, ERROR_BUSY, ERROR_GATTS_SYS_ATTR_MISSING and ERROR_NO_TX_BUFFERS the ATT table has been updated. */ 00241 if ((error != ERROR_NONE) && (error != ERROR_INVALID_STATE) && (error != ERROR_BLE_NO_TX_BUFFERS) && (error != ERROR_BUSY) && (error != ERROR_BLEGATTS_SYS_ATTR_MISSING)) { 00242 ASSERT_INT( ERROR_NONE, 00243 sd_ble_gatts_value_set(connectionHandle, nrfCharacteristicHandles[attributeHandle].value_handle, &value), 00244 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00245 } 00246 00247 /* Notifications consume application buffers. The return value can 00248 be used for resending notifications. 00249 */ 00250 if (error != ERROR_NONE) { 00251 returnValue = BLE_STACK_BUSY; 00252 } 00253 } else { 00254 ASSERT_INT( ERROR_NONE, 00255 sd_ble_gatts_value_set(connectionHandle, nrfCharacteristicHandles[attributeHandle].value_handle, &value), 00256 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00257 } 00258 00259 return returnValue; 00260 } 00261 00262 /**************************************************************************/ 00263 /*! 00264 @brief Callback handler for events getting pushed up from the SD 00265 */ 00266 /**************************************************************************/ 00267 void nRF51GattServer::hwCallback(ble_evt_t *p_ble_evt) 00268 { 00269 GattAttribute::Handle_t handle_value; 00270 GattServerEvents::gattEvent_t eventType; 00271 const ble_gatts_evt_t *gattsEventP = &p_ble_evt->evt.gatts_evt; 00272 00273 switch (p_ble_evt->header.evt_id) { 00274 case BLE_GATTS_EVT_WRITE: 00275 /* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */ 00276 00277 /* 1.) Handle CCCD changes */ 00278 handle_value = gattsEventP->params.write.handle; 00279 for (uint8_t i = 0; i < characteristicCount; i++) { 00280 if ((p_characteristics[i]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) && 00281 (nrfCharacteristicHandles[i].cccd_handle == handle_value)) { 00282 uint16_t cccd_value = (gattsEventP->params.write.data[1] << 8) | gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */ 00283 00284 if (((p_characteristics[i]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) || 00285 ((p_characteristics[i]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) { 00286 eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED; 00287 } else { 00288 eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED; 00289 } 00290 00291 handleEvent(eventType, handle_value); 00292 return; 00293 } 00294 } 00295 00296 /* 2.) Changes to the characteristic value will be handled with other events below */ 00297 eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN; 00298 break; 00299 00300 case BLE_GATTS_EVT_HVC: 00301 /* Indication confirmation received */ 00302 eventType = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED; 00303 handle_value = gattsEventP->params.hvc.handle; 00304 break; 00305 00306 case BLE_EVT_TX_COMPLETE: { 00307 handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count); 00308 return; 00309 } 00310 00311 case BLE_GATTS_EVT_SYS_ATTR_MISSING: 00312 sd_ble_gatts_sys_attr_set(gattsEventP->conn_handle, NULL, 0, 0); 00313 return; 00314 00315 case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: 00316 switch (gattsEventP->params.authorize_request.type) { 00317 case BLE_GATTS_AUTHORIZE_TYPE_READ: 00318 eventType = GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ; 00319 handle_value = gattsEventP->params.authorize_request.request.read.handle; 00320 break; 00321 case BLE_GATTS_AUTHORIZE_TYPE_WRITE: 00322 eventType = GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ; 00323 handle_value = gattsEventP->params.authorize_request.request.write.handle; 00324 break; 00325 default: 00326 return; 00327 } 00328 break; 00329 00330 default: 00331 return; 00332 } 00333 00334 /* Find index (charHandle) in the pool */ 00335 for (uint8_t i = 0; i < characteristicCount; i++) { 00336 if (nrfCharacteristicHandles[i].value_handle == handle_value) { 00337 switch (eventType) { 00338 case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { 00339 GattWriteCallbackParams cbParams = { 00340 .handle = i, 00341 .writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.write.op), 00342 .offset = gattsEventP->params.write.offset, 00343 .len = gattsEventP->params.write.len, 00344 .data = gattsEventP->params.write.data 00345 }; 00346 handleDataWrittenEvent(&cbParams); 00347 break; 00348 } 00349 case GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ: { 00350 GattWriteAuthCallbackParams cbParams = { 00351 .handle = i, 00352 .offset = gattsEventP->params.authorize_request.request.write.offset, 00353 .len = gattsEventP->params.authorize_request.request.write.len, 00354 .data = gattsEventP->params.authorize_request.request.write.data, 00355 }; 00356 ble_gatts_rw_authorize_reply_params_t reply = { 00357 .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, 00358 .params = { 00359 .write = { 00360 .gatt_status = p_characteristics[i]->authorizeWrite(&cbParams) 00361 } 00362 } 00363 }; 00364 sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); 00365 00366 /* 00367 * If write-authorization is enabled for a characteristic, 00368 * AUTHORIZATION_REQ event (if replied with true) is *not* 00369 * followed by another DATA_WRITTEN event; so we still need 00370 * to invoke handleDataWritten(), much the same as we would 00371 * have done if write-authorization had not been enabled. 00372 */ 00373 if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { 00374 GattWriteCallbackParams cbParams = { 00375 .handle = i, 00376 .writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.authorize_request.request.write.op), 00377 .offset = gattsEventP->params.authorize_request.request.write.offset, 00378 .len = gattsEventP->params.authorize_request.request.write.len, 00379 .data = gattsEventP->params.authorize_request.request.write.data, 00380 }; 00381 handleDataWrittenEvent(&cbParams); 00382 } 00383 break; 00384 } 00385 case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: { 00386 GattReadAuthCallbackParams cbParams = { 00387 .handle = i, 00388 .offset = gattsEventP->params.authorize_request.request.read.offset, 00389 .len = 0, 00390 .data = NULL 00391 }; 00392 00393 ble_gatts_rw_authorize_reply_params_t reply = { 00394 .type = BLE_GATTS_AUTHORIZE_TYPE_READ, 00395 .params = { 00396 .read = { 00397 .gatt_status = p_characteristics[i]->authorizeRead(&cbParams) 00398 } 00399 } 00400 }; 00401 00402 if (cbParams.authorizationReply == BLE_GATT_STATUS_SUCCESS) { 00403 if (cbParams.data != NULL) { 00404 reply.params.read.update = 1; 00405 reply.params.read.offset = cbParams.offset; 00406 reply.params.read.len = cbParams.len; 00407 reply.params.read.p_data = cbParams.data; 00408 } 00409 } 00410 00411 sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); 00412 break; 00413 } 00414 00415 default: 00416 handleEvent(eventType, handle_value); 00417 break; 00418 } 00419 } 00420 } 00421 }
Generated on Tue Jul 12 2022 15:45:40 by
