Nordic stack and drivers for the mbed BLE API

Dependents:   BLE_ANCS_SDAPI BLE_temperature BLE_HeartRate writable_gatt ... more

Committer:
Vincent Coubard
Date:
Wed Sep 14 14:39:43 2016 +0100
Revision:
638:c90ae1400bf2
Sync with bdab10dc0f90748b6989c8b577771bb403ca6bd8 from ARMmbed/mbed-os.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Vincent Coubard 638:c90ae1400bf2 1 /*
Vincent Coubard 638:c90ae1400bf2 2 * Copyright (c) Nordic Semiconductor ASA
Vincent Coubard 638:c90ae1400bf2 3 * All rights reserved.
Vincent Coubard 638:c90ae1400bf2 4 *
Vincent Coubard 638:c90ae1400bf2 5 * Redistribution and use in source and binary forms, with or without modification,
Vincent Coubard 638:c90ae1400bf2 6 * are permitted provided that the following conditions are met:
Vincent Coubard 638:c90ae1400bf2 7 *
Vincent Coubard 638:c90ae1400bf2 8 * 1. Redistributions of source code must retain the above copyright notice, this
Vincent Coubard 638:c90ae1400bf2 9 * list of conditions and the following disclaimer.
Vincent Coubard 638:c90ae1400bf2 10 *
Vincent Coubard 638:c90ae1400bf2 11 * 2. Redistributions in binary form must reproduce the above copyright notice, this
Vincent Coubard 638:c90ae1400bf2 12 * list of conditions and the following disclaimer in the documentation and/or
Vincent Coubard 638:c90ae1400bf2 13 * other materials provided with the distribution.
Vincent Coubard 638:c90ae1400bf2 14 *
Vincent Coubard 638:c90ae1400bf2 15 * 3. Neither the name of Nordic Semiconductor ASA nor the names of other
Vincent Coubard 638:c90ae1400bf2 16 * contributors to this software may be used to endorse or promote products
Vincent Coubard 638:c90ae1400bf2 17 * derived from this software without specific prior written permission.
Vincent Coubard 638:c90ae1400bf2 18 *
Vincent Coubard 638:c90ae1400bf2 19 *
Vincent Coubard 638:c90ae1400bf2 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Vincent Coubard 638:c90ae1400bf2 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Vincent Coubard 638:c90ae1400bf2 22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Vincent Coubard 638:c90ae1400bf2 23 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
Vincent Coubard 638:c90ae1400bf2 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Vincent Coubard 638:c90ae1400bf2 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Vincent Coubard 638:c90ae1400bf2 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
Vincent Coubard 638:c90ae1400bf2 27 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Vincent Coubard 638:c90ae1400bf2 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Vincent Coubard 638:c90ae1400bf2 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Vincent Coubard 638:c90ae1400bf2 30 *
Vincent Coubard 638:c90ae1400bf2 31 */
Vincent Coubard 638:c90ae1400bf2 32
Vincent Coubard 638:c90ae1400bf2 33 #include "ble_dfu.h"
Vincent Coubard 638:c90ae1400bf2 34 #include "nrf_error.h"
Vincent Coubard 638:c90ae1400bf2 35 #include "ble_types.h"
Vincent Coubard 638:c90ae1400bf2 36 #include "ble_gatts.h"
Vincent Coubard 638:c90ae1400bf2 37 #include "app_util.h"
Vincent Coubard 638:c90ae1400bf2 38 #include "ble_srv_common.h"
Vincent Coubard 638:c90ae1400bf2 39 #include "nordic_common.h"
Vincent Coubard 638:c90ae1400bf2 40 #include <stdint.h>
Vincent Coubard 638:c90ae1400bf2 41 #include <string.h>
Vincent Coubard 638:c90ae1400bf2 42 #include <stddef.h>
Vincent Coubard 638:c90ae1400bf2 43
Vincent Coubard 638:c90ae1400bf2 44 #define MAX_DFU_PKT_LEN 20 /**< Maximum length (in bytes) of the DFU Packet characteristic. */
Vincent Coubard 638:c90ae1400bf2 45 #define PKT_START_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Start DFU Request. */
Vincent Coubard 638:c90ae1400bf2 46 #define PKT_INIT_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Init DFU Request. */
Vincent Coubard 638:c90ae1400bf2 47 #define PKT_RCPT_NOTIF_REQ_LEN 3 /**< Length (in bytes) of the Packet Receipt Notification Request. */
Vincent Coubard 638:c90ae1400bf2 48 #define MAX_PKTS_RCPT_NOTIF_LEN 6 /**< Maximum length (in bytes) of the Packets Receipt Notification. */
Vincent Coubard 638:c90ae1400bf2 49 #define MAX_RESPONSE_LEN 7 /**< Maximum length (in bytes) of the response to a Control Point command. */
Vincent Coubard 638:c90ae1400bf2 50 #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. */
Vincent Coubard 638:c90ae1400bf2 51
Vincent Coubard 638:c90ae1400bf2 52 enum
Vincent Coubard 638:c90ae1400bf2 53 {
Vincent Coubard 638:c90ae1400bf2 54 OP_CODE_START_DFU = 1, /**< Value of the Op code field for 'Start DFU' command.*/
Vincent Coubard 638:c90ae1400bf2 55 OP_CODE_RECEIVE_INIT = 2, /**< Value of the Op code field for 'Initialize DFU parameters' command.*/
Vincent Coubard 638:c90ae1400bf2 56 OP_CODE_RECEIVE_FW = 3, /**< Value of the Op code field for 'Receive firmware image' command.*/
Vincent Coubard 638:c90ae1400bf2 57 OP_CODE_VALIDATE = 4, /**< Value of the Op code field for 'Validate firmware' command.*/
Vincent Coubard 638:c90ae1400bf2 58 OP_CODE_ACTIVATE_N_RESET = 5, /**< Value of the Op code field for 'Activate & Reset' command.*/
Vincent Coubard 638:c90ae1400bf2 59 OP_CODE_SYS_RESET = 6, /**< Value of the Op code field for 'Reset System' command.*/
Vincent Coubard 638:c90ae1400bf2 60 OP_CODE_IMAGE_SIZE_REQ = 7, /**< Value of the Op code field for 'Report received image size' command.*/
Vincent Coubard 638:c90ae1400bf2 61 OP_CODE_PKT_RCPT_NOTIF_REQ = 8, /**< Value of the Op code field for 'Request packet receipt notification.*/
Vincent Coubard 638:c90ae1400bf2 62 OP_CODE_RESPONSE = 16, /**< Value of the Op code field for 'Response.*/
Vincent Coubard 638:c90ae1400bf2 63 OP_CODE_PKT_RCPT_NOTIF = 17 /**< Value of the Op code field for 'Packets Receipt Notification'.*/
Vincent Coubard 638:c90ae1400bf2 64 };
Vincent Coubard 638:c90ae1400bf2 65
Vincent Coubard 638:c90ae1400bf2 66 static bool m_is_dfu_service_initialized = false; /**< Variable to check if the DFU service was initialized by the application.*/
Vincent Coubard 638:c90ae1400bf2 67 static uint8_t m_notif_buffer[MAX_NOTIF_BUFFER_LEN]; /**< Buffer used for sending notifications to peer. */
Vincent Coubard 638:c90ae1400bf2 68
Vincent Coubard 638:c90ae1400bf2 69 /**@brief Function for adding DFU Packet characteristic to the BLE Stack.
Vincent Coubard 638:c90ae1400bf2 70 *
Vincent Coubard 638:c90ae1400bf2 71 * @param[in] p_dfu DFU Service structure.
Vincent Coubard 638:c90ae1400bf2 72 *
Vincent Coubard 638:c90ae1400bf2 73 * @return NRF_SUCCESS on success. Otherwise an error code.
Vincent Coubard 638:c90ae1400bf2 74 */
Vincent Coubard 638:c90ae1400bf2 75 static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu)
Vincent Coubard 638:c90ae1400bf2 76 {
Vincent Coubard 638:c90ae1400bf2 77 ble_gatts_char_md_t char_md;
Vincent Coubard 638:c90ae1400bf2 78 ble_gatts_attr_t attr_char_value;
Vincent Coubard 638:c90ae1400bf2 79 ble_uuid_t char_uuid;
Vincent Coubard 638:c90ae1400bf2 80 ble_gatts_attr_md_t attr_md;
Vincent Coubard 638:c90ae1400bf2 81
Vincent Coubard 638:c90ae1400bf2 82 memset(&char_md, 0, sizeof(char_md));
Vincent Coubard 638:c90ae1400bf2 83
Vincent Coubard 638:c90ae1400bf2 84 char_md.char_props.write_wo_resp = 1;
Vincent Coubard 638:c90ae1400bf2 85 char_md.p_char_user_desc = NULL;
Vincent Coubard 638:c90ae1400bf2 86 char_md.p_char_pf = NULL;
Vincent Coubard 638:c90ae1400bf2 87 char_md.p_user_desc_md = NULL;
Vincent Coubard 638:c90ae1400bf2 88 char_md.p_cccd_md = NULL;
Vincent Coubard 638:c90ae1400bf2 89 char_md.p_sccd_md = NULL;
Vincent Coubard 638:c90ae1400bf2 90
Vincent Coubard 638:c90ae1400bf2 91 char_uuid.type = p_dfu->uuid_type;
Vincent Coubard 638:c90ae1400bf2 92 char_uuid.uuid = BLE_DFU_PKT_CHAR_UUID;
Vincent Coubard 638:c90ae1400bf2 93
Vincent Coubard 638:c90ae1400bf2 94 memset(&attr_md, 0, sizeof(attr_md));
Vincent Coubard 638:c90ae1400bf2 95
Vincent Coubard 638:c90ae1400bf2 96 BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
Vincent Coubard 638:c90ae1400bf2 97 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
Vincent Coubard 638:c90ae1400bf2 98
Vincent Coubard 638:c90ae1400bf2 99 attr_md.vloc = BLE_GATTS_VLOC_STACK;
Vincent Coubard 638:c90ae1400bf2 100 attr_md.rd_auth = 0;
Vincent Coubard 638:c90ae1400bf2 101 attr_md.wr_auth = 0;
Vincent Coubard 638:c90ae1400bf2 102 attr_md.vlen = 1;
Vincent Coubard 638:c90ae1400bf2 103
Vincent Coubard 638:c90ae1400bf2 104 memset(&attr_char_value, 0, sizeof(attr_char_value));
Vincent Coubard 638:c90ae1400bf2 105
Vincent Coubard 638:c90ae1400bf2 106 attr_char_value.p_uuid = &char_uuid;
Vincent Coubard 638:c90ae1400bf2 107 attr_char_value.p_attr_md = &attr_md;
Vincent Coubard 638:c90ae1400bf2 108 attr_char_value.init_len = 0;
Vincent Coubard 638:c90ae1400bf2 109 attr_char_value.init_offs = 0;
Vincent Coubard 638:c90ae1400bf2 110 attr_char_value.max_len = MAX_DFU_PKT_LEN;
Vincent Coubard 638:c90ae1400bf2 111 attr_char_value.p_value = NULL;
Vincent Coubard 638:c90ae1400bf2 112
Vincent Coubard 638:c90ae1400bf2 113 return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
Vincent Coubard 638:c90ae1400bf2 114 &char_md,
Vincent Coubard 638:c90ae1400bf2 115 &attr_char_value,
Vincent Coubard 638:c90ae1400bf2 116 &p_dfu->dfu_pkt_handles);
Vincent Coubard 638:c90ae1400bf2 117 }
Vincent Coubard 638:c90ae1400bf2 118
Vincent Coubard 638:c90ae1400bf2 119
Vincent Coubard 638:c90ae1400bf2 120 /**@brief Function for adding DFU Revision characteristic to the BLE Stack.
Vincent Coubard 638:c90ae1400bf2 121 *
Vincent Coubard 638:c90ae1400bf2 122 * @param[in] p_dfu DFU Service structure.
Vincent Coubard 638:c90ae1400bf2 123 *
Vincent Coubard 638:c90ae1400bf2 124 * @return NRF_SUCCESS on success. Otherwise an error code.
Vincent Coubard 638:c90ae1400bf2 125 */
Vincent Coubard 638:c90ae1400bf2 126 static uint32_t dfu_rev_char_add(ble_dfu_t * const p_dfu, ble_dfu_init_t const * const p_dfu_init)
Vincent Coubard 638:c90ae1400bf2 127 {
Vincent Coubard 638:c90ae1400bf2 128 ble_gatts_char_md_t char_md;
Vincent Coubard 638:c90ae1400bf2 129 ble_gatts_attr_t attr_char_value;
Vincent Coubard 638:c90ae1400bf2 130 ble_uuid_t char_uuid;
Vincent Coubard 638:c90ae1400bf2 131 ble_gatts_attr_md_t attr_md;
Vincent Coubard 638:c90ae1400bf2 132
Vincent Coubard 638:c90ae1400bf2 133 memset(&char_md, 0, sizeof(char_md));
Vincent Coubard 638:c90ae1400bf2 134
Vincent Coubard 638:c90ae1400bf2 135 char_md.char_props.read = 1;
Vincent Coubard 638:c90ae1400bf2 136 char_md.p_char_user_desc = NULL;
Vincent Coubard 638:c90ae1400bf2 137 char_md.p_char_pf = NULL;
Vincent Coubard 638:c90ae1400bf2 138 char_md.p_user_desc_md = NULL;
Vincent Coubard 638:c90ae1400bf2 139 char_md.p_cccd_md = NULL;
Vincent Coubard 638:c90ae1400bf2 140 char_md.p_sccd_md = NULL;
Vincent Coubard 638:c90ae1400bf2 141
Vincent Coubard 638:c90ae1400bf2 142 char_uuid.type = p_dfu->uuid_type;
Vincent Coubard 638:c90ae1400bf2 143 char_uuid.uuid = BLE_DFU_REV_CHAR_UUID;
Vincent Coubard 638:c90ae1400bf2 144
Vincent Coubard 638:c90ae1400bf2 145 memset(&attr_md, 0, sizeof(attr_md));
Vincent Coubard 638:c90ae1400bf2 146
Vincent Coubard 638:c90ae1400bf2 147 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
Vincent Coubard 638:c90ae1400bf2 148 BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
Vincent Coubard 638:c90ae1400bf2 149
Vincent Coubard 638:c90ae1400bf2 150 attr_md.vloc = BLE_GATTS_VLOC_STACK;
Vincent Coubard 638:c90ae1400bf2 151 attr_md.rd_auth = 0;
Vincent Coubard 638:c90ae1400bf2 152 attr_md.wr_auth = 0;
Vincent Coubard 638:c90ae1400bf2 153 attr_md.vlen = 1;
Vincent Coubard 638:c90ae1400bf2 154
Vincent Coubard 638:c90ae1400bf2 155 memset(&attr_char_value, 0, sizeof(attr_char_value));
Vincent Coubard 638:c90ae1400bf2 156
Vincent Coubard 638:c90ae1400bf2 157 attr_char_value.p_uuid = &char_uuid;
Vincent Coubard 638:c90ae1400bf2 158 attr_char_value.p_attr_md = &attr_md;
Vincent Coubard 638:c90ae1400bf2 159 attr_char_value.init_len = sizeof(uint16_t);
Vincent Coubard 638:c90ae1400bf2 160 attr_char_value.init_offs = 0;
Vincent Coubard 638:c90ae1400bf2 161 attr_char_value.max_len = sizeof(uint16_t);
Vincent Coubard 638:c90ae1400bf2 162 attr_char_value.p_value = (uint8_t *)&p_dfu_init->revision;
Vincent Coubard 638:c90ae1400bf2 163
Vincent Coubard 638:c90ae1400bf2 164 return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
Vincent Coubard 638:c90ae1400bf2 165 &char_md,
Vincent Coubard 638:c90ae1400bf2 166 &attr_char_value,
Vincent Coubard 638:c90ae1400bf2 167 &p_dfu->dfu_rev_handles);
Vincent Coubard 638:c90ae1400bf2 168 }
Vincent Coubard 638:c90ae1400bf2 169
Vincent Coubard 638:c90ae1400bf2 170
Vincent Coubard 638:c90ae1400bf2 171 /**@brief Function for adding DFU Control Point characteristic to the BLE Stack.
Vincent Coubard 638:c90ae1400bf2 172 *
Vincent Coubard 638:c90ae1400bf2 173 * @param[in] p_dfu DFU Service structure.
Vincent Coubard 638:c90ae1400bf2 174 *
Vincent Coubard 638:c90ae1400bf2 175 * @return NRF_SUCCESS on success. Otherwise an error code.
Vincent Coubard 638:c90ae1400bf2 176 */
Vincent Coubard 638:c90ae1400bf2 177 static uint32_t dfu_ctrl_pt_add(ble_dfu_t * const p_dfu)
Vincent Coubard 638:c90ae1400bf2 178 {
Vincent Coubard 638:c90ae1400bf2 179 ble_gatts_char_md_t char_md;
Vincent Coubard 638:c90ae1400bf2 180 ble_gatts_attr_t attr_char_value;
Vincent Coubard 638:c90ae1400bf2 181 ble_uuid_t char_uuid;
Vincent Coubard 638:c90ae1400bf2 182 ble_gatts_attr_md_t attr_md;
Vincent Coubard 638:c90ae1400bf2 183
Vincent Coubard 638:c90ae1400bf2 184 memset(&char_md, 0, sizeof(char_md));
Vincent Coubard 638:c90ae1400bf2 185
Vincent Coubard 638:c90ae1400bf2 186 char_md.char_props.write = 1;
Vincent Coubard 638:c90ae1400bf2 187 char_md.char_props.notify = 1;
Vincent Coubard 638:c90ae1400bf2 188 char_md.p_char_user_desc = NULL;
Vincent Coubard 638:c90ae1400bf2 189 char_md.p_char_pf = NULL;
Vincent Coubard 638:c90ae1400bf2 190 char_md.p_user_desc_md = NULL;
Vincent Coubard 638:c90ae1400bf2 191 char_md.p_cccd_md = NULL;
Vincent Coubard 638:c90ae1400bf2 192 char_md.p_sccd_md = NULL;
Vincent Coubard 638:c90ae1400bf2 193
Vincent Coubard 638:c90ae1400bf2 194 char_uuid.type = p_dfu->uuid_type;
Vincent Coubard 638:c90ae1400bf2 195 char_uuid.uuid = BLE_DFU_CTRL_PT_UUID;
Vincent Coubard 638:c90ae1400bf2 196
Vincent Coubard 638:c90ae1400bf2 197 memset(&attr_md, 0, sizeof(attr_md));
Vincent Coubard 638:c90ae1400bf2 198
Vincent Coubard 638:c90ae1400bf2 199 BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
Vincent Coubard 638:c90ae1400bf2 200 BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
Vincent Coubard 638:c90ae1400bf2 201
Vincent Coubard 638:c90ae1400bf2 202 attr_md.vloc = BLE_GATTS_VLOC_STACK;
Vincent Coubard 638:c90ae1400bf2 203 attr_md.rd_auth = 0;
Vincent Coubard 638:c90ae1400bf2 204 attr_md.wr_auth = 1;
Vincent Coubard 638:c90ae1400bf2 205 attr_md.vlen = 1;
Vincent Coubard 638:c90ae1400bf2 206
Vincent Coubard 638:c90ae1400bf2 207 memset(&attr_char_value, 0, sizeof(attr_char_value));
Vincent Coubard 638:c90ae1400bf2 208
Vincent Coubard 638:c90ae1400bf2 209 attr_char_value.p_uuid = &char_uuid;
Vincent Coubard 638:c90ae1400bf2 210 attr_char_value.p_attr_md = &attr_md;
Vincent Coubard 638:c90ae1400bf2 211 attr_char_value.init_len = 0;
Vincent Coubard 638:c90ae1400bf2 212 attr_char_value.init_offs = 0;
Vincent Coubard 638:c90ae1400bf2 213 attr_char_value.max_len = BLE_L2CAP_MTU_DEF;
Vincent Coubard 638:c90ae1400bf2 214 attr_char_value.p_value = NULL;
Vincent Coubard 638:c90ae1400bf2 215
Vincent Coubard 638:c90ae1400bf2 216 return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
Vincent Coubard 638:c90ae1400bf2 217 &char_md,
Vincent Coubard 638:c90ae1400bf2 218 &attr_char_value,
Vincent Coubard 638:c90ae1400bf2 219 &p_dfu->dfu_ctrl_pt_handles);
Vincent Coubard 638:c90ae1400bf2 220 }
Vincent Coubard 638:c90ae1400bf2 221
Vincent Coubard 638:c90ae1400bf2 222
Vincent Coubard 638:c90ae1400bf2 223 /**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the S110 SoftDevice.
Vincent Coubard 638:c90ae1400bf2 224 *
Vincent Coubard 638:c90ae1400bf2 225 * @param[in] p_dfu DFU Service Structure.
Vincent Coubard 638:c90ae1400bf2 226 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
Vincent Coubard 638:c90ae1400bf2 227 */
Vincent Coubard 638:c90ae1400bf2 228 static void on_connect(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
Vincent Coubard 638:c90ae1400bf2 229 {
Vincent Coubard 638:c90ae1400bf2 230 p_dfu->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
Vincent Coubard 638:c90ae1400bf2 231 }
Vincent Coubard 638:c90ae1400bf2 232
Vincent Coubard 638:c90ae1400bf2 233
Vincent Coubard 638:c90ae1400bf2 234 /**@brief Function for checking if the CCCD of DFU Control point is configured for Notification.
Vincent Coubard 638:c90ae1400bf2 235 *
Vincent Coubard 638:c90ae1400bf2 236 * @details This function checks if the CCCD of DFU Control Point characteristic is configured
Vincent Coubard 638:c90ae1400bf2 237 * for Notification by the DFU Controller.
Vincent Coubard 638:c90ae1400bf2 238 *
Vincent Coubard 638:c90ae1400bf2 239 * @param[in] p_dfu DFU Service structure.
Vincent Coubard 638:c90ae1400bf2 240 *
Vincent Coubard 638:c90ae1400bf2 241 * @return True if the CCCD of DFU Control Point characteristic is configured for Notification.
Vincent Coubard 638:c90ae1400bf2 242 * False otherwise.
Vincent Coubard 638:c90ae1400bf2 243 */
Vincent Coubard 638:c90ae1400bf2 244 static bool is_cccd_configured(ble_dfu_t * p_dfu)
Vincent Coubard 638:c90ae1400bf2 245 {
Vincent Coubard 638:c90ae1400bf2 246 // Check if the CCCDs are configured.
Vincent Coubard 638:c90ae1400bf2 247 uint8_t cccd_val_buf[BLE_CCCD_VALUE_LEN];
Vincent Coubard 638:c90ae1400bf2 248 ble_gatts_value_t gatts_value;
Vincent Coubard 638:c90ae1400bf2 249
Vincent Coubard 638:c90ae1400bf2 250 // Initialize value struct.
Vincent Coubard 638:c90ae1400bf2 251 memset(&gatts_value, 0, sizeof(gatts_value));
Vincent Coubard 638:c90ae1400bf2 252
Vincent Coubard 638:c90ae1400bf2 253 gatts_value.len = BLE_CCCD_VALUE_LEN;
Vincent Coubard 638:c90ae1400bf2 254 gatts_value.offset = 0;
Vincent Coubard 638:c90ae1400bf2 255 gatts_value.p_value = cccd_val_buf;
Vincent Coubard 638:c90ae1400bf2 256
Vincent Coubard 638:c90ae1400bf2 257 // Check the CCCD Value of DFU Control Point.
Vincent Coubard 638:c90ae1400bf2 258 uint32_t err_code = sd_ble_gatts_value_get(p_dfu->conn_handle,
Vincent Coubard 638:c90ae1400bf2 259 p_dfu->dfu_ctrl_pt_handles.cccd_handle,
Vincent Coubard 638:c90ae1400bf2 260 &gatts_value);
Vincent Coubard 638:c90ae1400bf2 261 if (err_code != NRF_SUCCESS)
Vincent Coubard 638:c90ae1400bf2 262 {
Vincent Coubard 638:c90ae1400bf2 263 if (p_dfu->error_handler != NULL)
Vincent Coubard 638:c90ae1400bf2 264 {
Vincent Coubard 638:c90ae1400bf2 265 p_dfu->error_handler(err_code);
Vincent Coubard 638:c90ae1400bf2 266 }
Vincent Coubard 638:c90ae1400bf2 267 return false;
Vincent Coubard 638:c90ae1400bf2 268 }
Vincent Coubard 638:c90ae1400bf2 269
Vincent Coubard 638:c90ae1400bf2 270 return ble_srv_is_notification_enabled(cccd_val_buf);
Vincent Coubard 638:c90ae1400bf2 271 }
Vincent Coubard 638:c90ae1400bf2 272
Vincent Coubard 638:c90ae1400bf2 273
Vincent Coubard 638:c90ae1400bf2 274 /**@brief Function for handling a Write event on the Control Point characteristic.
Vincent Coubard 638:c90ae1400bf2 275 *
Vincent Coubard 638:c90ae1400bf2 276 * @param[in] p_dfu DFU Service Structure.
Vincent Coubard 638:c90ae1400bf2 277 * @param[in] p_ble_write_evt Pointer to the write event received from BLE stack.
Vincent Coubard 638:c90ae1400bf2 278 *
Vincent Coubard 638:c90ae1400bf2 279 * @return NRF_SUCCESS on successful processing of control point write. Otherwise an error code.
Vincent Coubard 638:c90ae1400bf2 280 */
Vincent Coubard 638:c90ae1400bf2 281 static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t * p_ble_write_evt)
Vincent Coubard 638:c90ae1400bf2 282 {
Vincent Coubard 638:c90ae1400bf2 283 ble_gatts_rw_authorize_reply_params_t write_authorize_reply;
Vincent Coubard 638:c90ae1400bf2 284
Vincent Coubard 638:c90ae1400bf2 285 write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
Vincent Coubard 638:c90ae1400bf2 286
Vincent Coubard 638:c90ae1400bf2 287 if (!is_cccd_configured(p_dfu))
Vincent Coubard 638:c90ae1400bf2 288 {
Vincent Coubard 638:c90ae1400bf2 289 // Send an error response to the peer indicating that the CCCD is improperly configured.
Vincent Coubard 638:c90ae1400bf2 290 write_authorize_reply.params.write.gatt_status =
Vincent Coubard 638:c90ae1400bf2 291 BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR;
Vincent Coubard 638:c90ae1400bf2 292
Vincent Coubard 638:c90ae1400bf2 293 return (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply));
Vincent Coubard 638:c90ae1400bf2 294
Vincent Coubard 638:c90ae1400bf2 295 }
Vincent Coubard 638:c90ae1400bf2 296 else
Vincent Coubard 638:c90ae1400bf2 297 {
Vincent Coubard 638:c90ae1400bf2 298 uint32_t err_code;
Vincent Coubard 638:c90ae1400bf2 299
Vincent Coubard 638:c90ae1400bf2 300 write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 301
Vincent Coubard 638:c90ae1400bf2 302 err_code = (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &write_authorize_reply));
Vincent Coubard 638:c90ae1400bf2 303
Vincent Coubard 638:c90ae1400bf2 304 if (err_code != NRF_SUCCESS)
Vincent Coubard 638:c90ae1400bf2 305 {
Vincent Coubard 638:c90ae1400bf2 306 return err_code;
Vincent Coubard 638:c90ae1400bf2 307 }
Vincent Coubard 638:c90ae1400bf2 308 }
Vincent Coubard 638:c90ae1400bf2 309
Vincent Coubard 638:c90ae1400bf2 310 ble_dfu_evt_t ble_dfu_evt;
Vincent Coubard 638:c90ae1400bf2 311
Vincent Coubard 638:c90ae1400bf2 312 switch (p_ble_write_evt->data[0])
Vincent Coubard 638:c90ae1400bf2 313 {
Vincent Coubard 638:c90ae1400bf2 314 case OP_CODE_START_DFU:
Vincent Coubard 638:c90ae1400bf2 315 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_START;
Vincent Coubard 638:c90ae1400bf2 316
Vincent Coubard 638:c90ae1400bf2 317 if (p_ble_write_evt->len < PKT_START_DFU_PARAM_LEN)
Vincent Coubard 638:c90ae1400bf2 318 {
Vincent Coubard 638:c90ae1400bf2 319 return ble_dfu_response_send(p_dfu,
Vincent Coubard 638:c90ae1400bf2 320 (ble_dfu_procedure_t) p_ble_write_evt->data[0],
Vincent Coubard 638:c90ae1400bf2 321 BLE_DFU_RESP_VAL_OPER_FAILED);
Vincent Coubard 638:c90ae1400bf2 322 }
Vincent Coubard 638:c90ae1400bf2 323
Vincent Coubard 638:c90ae1400bf2 324 ble_dfu_evt.evt.ble_dfu_pkt_write.len = 1;
Vincent Coubard 638:c90ae1400bf2 325 ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]);
Vincent Coubard 638:c90ae1400bf2 326
Vincent Coubard 638:c90ae1400bf2 327 p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
Vincent Coubard 638:c90ae1400bf2 328 break;
Vincent Coubard 638:c90ae1400bf2 329
Vincent Coubard 638:c90ae1400bf2 330 case OP_CODE_RECEIVE_INIT:
Vincent Coubard 638:c90ae1400bf2 331 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_INIT_DATA;
Vincent Coubard 638:c90ae1400bf2 332
Vincent Coubard 638:c90ae1400bf2 333 if (p_ble_write_evt->len < PKT_INIT_DFU_PARAM_LEN)
Vincent Coubard 638:c90ae1400bf2 334 {
Vincent Coubard 638:c90ae1400bf2 335 return ble_dfu_response_send(p_dfu,
Vincent Coubard 638:c90ae1400bf2 336 (ble_dfu_procedure_t) p_ble_write_evt->data[0],
Vincent Coubard 638:c90ae1400bf2 337 BLE_DFU_RESP_VAL_OPER_FAILED);
Vincent Coubard 638:c90ae1400bf2 338 }
Vincent Coubard 638:c90ae1400bf2 339
Vincent Coubard 638:c90ae1400bf2 340 ble_dfu_evt.evt.ble_dfu_pkt_write.len = 1;
Vincent Coubard 638:c90ae1400bf2 341 ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]);
Vincent Coubard 638:c90ae1400bf2 342
Vincent Coubard 638:c90ae1400bf2 343 p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
Vincent Coubard 638:c90ae1400bf2 344 break;
Vincent Coubard 638:c90ae1400bf2 345
Vincent Coubard 638:c90ae1400bf2 346 case OP_CODE_RECEIVE_FW:
Vincent Coubard 638:c90ae1400bf2 347 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_APP_DATA;
Vincent Coubard 638:c90ae1400bf2 348
Vincent Coubard 638:c90ae1400bf2 349 p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
Vincent Coubard 638:c90ae1400bf2 350 break;
Vincent Coubard 638:c90ae1400bf2 351
Vincent Coubard 638:c90ae1400bf2 352 case OP_CODE_VALIDATE:
Vincent Coubard 638:c90ae1400bf2 353 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_VALIDATE;
Vincent Coubard 638:c90ae1400bf2 354
Vincent Coubard 638:c90ae1400bf2 355 p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
Vincent Coubard 638:c90ae1400bf2 356 break;
Vincent Coubard 638:c90ae1400bf2 357
Vincent Coubard 638:c90ae1400bf2 358 case OP_CODE_ACTIVATE_N_RESET:
Vincent Coubard 638:c90ae1400bf2 359 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_ACTIVATE_N_RESET;
Vincent Coubard 638:c90ae1400bf2 360
Vincent Coubard 638:c90ae1400bf2 361 p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
Vincent Coubard 638:c90ae1400bf2 362 break;
Vincent Coubard 638:c90ae1400bf2 363
Vincent Coubard 638:c90ae1400bf2 364 case OP_CODE_SYS_RESET:
Vincent Coubard 638:c90ae1400bf2 365 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_SYS_RESET;
Vincent Coubard 638:c90ae1400bf2 366
Vincent Coubard 638:c90ae1400bf2 367 p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
Vincent Coubard 638:c90ae1400bf2 368 break;
Vincent Coubard 638:c90ae1400bf2 369
Vincent Coubard 638:c90ae1400bf2 370 case OP_CODE_PKT_RCPT_NOTIF_REQ:
Vincent Coubard 638:c90ae1400bf2 371 if (p_ble_write_evt->len < PKT_RCPT_NOTIF_REQ_LEN)
Vincent Coubard 638:c90ae1400bf2 372 {
Vincent Coubard 638:c90ae1400bf2 373 return (ble_dfu_response_send(p_dfu,
Vincent Coubard 638:c90ae1400bf2 374 BLE_DFU_PKT_RCPT_REQ_PROCEDURE,
Vincent Coubard 638:c90ae1400bf2 375 BLE_DFU_RESP_VAL_NOT_SUPPORTED));
Vincent Coubard 638:c90ae1400bf2 376 }
Vincent Coubard 638:c90ae1400bf2 377
Vincent Coubard 638:c90ae1400bf2 378 ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts =
Vincent Coubard 638:c90ae1400bf2 379 uint16_decode(&(p_ble_write_evt->data[1]));
Vincent Coubard 638:c90ae1400bf2 380
Vincent Coubard 638:c90ae1400bf2 381 if (ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts == 0)
Vincent Coubard 638:c90ae1400bf2 382 {
Vincent Coubard 638:c90ae1400bf2 383 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_DISABLED;
Vincent Coubard 638:c90ae1400bf2 384 }
Vincent Coubard 638:c90ae1400bf2 385 else
Vincent Coubard 638:c90ae1400bf2 386 {
Vincent Coubard 638:c90ae1400bf2 387 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_ENABLED;
Vincent Coubard 638:c90ae1400bf2 388 }
Vincent Coubard 638:c90ae1400bf2 389
Vincent Coubard 638:c90ae1400bf2 390 p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
Vincent Coubard 638:c90ae1400bf2 391
Vincent Coubard 638:c90ae1400bf2 392 break;
Vincent Coubard 638:c90ae1400bf2 393
Vincent Coubard 638:c90ae1400bf2 394 case OP_CODE_IMAGE_SIZE_REQ:
Vincent Coubard 638:c90ae1400bf2 395 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_BYTES_RECEIVED_SEND;
Vincent Coubard 638:c90ae1400bf2 396
Vincent Coubard 638:c90ae1400bf2 397 p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
Vincent Coubard 638:c90ae1400bf2 398 break;
Vincent Coubard 638:c90ae1400bf2 399
Vincent Coubard 638:c90ae1400bf2 400 default:
Vincent Coubard 638:c90ae1400bf2 401 // Unsupported op code.
Vincent Coubard 638:c90ae1400bf2 402 return ble_dfu_response_send(p_dfu,
Vincent Coubard 638:c90ae1400bf2 403 (ble_dfu_procedure_t) p_ble_write_evt->data[0],
Vincent Coubard 638:c90ae1400bf2 404 BLE_DFU_RESP_VAL_NOT_SUPPORTED);
Vincent Coubard 638:c90ae1400bf2 405 }
Vincent Coubard 638:c90ae1400bf2 406 return NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 407 }
Vincent Coubard 638:c90ae1400bf2 408
Vincent Coubard 638:c90ae1400bf2 409
Vincent Coubard 638:c90ae1400bf2 410 /**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event from the S110
Vincent Coubard 638:c90ae1400bf2 411 * Stack.
Vincent Coubard 638:c90ae1400bf2 412 *
Vincent Coubard 638:c90ae1400bf2 413 * @param[in] p_dfu DFU Service Structure.
Vincent Coubard 638:c90ae1400bf2 414 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
Vincent Coubard 638:c90ae1400bf2 415 */
Vincent Coubard 638:c90ae1400bf2 416 static void on_rw_authorize_req(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
Vincent Coubard 638:c90ae1400bf2 417 {
Vincent Coubard 638:c90ae1400bf2 418 ble_gatts_evt_rw_authorize_request_t * p_authorize_request;
Vincent Coubard 638:c90ae1400bf2 419
Vincent Coubard 638:c90ae1400bf2 420 p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request);
Vincent Coubard 638:c90ae1400bf2 421
Vincent Coubard 638:c90ae1400bf2 422 if (
Vincent Coubard 638:c90ae1400bf2 423 (p_authorize_request->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
Vincent Coubard 638:c90ae1400bf2 424 &&
Vincent Coubard 638:c90ae1400bf2 425 (p_authorize_request->request.write.handle == p_dfu->dfu_ctrl_pt_handles.value_handle)
Vincent Coubard 638:c90ae1400bf2 426 &&
Vincent Coubard 638:c90ae1400bf2 427 (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ)
Vincent Coubard 638:c90ae1400bf2 428 &&
Vincent Coubard 638:c90ae1400bf2 429 (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW)
Vincent Coubard 638:c90ae1400bf2 430 &&
Vincent Coubard 638:c90ae1400bf2 431 (p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)
Vincent Coubard 638:c90ae1400bf2 432 )
Vincent Coubard 638:c90ae1400bf2 433 {
Vincent Coubard 638:c90ae1400bf2 434 uint32_t err_code;
Vincent Coubard 638:c90ae1400bf2 435
Vincent Coubard 638:c90ae1400bf2 436 err_code = on_ctrl_pt_write(p_dfu, &(p_authorize_request->request.write));
Vincent Coubard 638:c90ae1400bf2 437
Vincent Coubard 638:c90ae1400bf2 438 if (err_code != NRF_SUCCESS && p_dfu->error_handler != NULL)
Vincent Coubard 638:c90ae1400bf2 439 {
Vincent Coubard 638:c90ae1400bf2 440 p_dfu->error_handler(err_code);
Vincent Coubard 638:c90ae1400bf2 441 }
Vincent Coubard 638:c90ae1400bf2 442 }
Vincent Coubard 638:c90ae1400bf2 443 }
Vincent Coubard 638:c90ae1400bf2 444
Vincent Coubard 638:c90ae1400bf2 445
Vincent Coubard 638:c90ae1400bf2 446 /**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the S110 SoftDevice.
Vincent Coubard 638:c90ae1400bf2 447 *
Vincent Coubard 638:c90ae1400bf2 448 * @param[in] p_dfu DFU Service Structure.
Vincent Coubard 638:c90ae1400bf2 449 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
Vincent Coubard 638:c90ae1400bf2 450 */
Vincent Coubard 638:c90ae1400bf2 451 static void on_write(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
Vincent Coubard 638:c90ae1400bf2 452 {
Vincent Coubard 638:c90ae1400bf2 453 if (p_ble_evt->evt.gatts_evt.params.write.handle == p_dfu->dfu_pkt_handles.value_handle)
Vincent Coubard 638:c90ae1400bf2 454 {
Vincent Coubard 638:c90ae1400bf2 455 // DFU Packet written
Vincent Coubard 638:c90ae1400bf2 456
Vincent Coubard 638:c90ae1400bf2 457 ble_dfu_evt_t ble_dfu_evt;
Vincent Coubard 638:c90ae1400bf2 458
Vincent Coubard 638:c90ae1400bf2 459 ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PACKET_WRITE;
Vincent Coubard 638:c90ae1400bf2 460 ble_dfu_evt.evt.ble_dfu_pkt_write.len = p_ble_evt->evt.gatts_evt.params.write.len;
Vincent Coubard 638:c90ae1400bf2 461 ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = p_ble_evt->evt.gatts_evt.params.write.data;
Vincent Coubard 638:c90ae1400bf2 462
Vincent Coubard 638:c90ae1400bf2 463 p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
Vincent Coubard 638:c90ae1400bf2 464 }
Vincent Coubard 638:c90ae1400bf2 465 }
Vincent Coubard 638:c90ae1400bf2 466
Vincent Coubard 638:c90ae1400bf2 467
Vincent Coubard 638:c90ae1400bf2 468 /**@brief Function for handling the BLE_GAP_EVT_DISCONNECTED event from the S110 SoftDevice.
Vincent Coubard 638:c90ae1400bf2 469 *
Vincent Coubard 638:c90ae1400bf2 470 * @param[in] p_dfu DFU Service Structure.
Vincent Coubard 638:c90ae1400bf2 471 * @param[in] p_ble_evt Pointer to the event received from BLE stack.
Vincent Coubard 638:c90ae1400bf2 472 */
Vincent Coubard 638:c90ae1400bf2 473 static void on_disconnect(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
Vincent Coubard 638:c90ae1400bf2 474 {
Vincent Coubard 638:c90ae1400bf2 475 p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID;
Vincent Coubard 638:c90ae1400bf2 476 }
Vincent Coubard 638:c90ae1400bf2 477
Vincent Coubard 638:c90ae1400bf2 478
Vincent Coubard 638:c90ae1400bf2 479 uint32_t ble_dfu_init(ble_dfu_t * p_dfu, ble_dfu_init_t * p_dfu_init)
Vincent Coubard 638:c90ae1400bf2 480 {
Vincent Coubard 638:c90ae1400bf2 481 if ((p_dfu == NULL) || (p_dfu_init == NULL) || (p_dfu_init->evt_handler == NULL))
Vincent Coubard 638:c90ae1400bf2 482 {
Vincent Coubard 638:c90ae1400bf2 483 return NRF_ERROR_NULL;
Vincent Coubard 638:c90ae1400bf2 484 }
Vincent Coubard 638:c90ae1400bf2 485
Vincent Coubard 638:c90ae1400bf2 486 p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID;
Vincent Coubard 638:c90ae1400bf2 487
Vincent Coubard 638:c90ae1400bf2 488 ble_uuid_t service_uuid;
Vincent Coubard 638:c90ae1400bf2 489 uint32_t err_code;
Vincent Coubard 638:c90ae1400bf2 490
Vincent Coubard 638:c90ae1400bf2 491 const ble_uuid128_t base_uuid128 =
Vincent Coubard 638:c90ae1400bf2 492 {
Vincent Coubard 638:c90ae1400bf2 493 {
Vincent Coubard 638:c90ae1400bf2 494 0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
Vincent Coubard 638:c90ae1400bf2 495 0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00
Vincent Coubard 638:c90ae1400bf2 496 }
Vincent Coubard 638:c90ae1400bf2 497 };
Vincent Coubard 638:c90ae1400bf2 498
Vincent Coubard 638:c90ae1400bf2 499 service_uuid.uuid = BLE_DFU_SERVICE_UUID;
Vincent Coubard 638:c90ae1400bf2 500
Vincent Coubard 638:c90ae1400bf2 501 err_code = sd_ble_uuid_vs_add(&base_uuid128, &(service_uuid.type));
Vincent Coubard 638:c90ae1400bf2 502 if (err_code != NRF_SUCCESS)
Vincent Coubard 638:c90ae1400bf2 503 {
Vincent Coubard 638:c90ae1400bf2 504 return err_code;
Vincent Coubard 638:c90ae1400bf2 505 }
Vincent Coubard 638:c90ae1400bf2 506
Vincent Coubard 638:c90ae1400bf2 507 err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
Vincent Coubard 638:c90ae1400bf2 508 &service_uuid,
Vincent Coubard 638:c90ae1400bf2 509 &(p_dfu->service_handle));
Vincent Coubard 638:c90ae1400bf2 510 if (err_code != NRF_SUCCESS)
Vincent Coubard 638:c90ae1400bf2 511 {
Vincent Coubard 638:c90ae1400bf2 512 return err_code;
Vincent Coubard 638:c90ae1400bf2 513 }
Vincent Coubard 638:c90ae1400bf2 514
Vincent Coubard 638:c90ae1400bf2 515 p_dfu->uuid_type = service_uuid.type;
Vincent Coubard 638:c90ae1400bf2 516
Vincent Coubard 638:c90ae1400bf2 517 err_code = dfu_pkt_char_add(p_dfu);
Vincent Coubard 638:c90ae1400bf2 518 if (err_code != NRF_SUCCESS)
Vincent Coubard 638:c90ae1400bf2 519 {
Vincent Coubard 638:c90ae1400bf2 520 return err_code;
Vincent Coubard 638:c90ae1400bf2 521 }
Vincent Coubard 638:c90ae1400bf2 522
Vincent Coubard 638:c90ae1400bf2 523 err_code = dfu_ctrl_pt_add(p_dfu);
Vincent Coubard 638:c90ae1400bf2 524 if (err_code != NRF_SUCCESS)
Vincent Coubard 638:c90ae1400bf2 525 {
Vincent Coubard 638:c90ae1400bf2 526 return err_code;
Vincent Coubard 638:c90ae1400bf2 527 }
Vincent Coubard 638:c90ae1400bf2 528
Vincent Coubard 638:c90ae1400bf2 529 err_code = dfu_rev_char_add(p_dfu, p_dfu_init);
Vincent Coubard 638:c90ae1400bf2 530 if (err_code != NRF_SUCCESS)
Vincent Coubard 638:c90ae1400bf2 531 {
Vincent Coubard 638:c90ae1400bf2 532 return err_code;
Vincent Coubard 638:c90ae1400bf2 533 }
Vincent Coubard 638:c90ae1400bf2 534
Vincent Coubard 638:c90ae1400bf2 535 p_dfu->evt_handler = p_dfu_init->evt_handler;
Vincent Coubard 638:c90ae1400bf2 536
Vincent Coubard 638:c90ae1400bf2 537 if (p_dfu_init->error_handler != NULL)
Vincent Coubard 638:c90ae1400bf2 538 {
Vincent Coubard 638:c90ae1400bf2 539 p_dfu->error_handler = p_dfu_init->error_handler;
Vincent Coubard 638:c90ae1400bf2 540 }
Vincent Coubard 638:c90ae1400bf2 541
Vincent Coubard 638:c90ae1400bf2 542 m_is_dfu_service_initialized = true;
Vincent Coubard 638:c90ae1400bf2 543
Vincent Coubard 638:c90ae1400bf2 544 return NRF_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 545 }
Vincent Coubard 638:c90ae1400bf2 546
Vincent Coubard 638:c90ae1400bf2 547
Vincent Coubard 638:c90ae1400bf2 548 void ble_dfu_on_ble_evt(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
Vincent Coubard 638:c90ae1400bf2 549 {
Vincent Coubard 638:c90ae1400bf2 550 if ((p_dfu == NULL) || (p_ble_evt == NULL))
Vincent Coubard 638:c90ae1400bf2 551 {
Vincent Coubard 638:c90ae1400bf2 552 return;
Vincent Coubard 638:c90ae1400bf2 553 }
Vincent Coubard 638:c90ae1400bf2 554
Vincent Coubard 638:c90ae1400bf2 555 if (p_dfu->evt_handler != NULL)
Vincent Coubard 638:c90ae1400bf2 556 {
Vincent Coubard 638:c90ae1400bf2 557 switch (p_ble_evt->header.evt_id)
Vincent Coubard 638:c90ae1400bf2 558 {
Vincent Coubard 638:c90ae1400bf2 559 case BLE_GAP_EVT_CONNECTED:
Vincent Coubard 638:c90ae1400bf2 560 on_connect(p_dfu, p_ble_evt);
Vincent Coubard 638:c90ae1400bf2 561 break;
Vincent Coubard 638:c90ae1400bf2 562
Vincent Coubard 638:c90ae1400bf2 563 case BLE_GATTS_EVT_WRITE:
Vincent Coubard 638:c90ae1400bf2 564 on_write(p_dfu, p_ble_evt);
Vincent Coubard 638:c90ae1400bf2 565 break;
Vincent Coubard 638:c90ae1400bf2 566
Vincent Coubard 638:c90ae1400bf2 567 case BLE_GAP_EVT_DISCONNECTED:
Vincent Coubard 638:c90ae1400bf2 568 on_disconnect(p_dfu, p_ble_evt);
Vincent Coubard 638:c90ae1400bf2 569 break;
Vincent Coubard 638:c90ae1400bf2 570
Vincent Coubard 638:c90ae1400bf2 571 case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
Vincent Coubard 638:c90ae1400bf2 572 on_rw_authorize_req(p_dfu, p_ble_evt);
Vincent Coubard 638:c90ae1400bf2 573 break;
Vincent Coubard 638:c90ae1400bf2 574
Vincent Coubard 638:c90ae1400bf2 575 default:
Vincent Coubard 638:c90ae1400bf2 576 // No implementation needed.
Vincent Coubard 638:c90ae1400bf2 577 break;
Vincent Coubard 638:c90ae1400bf2 578 }
Vincent Coubard 638:c90ae1400bf2 579 }
Vincent Coubard 638:c90ae1400bf2 580 }
Vincent Coubard 638:c90ae1400bf2 581
Vincent Coubard 638:c90ae1400bf2 582
Vincent Coubard 638:c90ae1400bf2 583 uint32_t ble_dfu_bytes_rcvd_report(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd)
Vincent Coubard 638:c90ae1400bf2 584 {
Vincent Coubard 638:c90ae1400bf2 585 if (p_dfu == NULL)
Vincent Coubard 638:c90ae1400bf2 586 {
Vincent Coubard 638:c90ae1400bf2 587 return NRF_ERROR_NULL;
Vincent Coubard 638:c90ae1400bf2 588 }
Vincent Coubard 638:c90ae1400bf2 589
Vincent Coubard 638:c90ae1400bf2 590 if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
Vincent Coubard 638:c90ae1400bf2 591 {
Vincent Coubard 638:c90ae1400bf2 592 return NRF_ERROR_INVALID_STATE;
Vincent Coubard 638:c90ae1400bf2 593 }
Vincent Coubard 638:c90ae1400bf2 594
Vincent Coubard 638:c90ae1400bf2 595 ble_gatts_hvx_params_t hvx_params;
Vincent Coubard 638:c90ae1400bf2 596 uint16_t index = 0;
Vincent Coubard 638:c90ae1400bf2 597
Vincent Coubard 638:c90ae1400bf2 598 // Encode the Op Code.
Vincent Coubard 638:c90ae1400bf2 599 m_notif_buffer[index++] = OP_CODE_RESPONSE;
Vincent Coubard 638:c90ae1400bf2 600
Vincent Coubard 638:c90ae1400bf2 601 // Encode the Reqest Op Code.
Vincent Coubard 638:c90ae1400bf2 602 m_notif_buffer[index++] = OP_CODE_IMAGE_SIZE_REQ;
Vincent Coubard 638:c90ae1400bf2 603
Vincent Coubard 638:c90ae1400bf2 604 // Encode the Response Value.
Vincent Coubard 638:c90ae1400bf2 605 m_notif_buffer[index++] = (uint8_t)BLE_DFU_RESP_VAL_SUCCESS;
Vincent Coubard 638:c90ae1400bf2 606
Vincent Coubard 638:c90ae1400bf2 607 index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]);
Vincent Coubard 638:c90ae1400bf2 608
Vincent Coubard 638:c90ae1400bf2 609 memset(&hvx_params, 0, sizeof(hvx_params));
Vincent Coubard 638:c90ae1400bf2 610
Vincent Coubard 638:c90ae1400bf2 611 hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
Vincent Coubard 638:c90ae1400bf2 612 hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
Vincent Coubard 638:c90ae1400bf2 613 hvx_params.offset = 0;
Vincent Coubard 638:c90ae1400bf2 614 hvx_params.p_len = &index;
Vincent Coubard 638:c90ae1400bf2 615 hvx_params.p_data = m_notif_buffer;
Vincent Coubard 638:c90ae1400bf2 616
Vincent Coubard 638:c90ae1400bf2 617 return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
Vincent Coubard 638:c90ae1400bf2 618 }
Vincent Coubard 638:c90ae1400bf2 619
Vincent Coubard 638:c90ae1400bf2 620
Vincent Coubard 638:c90ae1400bf2 621 uint32_t ble_dfu_pkts_rcpt_notify(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd)
Vincent Coubard 638:c90ae1400bf2 622 {
Vincent Coubard 638:c90ae1400bf2 623 if (p_dfu == NULL)
Vincent Coubard 638:c90ae1400bf2 624 {
Vincent Coubard 638:c90ae1400bf2 625 return NRF_ERROR_NULL;
Vincent Coubard 638:c90ae1400bf2 626 }
Vincent Coubard 638:c90ae1400bf2 627
Vincent Coubard 638:c90ae1400bf2 628 if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
Vincent Coubard 638:c90ae1400bf2 629 {
Vincent Coubard 638:c90ae1400bf2 630 return NRF_ERROR_INVALID_STATE;
Vincent Coubard 638:c90ae1400bf2 631 }
Vincent Coubard 638:c90ae1400bf2 632
Vincent Coubard 638:c90ae1400bf2 633 ble_gatts_hvx_params_t hvx_params;
Vincent Coubard 638:c90ae1400bf2 634 uint16_t index = 0;
Vincent Coubard 638:c90ae1400bf2 635
Vincent Coubard 638:c90ae1400bf2 636 m_notif_buffer[index++] = OP_CODE_PKT_RCPT_NOTIF;
Vincent Coubard 638:c90ae1400bf2 637
Vincent Coubard 638:c90ae1400bf2 638 index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]);
Vincent Coubard 638:c90ae1400bf2 639
Vincent Coubard 638:c90ae1400bf2 640 memset(&hvx_params, 0, sizeof(hvx_params));
Vincent Coubard 638:c90ae1400bf2 641
Vincent Coubard 638:c90ae1400bf2 642 hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
Vincent Coubard 638:c90ae1400bf2 643 hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
Vincent Coubard 638:c90ae1400bf2 644 hvx_params.offset = 0;
Vincent Coubard 638:c90ae1400bf2 645 hvx_params.p_len = &index;
Vincent Coubard 638:c90ae1400bf2 646 hvx_params.p_data = m_notif_buffer;
Vincent Coubard 638:c90ae1400bf2 647
Vincent Coubard 638:c90ae1400bf2 648 return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
Vincent Coubard 638:c90ae1400bf2 649 }
Vincent Coubard 638:c90ae1400bf2 650
Vincent Coubard 638:c90ae1400bf2 651
Vincent Coubard 638:c90ae1400bf2 652 uint32_t ble_dfu_response_send(ble_dfu_t * p_dfu,
Vincent Coubard 638:c90ae1400bf2 653 ble_dfu_procedure_t dfu_proc,
Vincent Coubard 638:c90ae1400bf2 654 ble_dfu_resp_val_t resp_val)
Vincent Coubard 638:c90ae1400bf2 655 {
Vincent Coubard 638:c90ae1400bf2 656 if (p_dfu == NULL)
Vincent Coubard 638:c90ae1400bf2 657 {
Vincent Coubard 638:c90ae1400bf2 658 return NRF_ERROR_NULL;
Vincent Coubard 638:c90ae1400bf2 659 }
Vincent Coubard 638:c90ae1400bf2 660
Vincent Coubard 638:c90ae1400bf2 661 if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
Vincent Coubard 638:c90ae1400bf2 662 {
Vincent Coubard 638:c90ae1400bf2 663 return NRF_ERROR_INVALID_STATE;
Vincent Coubard 638:c90ae1400bf2 664 }
Vincent Coubard 638:c90ae1400bf2 665
Vincent Coubard 638:c90ae1400bf2 666 ble_gatts_hvx_params_t hvx_params;
Vincent Coubard 638:c90ae1400bf2 667 uint16_t index = 0;
Vincent Coubard 638:c90ae1400bf2 668
Vincent Coubard 638:c90ae1400bf2 669 m_notif_buffer[index++] = OP_CODE_RESPONSE;
Vincent Coubard 638:c90ae1400bf2 670
Vincent Coubard 638:c90ae1400bf2 671 // Encode the Request Op code
Vincent Coubard 638:c90ae1400bf2 672 m_notif_buffer[index++] = (uint8_t)dfu_proc;
Vincent Coubard 638:c90ae1400bf2 673
Vincent Coubard 638:c90ae1400bf2 674 // Encode the Response Value.
Vincent Coubard 638:c90ae1400bf2 675 m_notif_buffer[index++] = (uint8_t)resp_val;
Vincent Coubard 638:c90ae1400bf2 676
Vincent Coubard 638:c90ae1400bf2 677 memset(&hvx_params, 0, sizeof(hvx_params));
Vincent Coubard 638:c90ae1400bf2 678
Vincent Coubard 638:c90ae1400bf2 679 hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
Vincent Coubard 638:c90ae1400bf2 680 hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
Vincent Coubard 638:c90ae1400bf2 681 hvx_params.offset = 0;
Vincent Coubard 638:c90ae1400bf2 682 hvx_params.p_len = &index;
Vincent Coubard 638:c90ae1400bf2 683 hvx_params.p_data = m_notif_buffer;
Vincent Coubard 638:c90ae1400bf2 684
Vincent Coubard 638:c90ae1400bf2 685 return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
Vincent Coubard 638:c90ae1400bf2 686 }