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
nRF5xGattServer.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 "nRF5xGattServer.h" 00018 #ifdef YOTTA_CFG_MBED_OS 00019 #include "mbed-drivers/mbed.h" 00020 #else 00021 #include "mbed.h" 00022 #endif 00023 00024 #include "common/common.h " 00025 #include "btle/custom/custom_helper.h" 00026 00027 #include "nRF5xn.h" 00028 00029 /**************************************************************************/ 00030 /*! 00031 @brief Adds a new service to the GATT table on the peripheral 00032 00033 @returns ble_error_t 00034 00035 @retval BLE_ERROR_NONE 00036 Everything executed properly 00037 00038 @section EXAMPLE 00039 00040 @code 00041 00042 @endcode 00043 */ 00044 /**************************************************************************/ 00045 ble_error_t nRF5xGattServer::addService(GattService &service) 00046 { 00047 /* ToDo: Make sure this service UUID doesn't already exist (?) */ 00048 /* ToDo: Basic validation */ 00049 00050 /* Add the service to the nRF51 */ 00051 ble_uuid_t nordicUUID; 00052 nordicUUID = custom_convert_to_nordic_uuid(service.getUUID()); 00053 00054 uint16_t serviceHandle; 00055 ASSERT( ERROR_NONE == 00056 sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, 00057 &nordicUUID, 00058 &serviceHandle), 00059 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00060 service.setHandle(serviceHandle); 00061 00062 /* Add characteristics to the service */ 00063 for (uint8_t i = 0; i < service.getCharacteristicCount(); i++) { 00064 if (characteristicCount >= BLE_TOTAL_CHARACTERISTICS) { 00065 return BLE_ERROR_NO_MEM; 00066 } 00067 GattCharacteristic *p_char = service.getCharacteristic(i); 00068 00069 /* Skip any incompletely defined, read-only characteristics. */ 00070 if ((p_char->getValueAttribute().getValuePtr() == NULL) && 00071 (p_char->getValueAttribute().getLength() == 0) && 00072 (p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) { 00073 continue; 00074 } 00075 00076 nordicUUID = custom_convert_to_nordic_uuid(p_char->getValueAttribute().getUUID()); 00077 00078 /* The user-description descriptor is a special case which needs to be 00079 * handled at the time of adding the characteristic. The following block 00080 * is meant to discover its presence. */ 00081 const uint8_t *userDescriptionDescriptorValuePtr = NULL; 00082 uint16_t userDescriptionDescriptorValueLen = 0; 00083 for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) { 00084 GattAttribute *p_desc = p_char->getDescriptor(j); 00085 if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) { 00086 userDescriptionDescriptorValuePtr = p_desc->getValuePtr(); 00087 userDescriptionDescriptorValueLen = p_desc->getLength(); 00088 } 00089 } 00090 00091 ASSERT ( ERROR_NONE == 00092 custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID, 00093 &nordicUUID, 00094 p_char->getProperties(), 00095 p_char->getRequiredSecurity(), 00096 p_char->getValueAttribute().getValuePtr(), 00097 p_char->getValueAttribute().getLength(), 00098 p_char->getValueAttribute().getMaxLength(), 00099 p_char->getValueAttribute().hasVariableLength(), 00100 userDescriptionDescriptorValuePtr, 00101 userDescriptionDescriptorValueLen, 00102 p_char->isReadAuthorizationEnabled(), 00103 p_char->isWriteAuthorizationEnabled(), 00104 &nrfCharacteristicHandles[characteristicCount]), 00105 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00106 00107 /* Update the characteristic handle */ 00108 p_characteristics[characteristicCount] = p_char; 00109 p_char->getValueAttribute().setHandle(nrfCharacteristicHandles[characteristicCount].value_handle); 00110 characteristicCount++; 00111 00112 /* Add optional descriptors if any */ 00113 for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) { 00114 if (descriptorCount >= BLE_TOTAL_DESCRIPTORS) { 00115 return BLE_ERROR_NO_MEM; 00116 } 00117 00118 GattAttribute *p_desc = p_char->getDescriptor(j); 00119 /* skip the user-description-descriptor here; this has already been handled when adding the characteristic (above). */ 00120 if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) { 00121 continue; 00122 } 00123 00124 nordicUUID = custom_convert_to_nordic_uuid(p_desc->getUUID()); 00125 00126 ASSERT(ERROR_NONE == 00127 custom_add_in_descriptor(BLE_GATT_HANDLE_INVALID, 00128 &nordicUUID, 00129 p_desc->getValuePtr(), 00130 p_desc->getLength(), 00131 p_desc->getMaxLength(), 00132 p_desc->hasVariableLength(), 00133 &nrfDescriptorHandles[descriptorCount]), 00134 BLE_ERROR_PARAM_OUT_OF_RANGE); 00135 00136 p_descriptors[descriptorCount++] = p_desc; 00137 p_desc->setHandle(nrfDescriptorHandles[descriptorCount]); 00138 } 00139 } 00140 00141 serviceCount++; 00142 00143 return BLE_ERROR_NONE; 00144 } 00145 00146 /**************************************************************************/ 00147 /*! 00148 @brief Reads the value of a characteristic, based on the service 00149 and characteristic index fields 00150 00151 @param[in] attributeHandle 00152 The handle of the GattCharacteristic to read from 00153 @param[in] buffer 00154 Buffer to hold the the characteristic's value 00155 (raw byte array in LSB format) 00156 @param[in/out] len 00157 input: Length in bytes to be read. 00158 output: Total length of attribute value upon successful return. 00159 00160 @returns ble_error_t 00161 00162 @retval BLE_ERROR_NONE 00163 Everything executed properly 00164 */ 00165 /**************************************************************************/ 00166 ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) 00167 { 00168 return read(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP); 00169 } 00170 00171 ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP) 00172 { 00173 ble_gatts_value_t value = { 00174 .len = *lengthP, 00175 .offset = 0, 00176 .p_value = buffer, 00177 }; 00178 00179 ASSERT( ERROR_NONE == 00180 sd_ble_gatts_value_get(connectionHandle, attributeHandle, &value), 00181 BLE_ERROR_PARAM_OUT_OF_RANGE); 00182 *lengthP = value.len; 00183 00184 return BLE_ERROR_NONE; 00185 } 00186 00187 /**************************************************************************/ 00188 /*! 00189 @brief Updates the value of a characteristic, based on the service 00190 and characteristic index fields 00191 00192 @param[in] charHandle 00193 The handle of the GattCharacteristic to write to 00194 @param[in] buffer 00195 Data to use when updating the characteristic's value 00196 (raw byte array in LSB format) 00197 @param[in] len 00198 The number of bytes in buffer 00199 00200 @returns ble_error_t 00201 00202 @retval BLE_ERROR_NONE 00203 Everything executed properly 00204 */ 00205 /**************************************************************************/ 00206 ble_error_t nRF5xGattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) 00207 { 00208 return write(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, len, localOnly); 00209 } 00210 00211 ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly) 00212 { 00213 ble_error_t returnValue = BLE_ERROR_NONE; 00214 00215 ble_gatts_value_t value = { 00216 .len = len, 00217 .offset = 0, 00218 .p_value = const_cast<uint8_t *>(buffer), 00219 }; 00220 00221 if (localOnly) { 00222 /* Only update locally regardless of notify/indicate */ 00223 ASSERT_INT( ERROR_NONE, 00224 sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value), 00225 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00226 return BLE_ERROR_NONE; 00227 } 00228 00229 int characteristicIndex = resolveValueHandleToCharIndex(attributeHandle); 00230 if ((characteristicIndex != -1) && 00231 (p_characteristics[characteristicIndex]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) { 00232 /* HVX update for the characteristic value */ 00233 ble_gatts_hvx_params_t hvx_params; 00234 00235 hvx_params.handle = attributeHandle; 00236 hvx_params.type = 00237 (p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION; 00238 hvx_params.offset = 0; 00239 hvx_params.p_data = const_cast<uint8_t *>(buffer); 00240 hvx_params.p_len = &len; 00241 00242 if (connectionHandle == BLE_CONN_HANDLE_INVALID) { /* use the default connection handle if the caller hasn't specified a valid connectionHandle. */ 00243 nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); 00244 connectionHandle = gap.getConnectionHandle(); 00245 } 00246 error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params); 00247 if (error != ERROR_NONE) { 00248 switch (error) { 00249 case ERROR_BLE_NO_TX_BUFFERS: /* Notifications consume application buffers. The return value can be used for resending notifications. */ 00250 case ERROR_BUSY: 00251 returnValue = BLE_STACK_BUSY; 00252 break; 00253 00254 case ERROR_INVALID_STATE: 00255 case ERROR_BLEGATTS_SYS_ATTR_MISSING: 00256 returnValue = BLE_ERROR_INVALID_STATE; 00257 break; 00258 00259 default : 00260 ASSERT_INT( ERROR_NONE, 00261 sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value), 00262 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00263 00264 /* Notifications consume application buffers. The return value can 00265 * be used for resending notifications. */ 00266 returnValue = BLE_STACK_BUSY; 00267 break; 00268 } 00269 } 00270 } else { 00271 returnValue = BLE_ERROR_INVALID_STATE; // if assert is not used 00272 ASSERT_INT( ERROR_NONE, 00273 sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value), 00274 BLE_ERROR_PARAM_OUT_OF_RANGE ); 00275 } 00276 00277 return returnValue; 00278 } 00279 00280 /** 00281 * Perform an explicit BLE notification of a given attribute. 00282 * 00283 * @param[in] attributeHandle 00284 * Handle for the value attribute of the Characteristic. 00285 * @param[in] value 00286 * A pointer to a buffer holding the new value 00287 * @param[in] size 00288 * Size of the new value (in bytes). 00289 * 00290 * @return BLE_ERROR_NONE if we have successfully set the value of the attribute. 00291 */ 00292 ble_error_t nRF5xGattServer::notify(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len) 00293 { 00294 uint16_t gapConnectionHandle = ((nRF5xGap &)nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap()).getConnectionHandle(); 00295 ble_gatts_hvx_params_t hvx_params; 00296 00297 hvx_params.handle = attributeHandle; 00298 hvx_params.type = BLE_GATT_HVX_NOTIFICATION; 00299 hvx_params.offset = 0; 00300 hvx_params.p_data = const_cast<uint8_t *>(buffer); 00301 hvx_params.p_len = &len; 00302 00303 error_t error = (error_t) sd_ble_gatts_hvx(gapConnectionHandle, &hvx_params); 00304 00305 if (error == ERROR_NONE) 00306 return BLE_ERROR_NONE; 00307 else 00308 return BLE_STACK_BUSY; 00309 } 00310 00311 00312 ble_error_t nRF5xGattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP) 00313 { 00314 /* Forward the call with the default connection handle. */ 00315 nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap(); 00316 return areUpdatesEnabled(gap.getConnectionHandle(), characteristic, enabledP); 00317 } 00318 00319 ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP) 00320 { 00321 int characteristicIndex = resolveValueHandleToCharIndex(characteristic.getValueHandle()); 00322 if (characteristicIndex == -1) { 00323 return BLE_ERROR_INVALID_PARAM; 00324 } 00325 00326 /* Read the cccd value from the GATT server. */ 00327 GattAttribute::Handle_t cccdHandle = nrfCharacteristicHandles[characteristicIndex].cccd_handle; 00328 uint16_t cccdValue; 00329 uint16_t length = sizeof(cccdValue); 00330 ble_error_t rc = read(connectionHandle, cccdHandle, reinterpret_cast<uint8_t *>(&cccdValue), &length); 00331 if (rc != BLE_ERROR_NONE) { 00332 return rc; 00333 } 00334 if (length != sizeof(cccdValue)) { 00335 return BLE_ERROR_INVALID_STATE; 00336 } 00337 00338 /* Check for NOTFICATION or INDICATION in CCCD. */ 00339 if ((cccdValue & BLE_GATT_HVX_NOTIFICATION) || (cccdValue & BLE_GATT_HVX_INDICATION)) { 00340 *enabledP = true; 00341 } 00342 00343 return BLE_ERROR_NONE; 00344 } 00345 00346 /**************************************************************************/ 00347 /*! 00348 @brief Clear nRF5xGattServer's state. 00349 00350 @returns ble_error_t 00351 00352 @retval BLE_ERROR_NONE 00353 Everything executed properly 00354 */ 00355 /**************************************************************************/ 00356 ble_error_t nRF5xGattServer::reset(void) 00357 { 00358 /* Clear all state that is from the parent, including private members */ 00359 if (GattServer::reset() != BLE_ERROR_NONE) { 00360 return BLE_ERROR_INVALID_STATE; 00361 } 00362 00363 /* Clear derived class members */ 00364 memset(p_characteristics, 0, sizeof(p_characteristics)); 00365 memset(p_descriptors, 0, sizeof(p_descriptors)); 00366 memset(nrfCharacteristicHandles, 0, sizeof(ble_gatts_char_handles_t)); 00367 memset(nrfDescriptorHandles, 0, sizeof(nrfDescriptorHandles)); 00368 descriptorCount = 0; 00369 00370 return BLE_ERROR_NONE; 00371 } 00372 00373 /**************************************************************************/ 00374 /*! 00375 @brief Callback handler for events getting pushed up from the SD 00376 */ 00377 /**************************************************************************/ 00378 void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt) 00379 { 00380 GattAttribute::Handle_t handle_value; 00381 GattServerEvents::gattEvent_t eventType; 00382 const ble_gatts_evt_t *gattsEventP = &p_ble_evt->evt.gatts_evt; 00383 00384 switch (p_ble_evt->header.evt_id) { 00385 case BLE_GATTS_EVT_WRITE: { 00386 /* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */ 00387 00388 /* 1.) Handle CCCD changes */ 00389 handle_value = gattsEventP->params.write.handle; 00390 int characteristicIndex = resolveCCCDHandleToCharIndex(handle_value); 00391 if ((characteristicIndex != -1) && 00392 (p_characteristics[characteristicIndex]->getProperties() & 00393 (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) { 00394 00395 uint16_t cccd_value = (gattsEventP->params.write.data[1] << 8) | gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */ 00396 00397 if (((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) || 00398 ((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) { 00399 eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED; 00400 } else { 00401 eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED; 00402 } 00403 00404 handleEvent(eventType, p_characteristics[characteristicIndex]->getValueHandle()); 00405 return; 00406 } 00407 00408 /* 2.) Changes to the characteristic value will be handled with other events below */ 00409 eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN; 00410 } 00411 break; 00412 00413 case BLE_GATTS_EVT_HVC: 00414 /* Indication confirmation received */ 00415 eventType = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED; 00416 handle_value = gattsEventP->params.hvc.handle; 00417 break; 00418 00419 case BLE_EVT_TX_COMPLETE: { 00420 handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count); 00421 return; 00422 } 00423 00424 case BLE_GATTS_EVT_SYS_ATTR_MISSING: 00425 case BLE_GAP_EVT_CONN_SEC_UPDATE: 00426 { 00427 GattSysAttrMissingCallbackParams cbParams = {gattsEventP->conn_handle}; 00428 handleSysAttrMissingEvent(&cbParams); 00429 return; 00430 } 00431 00432 case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: 00433 switch (gattsEventP->params.authorize_request.type) { 00434 case BLE_GATTS_AUTHORIZE_TYPE_READ: 00435 eventType = GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ; 00436 handle_value = gattsEventP->params.authorize_request.request.read.handle; 00437 break; 00438 case BLE_GATTS_AUTHORIZE_TYPE_WRITE: 00439 eventType = GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ; 00440 handle_value = gattsEventP->params.authorize_request.request.write.handle; 00441 break; 00442 default: 00443 return; 00444 } 00445 break; 00446 00447 default: 00448 return; 00449 } 00450 00451 int characteristicIndex = resolveValueHandleToCharIndex(handle_value); 00452 if (characteristicIndex == -1) { 00453 return; 00454 } 00455 00456 /* Find index (charHandle) in the pool */ 00457 switch (eventType) { 00458 case GattServerEvents::GATT_EVENT_DATA_WRITTEN: { 00459 GattWriteCallbackParams cbParams = { 00460 .connHandle = gattsEventP->conn_handle, 00461 .handle = handle_value, 00462 .writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.write.op), 00463 .offset = gattsEventP->params.write.offset, 00464 .len = gattsEventP->params.write.len, 00465 .data = gattsEventP->params.write.data 00466 }; 00467 handleDataWrittenEvent(&cbParams); 00468 break; 00469 } 00470 case GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ: { 00471 GattWriteAuthCallbackParams cbParams = { 00472 .connHandle = gattsEventP->conn_handle, 00473 .handle = handle_value, 00474 .offset = gattsEventP->params.authorize_request.request.write.offset, 00475 .len = gattsEventP->params.authorize_request.request.write.len, 00476 .data = gattsEventP->params.authorize_request.request.write.data, 00477 .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member 00478 * set to AUTH_CALLBACK_REPLY_SUCCESS if the client 00479 * request is to proceed. */ 00480 }; 00481 ble_gatts_rw_authorize_reply_params_t reply = { 00482 .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE, 00483 .params = { 00484 .write = { 00485 .gatt_status = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams) 00486 } 00487 } 00488 }; 00489 sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); 00490 00491 /* 00492 * If write-authorization is enabled for a characteristic, 00493 * AUTHORIZATION_REQ event (if replied with true) is *not* 00494 * followed by another DATA_WRITTEN event; so we still need 00495 * to invoke handleDataWritten(), much the same as we would 00496 * have done if write-authorization had not been enabled. 00497 */ 00498 if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) { 00499 GattWriteCallbackParams cbParams = { 00500 .connHandle = gattsEventP->conn_handle, 00501 .handle = handle_value, 00502 .writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.authorize_request.request.write.op), 00503 .offset = gattsEventP->params.authorize_request.request.write.offset, 00504 .len = gattsEventP->params.authorize_request.request.write.len, 00505 .data = gattsEventP->params.authorize_request.request.write.data, 00506 }; 00507 handleDataWrittenEvent(&cbParams); 00508 } 00509 break; 00510 } 00511 case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: { 00512 GattReadAuthCallbackParams cbParams = { 00513 .connHandle = gattsEventP->conn_handle, 00514 .handle = handle_value, 00515 .offset = gattsEventP->params.authorize_request.request.read.offset, 00516 .len = 0, 00517 .data = NULL, 00518 .authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member 00519 * set to AUTH_CALLBACK_REPLY_SUCCESS if the client 00520 * request is to proceed. */ 00521 }; 00522 00523 ble_gatts_rw_authorize_reply_params_t reply = { 00524 .type = BLE_GATTS_AUTHORIZE_TYPE_READ, 00525 .params = { 00526 .read = { 00527 .gatt_status = p_characteristics[characteristicIndex]->authorizeRead(&cbParams) 00528 } 00529 } 00530 }; 00531 00532 if (cbParams.authorizationReply == BLE_GATT_STATUS_SUCCESS) { 00533 if (cbParams.data != NULL) { 00534 reply.params.read.update = 1; 00535 reply.params.read.offset = cbParams.offset; 00536 reply.params.read.len = cbParams.len; 00537 reply.params.read.p_data = cbParams.data; 00538 } 00539 } 00540 00541 sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply); 00542 break; 00543 } 00544 00545 default: 00546 handleEvent(eventType, handle_value); 00547 break; 00548 } 00549 }
Generated on Fri Jul 15 2022 12:51:28 by
1.7.2
