Clone of the nRF51822 repository from github The correct home is https://github.com/lancaster-university/nRF51822
Dependencies: nrf51-sdk
Dependents: microbit-dal microbit-ble-open microbit-dal-eddystone microbit-dal-ble-accelerometer-example ... more
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 Tue Jul 12 2022 15:23:08 by 1.7.2