R1 code for micro:bit based train controller code, requires second micro:bit running rx code to operate - see https://meanderingpi.wordpress.com/ for more information
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 19:00:11 by 1.7.2