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 nrf51-sdk by
ble_dfu.c
00001 /* 00002 * Copyright (c) Nordic Semiconductor ASA 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without modification, 00006 * are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright notice, this 00009 * list of conditions and the following disclaimer. 00010 * 00011 * 2. Redistributions in binary form must reproduce the above copyright notice, this 00012 * list of conditions and the following disclaimer in the documentation and/or 00013 * other materials provided with the distribution. 00014 * 00015 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other 00016 * contributors to this software may be used to endorse or promote products 00017 * derived from this software without specific prior written permission. 00018 * 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00021 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00023 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00024 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00027 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 * 00031 */ 00032 00033 #include "ble_dfu.h " 00034 #include "nrf_error.h" 00035 #include "ble_types.h" 00036 #include "ble_gatts.h" 00037 #include "app_util.h " 00038 #include "ble_srv_common.h " 00039 #include "nordic_common.h" 00040 #include <stdint.h> 00041 #include <string.h> 00042 #include <stddef.h> 00043 00044 #define MAX_DFU_PKT_LEN 20 /**< Maximum length (in bytes) of the DFU Packet characteristic. */ 00045 #define PKT_START_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Start DFU Request. */ 00046 #define PKT_INIT_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Init DFU Request. */ 00047 #define PKT_RCPT_NOTIF_REQ_LEN 3 /**< Length (in bytes) of the Packet Receipt Notification Request. */ 00048 #define MAX_PKTS_RCPT_NOTIF_LEN 6 /**< Maximum length (in bytes) of the Packets Receipt Notification. */ 00049 #define MAX_RESPONSE_LEN 7 /**< Maximum length (in bytes) of the response to a Control Point command. */ 00050 #define MAX_NOTIF_BUFFER_LEN MAX(MAX_PKTS_RCPT_NOTIF_LEN, MAX_RESPONSE_LEN) /**< Maximum length (in bytes) of the buffer needed by DFU Service while sending notifications to peer. */ 00051 00052 enum 00053 { 00054 OP_CODE_START_DFU = 1, /**< Value of the Op code field for 'Start DFU' command.*/ 00055 OP_CODE_RECEIVE_INIT = 2, /**< Value of the Op code field for 'Initialize DFU parameters' command.*/ 00056 OP_CODE_RECEIVE_FW = 3, /**< Value of the Op code field for 'Receive firmware image' command.*/ 00057 OP_CODE_VALIDATE = 4, /**< Value of the Op code field for 'Validate firmware' command.*/ 00058 OP_CODE_ACTIVATE_N_RESET = 5, /**< Value of the Op code field for 'Activate & Reset' command.*/ 00059 OP_CODE_SYS_RESET = 6, /**< Value of the Op code field for 'Reset System' command.*/ 00060 OP_CODE_IMAGE_SIZE_REQ = 7, /**< Value of the Op code field for 'Report received image size' command.*/ 00061 OP_CODE_PKT_RCPT_NOTIF_REQ = 8, /**< Value of the Op code field for 'Request packet receipt notification.*/ 00062 OP_CODE_RESPONSE = 16, /**< Value of the Op code field for 'Response.*/ 00063 OP_CODE_PKT_RCPT_NOTIF = 17 /**< Value of the Op code field for 'Packets Receipt Notification'.*/ 00064 }; 00065 00066 static bool m_is_dfu_service_initialized = false; /**< Variable to check if the DFU service was initialized by the application.*/ 00067 static uint8_t m_notif_buffer[MAX_NOTIF_BUFFER_LEN]; /**< Buffer used for sending notifications to peer. */ 00068 00069 /**@brief Function for adding DFU Packet characteristic to the BLE Stack. 00070 * 00071 * @param[in] p_dfu DFU Service structure. 00072 * 00073 * @return NRF_SUCCESS on success. Otherwise an error code. 00074 */ 00075 static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu) 00076 { 00077 ble_gatts_char_md_t char_md; 00078 ble_gatts_attr_t attr_char_value; 00079 ble_uuid_t char_uuid; 00080 ble_gatts_attr_md_t attr_md; 00081 00082 memset(&char_md, 0, sizeof(char_md)); 00083 00084 char_md.char_props.write_wo_resp = 1; 00085 char_md.p_char_user_desc = NULL; 00086 char_md.p_char_pf = NULL; 00087 char_md.p_user_desc_md = NULL; 00088 char_md.p_cccd_md = NULL; 00089 char_md.p_sccd_md = NULL; 00090 00091 char_uuid.type = p_dfu->uuid_type; 00092 char_uuid.uuid = BLE_DFU_PKT_CHAR_UUID; 00093 00094 memset(&attr_md, 0, sizeof(attr_md)); 00095 00096 BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm); 00097 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); 00098 00099 attr_md.vloc = BLE_GATTS_VLOC_STACK; 00100 attr_md.rd_auth = 0; 00101 attr_md.wr_auth = 0; 00102 attr_md.vlen = 1; 00103 00104 memset(&attr_char_value, 0, sizeof(attr_char_value)); 00105 00106 attr_char_value.p_uuid = &char_uuid; 00107 attr_char_value.p_attr_md = &attr_md; 00108 attr_char_value.init_len = 0; 00109 attr_char_value.init_offs = 0; 00110 attr_char_value.max_len = MAX_DFU_PKT_LEN; 00111 attr_char_value.p_value = NULL; 00112 00113 return sd_ble_gatts_characteristic_add(p_dfu->service_handle, 00114 &char_md, 00115 &attr_char_value, 00116 &p_dfu->dfu_pkt_handles); 00117 } 00118 00119 00120 /**@brief Function for adding DFU Revision characteristic to the BLE Stack. 00121 * 00122 * @param[in] p_dfu DFU Service structure. 00123 * 00124 * @return NRF_SUCCESS on success. Otherwise an error code. 00125 */ 00126 static uint32_t dfu_rev_char_add(ble_dfu_t * const p_dfu, ble_dfu_init_t const * const p_dfu_init) 00127 { 00128 ble_gatts_char_md_t char_md; 00129 ble_gatts_attr_t attr_char_value; 00130 ble_uuid_t char_uuid; 00131 ble_gatts_attr_md_t attr_md; 00132 00133 memset(&char_md, 0, sizeof(char_md)); 00134 00135 char_md.char_props.read = 1; 00136 char_md.p_char_user_desc = NULL; 00137 char_md.p_char_pf = NULL; 00138 char_md.p_user_desc_md = NULL; 00139 char_md.p_cccd_md = NULL; 00140 char_md.p_sccd_md = NULL; 00141 00142 char_uuid.type = p_dfu->uuid_type; 00143 char_uuid.uuid = BLE_DFU_REV_CHAR_UUID; 00144 00145 memset(&attr_md, 0, sizeof(attr_md)); 00146 00147 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); 00148 BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm); 00149 00150 attr_md.vloc = BLE_GATTS_VLOC_STACK; 00151 attr_md.rd_auth = 0; 00152 attr_md.wr_auth = 0; 00153 attr_md.vlen = 1; 00154 00155 memset(&attr_char_value, 0, sizeof(attr_char_value)); 00156 00157 attr_char_value.p_uuid = &char_uuid; 00158 attr_char_value.p_attr_md = &attr_md; 00159 attr_char_value.init_len = sizeof(uint16_t); 00160 attr_char_value.init_offs = 0; 00161 attr_char_value.max_len = sizeof(uint16_t); 00162 attr_char_value.p_value = (uint8_t *)&p_dfu_init->revision; 00163 00164 return sd_ble_gatts_characteristic_add(p_dfu->service_handle, 00165 &char_md, 00166 &attr_char_value, 00167 &p_dfu->dfu_rev_handles); 00168 } 00169 00170 00171 /**@brief Function for adding DFU Control Point characteristic to the BLE Stack. 00172 * 00173 * @param[in] p_dfu DFU Service structure. 00174 * 00175 * @return NRF_SUCCESS on success. Otherwise an error code. 00176 */ 00177 static uint32_t dfu_ctrl_pt_add(ble_dfu_t * const p_dfu) 00178 { 00179 ble_gatts_char_md_t char_md; 00180 ble_gatts_attr_t attr_char_value; 00181 ble_uuid_t char_uuid; 00182 ble_gatts_attr_md_t attr_md; 00183 00184 memset(&char_md, 0, sizeof(char_md)); 00185 00186 char_md.char_props.write = 1; 00187 char_md.char_props.notify = 1; 00188 char_md.p_char_user_desc = NULL; 00189 char_md.p_char_pf = NULL; 00190 char_md.p_user_desc_md = NULL; 00191 char_md.p_cccd_md = NULL; 00192 char_md.p_sccd_md = NULL; 00193 00194 char_uuid.type = p_dfu->uuid_type; 00195 char_uuid.uuid = BLE_DFU_CTRL_PT_UUID; 00196 00197 memset(&attr_md, 0, sizeof(attr_md)); 00198 00199 BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm); 00200 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); 00201 00202 attr_md.vloc = BLE_GATTS_VLOC_STACK; 00203 attr_md.rd_auth = 0; 00204 attr_md.wr_auth = 1; 00205 attr_md.vlen = 1; 00206 00207 memset(&attr_char_value, 0, sizeof(attr_char_value)); 00208 00209 attr_char_value.p_uuid = &char_uuid; 00210 attr_char_value.p_attr_md = &attr_md; 00211 attr_char_value.init_len = 0; 00212 attr_char_value.init_offs = 0; 00213 attr_char_value.max_len = BLE_L2CAP_MTU_DEF; 00214 attr_char_value.p_value = NULL; 00215 00216 return sd_ble_gatts_characteristic_add(p_dfu->service_handle, 00217 &char_md, 00218 &attr_char_value, 00219 &p_dfu->dfu_ctrl_pt_handles); 00220 } 00221 00222 00223 /**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the S110 SoftDevice. 00224 * 00225 * @param[in] p_dfu DFU Service Structure. 00226 * @param[in] p_ble_evt Pointer to the event received from BLE stack. 00227 */ 00228 static void on_connect(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt) 00229 { 00230 p_dfu->conn_handle = p_ble_evt->evt.gap_evt.conn_handle; 00231 } 00232 00233 00234 /**@brief Function for checking if the CCCD of DFU Control point is configured for Notification. 00235 * 00236 * @details This function checks if the CCCD of DFU Control Point characteristic is configured 00237 * for Notification by the DFU Controller. 00238 * 00239 * @param[in] p_dfu DFU Service structure. 00240 * 00241 * @return True if the CCCD of DFU Control Point characteristic is configured for Notification. 00242 * False otherwise. 00243 */ 00244 static bool is_cccd_configured(ble_dfu_t * p_dfu) 00245 { 00246 // Check if the CCCDs are configured. 00247 uint8_t cccd_val_buf[BLE_CCCD_VALUE_LEN]; 00248 ble_gatts_value_t gatts_value; 00249 00250 // Initialize value struct. 00251 memset(&gatts_value, 0, sizeof(gatts_value)); 00252 00253 gatts_value.len = BLE_CCCD_VALUE_LEN; 00254 gatts_value.offset = 0; 00255 gatts_value.p_value = cccd_val_buf; 00256 00257 // Check the CCCD Value of DFU Control Point. 00258 uint32_t err_code = sd_ble_gatts_value_get(p_dfu->conn_handle, 00259 p_dfu->dfu_ctrl_pt_handles.cccd_handle, 00260 &gatts_value); 00261 if (err_code != NRF_SUCCESS) 00262 { 00263 if (p_dfu->error_handler != NULL) 00264 { 00265 p_dfu->error_handler(err_code); 00266 } 00267 return false; 00268 } 00269 00270 return ble_srv_is_notification_enabled(cccd_val_buf); 00271 } 00272 00273 00274 /**@brief Function for handling a Write event on the Control Point characteristic. 00275 * 00276 * @param[in] p_dfu DFU Service Structure. 00277 * @param[in] p_ble_write_evt Pointer to the write event received from BLE stack. 00278 * 00279 * @return NRF_SUCCESS on successful processing of control point write. Otherwise an error code. 00280 */ 00281 static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t * p_ble_write_evt) 00282 { 00283 ble_gatts_rw_authorize_reply_params_t write_authorize_reply; 00284 00285 write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; 00286 00287 if (!is_cccd_configured(p_dfu)) 00288 { 00289 // Send an error response to the peer indicating that the CCCD is improperly configured. 00290 write_authorize_reply.params.write.gatt_status = 00291 BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR; 00292 00293 return (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply)); 00294 00295 } 00296 else 00297 { 00298 uint32_t err_code; 00299 00300 write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS; 00301 00302 err_code = (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply)); 00303 00304 if (err_code != NRF_SUCCESS) 00305 { 00306 return err_code; 00307 } 00308 } 00309 00310 ble_dfu_evt_t ble_dfu_evt; 00311 00312 switch (p_ble_write_evt->data[0]) 00313 { 00314 case OP_CODE_START_DFU: 00315 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_START; 00316 00317 if (p_ble_write_evt->len < PKT_START_DFU_PARAM_LEN) 00318 { 00319 return ble_dfu_response_send(p_dfu, 00320 (ble_dfu_procedure_t) p_ble_write_evt->data[0], 00321 BLE_DFU_RESP_VAL_OPER_FAILED); 00322 } 00323 00324 ble_dfu_evt.evt.ble_dfu_pkt_write.len = 1; 00325 ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]); 00326 00327 p_dfu->evt_handler(p_dfu, &ble_dfu_evt); 00328 break; 00329 00330 case OP_CODE_RECEIVE_INIT: 00331 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_INIT_DATA; 00332 00333 if (p_ble_write_evt->len < PKT_INIT_DFU_PARAM_LEN) 00334 { 00335 return ble_dfu_response_send(p_dfu, 00336 (ble_dfu_procedure_t) p_ble_write_evt->data[0], 00337 BLE_DFU_RESP_VAL_OPER_FAILED); 00338 } 00339 00340 ble_dfu_evt.evt.ble_dfu_pkt_write.len = 1; 00341 ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]); 00342 00343 p_dfu->evt_handler(p_dfu, &ble_dfu_evt); 00344 break; 00345 00346 case OP_CODE_RECEIVE_FW: 00347 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_APP_DATA; 00348 00349 p_dfu->evt_handler(p_dfu, &ble_dfu_evt); 00350 break; 00351 00352 case OP_CODE_VALIDATE: 00353 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_VALIDATE; 00354 00355 p_dfu->evt_handler(p_dfu, &ble_dfu_evt); 00356 break; 00357 00358 case OP_CODE_ACTIVATE_N_RESET: 00359 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_ACTIVATE_N_RESET; 00360 00361 p_dfu->evt_handler(p_dfu, &ble_dfu_evt); 00362 break; 00363 00364 case OP_CODE_SYS_RESET: 00365 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_SYS_RESET; 00366 00367 p_dfu->evt_handler(p_dfu, &ble_dfu_evt); 00368 break; 00369 00370 case OP_CODE_PKT_RCPT_NOTIF_REQ: 00371 if (p_ble_write_evt->len < PKT_RCPT_NOTIF_REQ_LEN) 00372 { 00373 return (ble_dfu_response_send(p_dfu, 00374 BLE_DFU_PKT_RCPT_REQ_PROCEDURE, 00375 BLE_DFU_RESP_VAL_NOT_SUPPORTED)); 00376 } 00377 00378 ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts = 00379 uint16_decode(&(p_ble_write_evt->data[1])); 00380 00381 if (ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts == 0) 00382 { 00383 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_DISABLED; 00384 } 00385 else 00386 { 00387 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_ENABLED; 00388 } 00389 00390 p_dfu->evt_handler(p_dfu, &ble_dfu_evt); 00391 00392 break; 00393 00394 case OP_CODE_IMAGE_SIZE_REQ: 00395 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_BYTES_RECEIVED_SEND; 00396 00397 p_dfu->evt_handler(p_dfu, &ble_dfu_evt); 00398 break; 00399 00400 default: 00401 // Unsupported op code. 00402 return ble_dfu_response_send(p_dfu, 00403 (ble_dfu_procedure_t) p_ble_write_evt->data[0], 00404 BLE_DFU_RESP_VAL_NOT_SUPPORTED); 00405 } 00406 return NRF_SUCCESS; 00407 } 00408 00409 00410 /**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event from the S110 00411 * Stack. 00412 * 00413 * @param[in] p_dfu DFU Service Structure. 00414 * @param[in] p_ble_evt Pointer to the event received from BLE stack. 00415 */ 00416 static void on_rw_authorize_req(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt) 00417 { 00418 ble_gatts_evt_rw_authorize_request_t * p_authorize_request; 00419 00420 p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request); 00421 00422 if ( 00423 (p_authorize_request->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) 00424 && 00425 (p_authorize_request->request.write.handle == p_dfu->dfu_ctrl_pt_handles.value_handle) 00426 && 00427 (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ) 00428 && 00429 (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) 00430 && 00431 (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL) 00432 ) 00433 { 00434 uint32_t err_code; 00435 00436 err_code = on_ctrl_pt_write(p_dfu, &(p_authorize_request->request.write)); 00437 00438 if (err_code != NRF_SUCCESS && p_dfu->error_handler != NULL) 00439 { 00440 p_dfu->error_handler(err_code); 00441 } 00442 } 00443 } 00444 00445 00446 /**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the S110 SoftDevice. 00447 * 00448 * @param[in] p_dfu DFU Service Structure. 00449 * @param[in] p_ble_evt Pointer to the event received from BLE stack. 00450 */ 00451 static void on_write(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt) 00452 { 00453 if (p_ble_evt->evt.gatts_evt.params.write.handle == p_dfu->dfu_pkt_handles.value_handle) 00454 { 00455 // DFU Packet written 00456 00457 ble_dfu_evt_t ble_dfu_evt; 00458 00459 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PACKET_WRITE; 00460 ble_dfu_evt.evt.ble_dfu_pkt_write.len = p_ble_evt->evt.gatts_evt.params.write.len; 00461 ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = p_ble_evt->evt.gatts_evt.params.write.data; 00462 00463 p_dfu->evt_handler(p_dfu, &ble_dfu_evt); 00464 } 00465 } 00466 00467 00468 /**@brief Function for handling the BLE_GAP_EVT_DISCONNECTED event from the S110 SoftDevice. 00469 * 00470 * @param[in] p_dfu DFU Service Structure. 00471 * @param[in] p_ble_evt Pointer to the event received from BLE stack. 00472 */ 00473 static void on_disconnect(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt) 00474 { 00475 p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID; 00476 } 00477 00478 00479 uint32_t ble_dfu_init(ble_dfu_t * p_dfu, ble_dfu_init_t * p_dfu_init) 00480 { 00481 if ((p_dfu == NULL) || (p_dfu_init == NULL) || (p_dfu_init->evt_handler == NULL)) 00482 { 00483 return NRF_ERROR_NULL; 00484 } 00485 00486 p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID; 00487 00488 ble_uuid_t service_uuid; 00489 uint32_t err_code; 00490 00491 const ble_uuid128_t base_uuid128 = 00492 { 00493 { 00494 0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 00495 0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00 00496 } 00497 }; 00498 00499 service_uuid.uuid = BLE_DFU_SERVICE_UUID; 00500 00501 err_code = sd_ble_uuid_vs_add(&base_uuid128, &(service_uuid.type)); 00502 if (err_code != NRF_SUCCESS) 00503 { 00504 return err_code; 00505 } 00506 00507 err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, 00508 &service_uuid, 00509 &(p_dfu->service_handle)); 00510 if (err_code != NRF_SUCCESS) 00511 { 00512 return err_code; 00513 } 00514 00515 p_dfu->uuid_type = service_uuid.type; 00516 00517 err_code = dfu_pkt_char_add(p_dfu); 00518 if (err_code != NRF_SUCCESS) 00519 { 00520 return err_code; 00521 } 00522 00523 err_code = dfu_ctrl_pt_add(p_dfu); 00524 if (err_code != NRF_SUCCESS) 00525 { 00526 return err_code; 00527 } 00528 00529 err_code = dfu_rev_char_add(p_dfu, p_dfu_init); 00530 if (err_code != NRF_SUCCESS) 00531 { 00532 return err_code; 00533 } 00534 00535 p_dfu->evt_handler = p_dfu_init->evt_handler; 00536 00537 if (p_dfu_init->error_handler != NULL) 00538 { 00539 p_dfu->error_handler = p_dfu_init->error_handler; 00540 } 00541 00542 m_is_dfu_service_initialized = true; 00543 00544 return NRF_SUCCESS; 00545 } 00546 00547 00548 void ble_dfu_on_ble_evt(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt) 00549 { 00550 if ((p_dfu == NULL) || (p_ble_evt == NULL)) 00551 { 00552 return; 00553 } 00554 00555 if (p_dfu->evt_handler != NULL) 00556 { 00557 switch (p_ble_evt->header.evt_id) 00558 { 00559 case BLE_GAP_EVT_CONNECTED: 00560 on_connect(p_dfu, p_ble_evt); 00561 break; 00562 00563 case BLE_GATTS_EVT_WRITE: 00564 on_write(p_dfu, p_ble_evt); 00565 break; 00566 00567 case BLE_GAP_EVT_DISCONNECTED: 00568 on_disconnect(p_dfu, p_ble_evt); 00569 break; 00570 00571 case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: 00572 on_rw_authorize_req(p_dfu, p_ble_evt); 00573 break; 00574 00575 default: 00576 // No implementation needed. 00577 break; 00578 } 00579 } 00580 } 00581 00582 00583 uint32_t ble_dfu_bytes_rcvd_report(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd) 00584 { 00585 if (p_dfu == NULL) 00586 { 00587 return NRF_ERROR_NULL; 00588 } 00589 00590 if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized) 00591 { 00592 return NRF_ERROR_INVALID_STATE; 00593 } 00594 00595 ble_gatts_hvx_params_t hvx_params; 00596 uint16_t index = 0; 00597 00598 // Encode the Op Code. 00599 m_notif_buffer[index++] = OP_CODE_RESPONSE; 00600 00601 // Encode the Reqest Op Code. 00602 m_notif_buffer[index++] = OP_CODE_IMAGE_SIZE_REQ; 00603 00604 // Encode the Response Value. 00605 m_notif_buffer[index++] = (uint8_t)BLE_DFU_RESP_VAL_SUCCESS; 00606 00607 index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]); 00608 00609 memset(&hvx_params, 0, sizeof(hvx_params)); 00610 00611 hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle; 00612 hvx_params.type = BLE_GATT_HVX_NOTIFICATION; 00613 hvx_params.offset = 0; 00614 hvx_params.p_len = &index; 00615 hvx_params.p_data = m_notif_buffer; 00616 00617 return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params); 00618 } 00619 00620 00621 uint32_t ble_dfu_pkts_rcpt_notify(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd) 00622 { 00623 if (p_dfu == NULL) 00624 { 00625 return NRF_ERROR_NULL; 00626 } 00627 00628 if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized) 00629 { 00630 return NRF_ERROR_INVALID_STATE; 00631 } 00632 00633 ble_gatts_hvx_params_t hvx_params; 00634 uint16_t index = 0; 00635 00636 m_notif_buffer[index++] = OP_CODE_PKT_RCPT_NOTIF; 00637 00638 index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]); 00639 00640 memset(&hvx_params, 0, sizeof(hvx_params)); 00641 00642 hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle; 00643 hvx_params.type = BLE_GATT_HVX_NOTIFICATION; 00644 hvx_params.offset = 0; 00645 hvx_params.p_len = &index; 00646 hvx_params.p_data = m_notif_buffer; 00647 00648 return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params); 00649 } 00650 00651 00652 uint32_t ble_dfu_response_send(ble_dfu_t * p_dfu, 00653 ble_dfu_procedure_t dfu_proc, 00654 ble_dfu_resp_val_t resp_val) 00655 { 00656 if (p_dfu == NULL) 00657 { 00658 return NRF_ERROR_NULL; 00659 } 00660 00661 if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized) 00662 { 00663 return NRF_ERROR_INVALID_STATE; 00664 } 00665 00666 ble_gatts_hvx_params_t hvx_params; 00667 uint16_t index = 0; 00668 00669 m_notif_buffer[index++] = OP_CODE_RESPONSE; 00670 00671 // Encode the Request Op code 00672 m_notif_buffer[index++] = (uint8_t)dfu_proc; 00673 00674 // Encode the Response Value. 00675 m_notif_buffer[index++] = (uint8_t)resp_val; 00676 00677 memset(&hvx_params, 0, sizeof(hvx_params)); 00678 00679 hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle; 00680 hvx_params.type = BLE_GATT_HVX_NOTIFICATION; 00681 hvx_params.offset = 0; 00682 hvx_params.p_len = &index; 00683 hvx_params.p_data = m_notif_buffer; 00684 00685 return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params); 00686 }
Generated on Tue Jul 12 2022 14:11:18 by
