David Kester / nRF51822

Dependents:   GonioTrainer

Fork of nRF51822 by Nordic Semiconductor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ble_dfu.c Source File

ble_dfu.c

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