None

Dependents:   nRF51822

Fork of nrf51-sdk by Lancaster University

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ble_dfu.c Source File

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 }