nrf_dfu_ble.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261
  1. /**
  2. * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "nrf_dfu_ble.h"
  41. #include <stddef.h>
  42. #include "sdk_common.h"
  43. #include "nrf_dfu_transport.h"
  44. #include "nrf_dfu_types.h"
  45. #include "nrf_dfu_req_handler.h"
  46. #include "nrf_dfu_handling_error.h"
  47. #include "nrf_sdm.h"
  48. #include "nrf_dfu_mbr.h"
  49. #include "nrf_bootloader_info.h"
  50. #include "ble.h"
  51. #include "ble_srv_common.h"
  52. #include "ble_hci.h"
  53. #include "nrf_sdh.h"
  54. #include "nrf_sdh_ble.h"
  55. #include "nrf_balloc.h"
  56. #include "nrf_delay.h"
  57. #include "nrf_dfu_settings.h"
  58. #include "nrf_dfu_ble.h"
  59. #define NRF_LOG_MODULE_NAME nrf_dfu_ble
  60. #include "nrf_log.h"
  61. NRF_LOG_MODULE_REGISTER();
  62. #ifndef NRF_DFU_BLE_ADV_INTERVAL
  63. #define NRF_DFU_BLE_ADV_INTERVAL 40 /* 40 * 0,625ms = 25ms */
  64. #warning "sdk_config.h is not up to date."
  65. #endif
  66. #define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */
  67. #define APP_ADV_DATA_HEADER_SIZE 9 /**< Size of encoded advertisement data header (not including device name). */
  68. #define APP_ADV_DURATION BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED /**< The advertising duration in units of 10 milliseconds. This is set to @ref BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED so that the advertisement is done as long as there there is a call to @ref dfu_transport_close function.*/
  69. #define GATT_HEADER_LEN 3 /**< GATT header length. */
  70. #define GATT_PAYLOAD(mtu) ((mtu) - GATT_HEADER_LEN) /**< Length of the ATT payload for a given ATT MTU. */
  71. #define MAX_DFU_PKT_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - GATT_HEADER_LEN) /**< Maximum length (in bytes) of the DFU Packet characteristic (3 bytes are used for the GATT opcode and handle). */
  72. #define MAX_RESPONSE_LEN 17 /**< Maximum length (in bytes) of the response to a Control Point command. */
  73. #define RESPONSE_HEADER_LEN 3 /**< The length of the header of a response. I.E. the index of the opcode-specific payload. */
  74. #define DFU_BLE_FLAG_INITIALIZED (1 << 0) /**< Flag to check if the DFU service was initialized by the application.*/
  75. #define DFU_BLE_FLAG_USE_ADV_NAME (1 << 1) /**< Flag to indicate that advertisement name is to be used. */
  76. #define DFU_BLE_RESETTING_SOON (1 << 2) /**< Flag to indicate that the device will reset soon. */
  77. #define BLE_OBSERVER_PRIO 2 /**< BLE observer priority. Controls the priority for BLE event handler. */
  78. #if (NRF_DFU_BLE_BUFFERS_OVERRIDE)
  79. /* If selected, use the override value. */
  80. #define MAX_DFU_BUFFERS NRF_DFU_BLE_BUFFERS
  81. #else
  82. #define MAX_DFU_BUFFERS ((CODE_PAGE_SIZE / MAX_DFU_PKT_LEN) + 1)
  83. #endif
  84. #if (NRF_DFU_BLE_REQUIRES_BONDS) && (!NRF_SDH_BLE_SERVICE_CHANGED)
  85. #error NRF_DFU_BLE_REQUIRES_BONDS requires NRF_SDH_BLE_SERVICE_CHANGED. \
  86. Please update the SoftDevice BLE stack configuration in sdk_config.h
  87. #endif
  88. #if (MAX_DFU_PKT_LEN % 4)
  89. #error Payload length should be a multiple of four. \
  90. Payload length is set to NRF_SDH_BLE_GATT_MAX_MTU_SIZE - 3.
  91. #endif
  92. DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const ble_dfu_transport) =
  93. {
  94. .init_func = ble_dfu_transport_init,
  95. .close_func = ble_dfu_transport_close,
  96. };
  97. #if (NRF_DFU_BLE_REQUIRES_BONDS)
  98. static nrf_dfu_peer_data_t m_peer_data;
  99. #else
  100. static nrf_dfu_adv_name_t m_adv_name;
  101. #endif
  102. static uint32_t m_flags;
  103. static ble_dfu_t m_dfu; /**< Structure used to identify the Device Firmware Update service. */
  104. static uint16_t m_pkt_notif_target; /**< Number of packets of firmware data to be received before transmitting the next Packet Receipt Notification to the DFU Controller. */
  105. static uint16_t m_pkt_notif_target_cnt; /**< Number of packets of firmware data received after sending last Packet Receipt Notification or since the receipt of a @ref BLE_DFU_PKT_RCPT_NOTIF_ENABLED event from the DFU service, which ever occurs later.*/
  106. static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */
  107. static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; /**< Advertising handle used to identify an advertising set. */
  108. static nrf_dfu_observer_t m_observer; /**< Observer function called on certain events. */
  109. static ble_gap_conn_params_t const m_gap_conn_params =
  110. {
  111. .min_conn_interval = NRF_DFU_BLE_MIN_CONN_INTERVAL,
  112. .max_conn_interval = NRF_DFU_BLE_MAX_CONN_INTERVAL,
  113. /* This value is expressed in units of 10 ms, rather than 1 ms. */
  114. .conn_sup_timeout = NRF_DFU_BLE_CONN_SUP_TIMEOUT_MS / 10,
  115. .slave_latency = 0,
  116. };
  117. NRF_BALLOC_DEF(m_buffer_pool, MAX_DFU_PKT_LEN, MAX_DFU_BUFFERS);
  118. /**@brief Function for the Advertising functionality initialization.
  119. *
  120. * @details Encodes the required advertising data and passes it to the stack.
  121. * The advertising data encoded here is specific for DFU.
  122. */
  123. static uint32_t advertising_init(uint8_t adv_flags, ble_gap_adv_params_t const * const p_adv_params)
  124. {
  125. uint32_t err_code;
  126. uint16_t actual_device_name_length = BLE_GAP_ADV_SET_DATA_SIZE_MAX - APP_ADV_DATA_HEADER_SIZE;
  127. /* This needs to be static because of SoftDevice API requirements. */
  128. static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];
  129. ble_gap_adv_data_t m_adv_data =
  130. {
  131. .adv_data =
  132. {
  133. .p_data = m_enc_advdata,
  134. .len = APP_ADV_DATA_HEADER_SIZE,
  135. }
  136. };
  137. /* Encode flags. */
  138. m_enc_advdata[0] = 0x2;
  139. m_enc_advdata[1] = BLE_GAP_AD_TYPE_FLAGS;
  140. m_enc_advdata[2] = adv_flags;
  141. /* Encode 'more available' UUID list. */
  142. m_enc_advdata[3] = 0x3;
  143. m_enc_advdata[4] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE;
  144. m_enc_advdata[5] = LSB_16(BLE_DFU_SERVICE_UUID);
  145. m_enc_advdata[6] = MSB_16(BLE_DFU_SERVICE_UUID);
  146. /* Get GAP device name and length. */
  147. err_code = sd_ble_gap_device_name_get(&m_enc_advdata[9], &actual_device_name_length);
  148. if (err_code != NRF_SUCCESS)
  149. {
  150. return err_code;
  151. }
  152. // Set GAP device in advertising data.
  153. m_enc_advdata[7] = actual_device_name_length + 1; // (actual_length + ADV_AD_TYPE_FIELD_SIZE(1))
  154. m_enc_advdata[8] = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
  155. m_adv_data.adv_data.len += actual_device_name_length;
  156. return sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, p_adv_params);
  157. }
  158. /**@brief Function for starting advertising.
  159. */
  160. static uint32_t advertising_start(void)
  161. {
  162. uint32_t err_code;
  163. uint8_t adv_flag = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
  164. ble_gap_adv_params_t adv_params =
  165. {
  166. .properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED,
  167. .p_peer_addr = NULL,
  168. .filter_policy = BLE_GAP_ADV_FP_ANY,
  169. .interval = NRF_DFU_BLE_ADV_INTERVAL,
  170. .duration = APP_ADV_DURATION,
  171. .primary_phy = BLE_GAP_PHY_1MBPS,
  172. };
  173. NRF_LOG_DEBUG("Advertising...");
  174. #if (NRF_DFU_BLE_REQUIRES_BONDS)
  175. ble_gap_irk_t empty_irk = {{0}};
  176. if (memcmp(m_peer_data.ble_id.id_info.irk, empty_irk.irk, sizeof(ble_gap_irk_t)) != 0)
  177. {
  178. adv_flag = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
  179. adv_params.filter_policy = BLE_GAP_ADV_FP_FILTER_CONNREQ;
  180. ble_gap_addr_t const * const p_gap_addr = &m_peer_data.ble_id.id_addr_info;
  181. ble_gap_id_key_t const * const p_gap_id_key = &m_peer_data.ble_id;
  182. err_code = sd_ble_gap_whitelist_set(&p_gap_addr, 1);
  183. if (err_code != NRF_SUCCESS)
  184. {
  185. NRF_LOG_WARNING("sd_ble_gap_whitelist_set() returned %s",
  186. NRF_LOG_ERROR_STRING_GET(err_code));
  187. }
  188. err_code = sd_ble_gap_device_identities_set(&p_gap_id_key, NULL, 1);
  189. if (err_code != NRF_SUCCESS)
  190. {
  191. NRF_LOG_WARNING("sd_ble_gap_device_identities_set() returned %s",
  192. NRF_LOG_ERROR_STRING_GET(err_code));
  193. }
  194. }
  195. #endif /* NRF_DFU_BLE_REQUIRES_BONDS */
  196. err_code = advertising_init(adv_flag, &adv_params);
  197. VERIFY_SUCCESS(err_code);
  198. err_code = sd_ble_gap_adv_stop(m_adv_handle);
  199. UNUSED_RETURN_VALUE(err_code);
  200. return sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
  201. }
  202. static bool is_cccd_configured(ble_dfu_t * p_dfu)
  203. {
  204. uint8_t cccd_val_buf[BLE_CCCD_VALUE_LEN];
  205. ble_gatts_value_t gatts_value =
  206. {
  207. .len = BLE_CCCD_VALUE_LEN,
  208. .p_value = cccd_val_buf
  209. };
  210. /* Check the CCCD Value of DFU Control Point. */
  211. uint32_t err_code = sd_ble_gatts_value_get(m_conn_handle,
  212. p_dfu->dfu_ctrl_pt_handles.cccd_handle,
  213. &gatts_value);
  214. VERIFY_SUCCESS(err_code);
  215. return ble_srv_is_notification_enabled(cccd_val_buf);
  216. }
  217. static ret_code_t response_send(uint8_t * p_buf, uint16_t len)
  218. {
  219. ble_gatts_hvx_params_t hvx_params =
  220. {
  221. .handle = m_dfu.dfu_ctrl_pt_handles.value_handle,
  222. .type = BLE_GATT_HVX_NOTIFICATION,
  223. .p_data = (uint8_t *)(p_buf),
  224. .p_len = &len,
  225. };
  226. return sd_ble_gatts_hvx(m_conn_handle, &hvx_params);
  227. }
  228. #if (NRF_DFU_BLE_REQUIRES_BONDS)
  229. static uint32_t service_changed_send(void)
  230. {
  231. uint32_t err_code;
  232. NRF_LOG_DEBUG("Sending Service Changed indication");
  233. err_code = sd_ble_gatts_sys_attr_set(m_conn_handle,
  234. m_peer_data.sys_serv_attr,
  235. sizeof(m_peer_data.sys_serv_attr),
  236. BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS);
  237. VERIFY_SUCCESS(err_code);
  238. err_code = sd_ble_gatts_sys_attr_set(m_conn_handle,
  239. NULL,
  240. 0,
  241. BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS);
  242. VERIFY_SUCCESS(err_code);
  243. err_code = sd_ble_gatts_service_changed(m_conn_handle, m_dfu.service_handle, 0xFFFF);
  244. if ( (err_code == BLE_ERROR_INVALID_CONN_HANDLE)
  245. || (err_code == NRF_ERROR_INVALID_STATE)
  246. || (err_code == NRF_ERROR_BUSY))
  247. {
  248. /* These errors can be expected when trying to send a Service Changed indication */
  249. /* if the CCCD is not set to indicate. Thus, set the returning error code to success. */
  250. NRF_LOG_WARNING("Client did not have the Service Changed indication set to enabled."
  251. "Error: 0x%08x", err_code);
  252. err_code = NRF_SUCCESS;
  253. }
  254. return err_code;
  255. }
  256. #endif
  257. /**@brief Function for encoding the beginning of a response.
  258. *
  259. * @param[inout] p_buffer The buffer to encode into.
  260. * @param[in] op_code The opcode of the response.
  261. * @param[in] result The result of the operation.
  262. *
  263. * @return The length added to the buffer.
  264. */
  265. static uint32_t response_prepare(uint8_t * p_buffer, uint8_t op_code, uint8_t result)
  266. {
  267. ASSERT(p_buffer);
  268. p_buffer[0] = NRF_DFU_OP_RESPONSE;
  269. p_buffer[1] = op_code;
  270. p_buffer[2] = result;
  271. return RESPONSE_HEADER_LEN;
  272. }
  273. /**@brief Function for encoding a select object response into a buffer.
  274. *
  275. * The select object response consists of a maximum object size, a firmware offset, and a CRC value.
  276. *
  277. * @param[inout] p_buffer The buffer to encode the response into.
  278. * @param[in] max_size The maximum object size value to encode.
  279. * @param[in] fw_offset The firmware offset value to encode.
  280. * @param[in] crc The CRC value to encode.
  281. *
  282. * @return The length added to the buffer.
  283. */
  284. static uint32_t response_select_obj_add(uint8_t * p_buffer,
  285. uint32_t max_size,
  286. uint32_t fw_offset,
  287. uint32_t crc)
  288. {
  289. uint16_t offset = uint32_encode(max_size, &p_buffer[RESPONSE_HEADER_LEN]);
  290. offset += uint32_encode(fw_offset, &p_buffer[RESPONSE_HEADER_LEN + offset]);
  291. offset += uint32_encode(crc, &p_buffer[RESPONSE_HEADER_LEN + offset]);
  292. return offset;
  293. }
  294. /**@brief Function for encoding a CRC response into a buffer.
  295. *
  296. * The CRC response consists of a firmware offset and a CRC value.
  297. *
  298. * @param[inout] p_buffer The buffer to encode the response into.
  299. * @param[in] fw_offset The firmware offset value to encode.
  300. * @param[in] crc The CRC value to encode.
  301. *
  302. * @return The length added to the buffer.
  303. */
  304. static uint32_t response_crc_add(uint8_t * p_buffer, uint32_t fw_offset, uint32_t crc)
  305. {
  306. uint16_t offset = uint32_encode(fw_offset, &p_buffer[RESPONSE_HEADER_LEN]);
  307. offset += uint32_encode(crc, &p_buffer[RESPONSE_HEADER_LEN + offset]);
  308. return offset;
  309. }
  310. /**@brief Function for appending an extended error code to the response buffer.
  311. *
  312. * @param[inout] p_buffer The buffer to append the extended error code to.
  313. * @param[in] result The error code to append.
  314. * @param[in] buf_offset The current length of the buffer.
  315. *
  316. * @return The length added to the buffer.
  317. */
  318. static uint32_t response_ext_err_payload_add(uint8_t * p_buffer, uint8_t result, uint32_t buf_offset)
  319. {
  320. p_buffer[buf_offset] = ext_error_get();
  321. (void) ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR);
  322. return 1;
  323. }
  324. static void ble_dfu_req_handler_callback(nrf_dfu_response_t * p_res, void * p_context)
  325. {
  326. ASSERT(p_res);
  327. ASSERT(p_context);
  328. uint8_t len = 0;
  329. uint8_t buffer[MAX_RESPONSE_LEN] = {0};
  330. if (p_res->request == NRF_DFU_OP_OBJECT_WRITE)
  331. {
  332. --m_pkt_notif_target_cnt;
  333. if ((m_pkt_notif_target == 0) || (m_pkt_notif_target_cnt && m_pkt_notif_target > 0))
  334. {
  335. return;
  336. }
  337. /* Reply with a CRC message and reset the packet counter. */
  338. m_pkt_notif_target_cnt = m_pkt_notif_target;
  339. p_res->request = NRF_DFU_OP_CRC_GET;
  340. }
  341. len += response_prepare(buffer, p_res->request, p_res->result);
  342. if (p_res->result != NRF_DFU_RES_CODE_SUCCESS)
  343. {
  344. NRF_LOG_WARNING("DFU request %d failed with error: 0x%x", p_res->request, p_res->result);
  345. if (p_res->result == NRF_DFU_RES_CODE_EXT_ERROR)
  346. {
  347. len += response_ext_err_payload_add(buffer, p_res->result, len);
  348. }
  349. (void) response_send(buffer, len);
  350. return;
  351. }
  352. switch (p_res->request)
  353. {
  354. case NRF_DFU_OP_OBJECT_CREATE:
  355. case NRF_DFU_OP_OBJECT_EXECUTE:
  356. break;
  357. case NRF_DFU_OP_OBJECT_SELECT:
  358. {
  359. len += response_select_obj_add(buffer,
  360. p_res->select.max_size,
  361. p_res->select.offset,
  362. p_res->select.crc);
  363. } break;
  364. case NRF_DFU_OP_OBJECT_WRITE:
  365. {
  366. len += response_crc_add(buffer, p_res->write.offset, p_res->write.crc);
  367. } break;
  368. case NRF_DFU_OP_CRC_GET:
  369. {
  370. len += response_crc_add(buffer, p_res->crc.offset, p_res->crc.crc);
  371. } break;
  372. default:
  373. {
  374. // No action.
  375. } break;
  376. }
  377. (void) response_send(buffer, len);
  378. }
  379. /**@brief Function for handling a Write event on the Control Point characteristic.
  380. *
  381. * @param[in] p_dfu DFU Service Structure.
  382. * @param[in] p_ble_write_evt Pointer to the write event received from BLE stack.
  383. *
  384. * @return NRF_SUCCESS on successful processing of control point write. Otherwise an error code.
  385. */
  386. static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t const * p_ble_write_evt)
  387. {
  388. //lint -save -e415 -e416 : Out-of-bounds access on p_ble_write_evt->data
  389. nrf_dfu_request_t request =
  390. {
  391. .request = (nrf_dfu_op_t)(p_ble_write_evt->data[0]),
  392. .p_context = p_dfu,
  393. .callback.response = ble_dfu_req_handler_callback,
  394. };
  395. switch (request.request)
  396. {
  397. case NRF_DFU_OP_OBJECT_SELECT:
  398. {
  399. /* Set object type to read info about */
  400. request.select.object_type = p_ble_write_evt->data[1];
  401. } break;
  402. case NRF_DFU_OP_OBJECT_CREATE:
  403. {
  404. /* Reset the packet receipt notification on create object */
  405. m_pkt_notif_target_cnt = m_pkt_notif_target;
  406. request.create.object_type = p_ble_write_evt->data[1];
  407. request.create.object_size = uint32_decode(&(p_ble_write_evt->data[2]));
  408. if (request.create.object_type == NRF_DFU_OBJ_TYPE_COMMAND)
  409. {
  410. /* Activity on the current transport. Close all except the current one. */
  411. (void) nrf_dfu_transports_close(&ble_dfu_transport);
  412. }
  413. } break;
  414. case NRF_DFU_OP_RECEIPT_NOTIF_SET:
  415. {
  416. NRF_LOG_DEBUG("Set receipt notif");
  417. m_pkt_notif_target = uint16_decode(&(p_ble_write_evt->data[1]));
  418. m_pkt_notif_target_cnt = m_pkt_notif_target;
  419. } break;
  420. default:
  421. break;
  422. }
  423. //lint -restore : Out-of-bounds access
  424. return nrf_dfu_req_handler_on_req(&request);
  425. }
  426. /**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event from the
  427. * SoftDevice.
  428. *
  429. * @param[in] p_dfu DFU Service Structure.
  430. * @param[in] p_ble_evt Pointer to the event received from BLE stack.
  431. */
  432. static bool on_rw_authorize_req(ble_dfu_t * p_dfu, ble_evt_t const * p_ble_evt)
  433. {
  434. uint32_t err_code;
  435. ble_gatts_evt_rw_authorize_request_t const * p_authorize_request;
  436. ble_gatts_evt_write_t const * p_ble_write_evt;
  437. p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request);
  438. p_ble_write_evt = &(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write);
  439. if ( (p_authorize_request->type != BLE_GATTS_AUTHORIZE_TYPE_WRITE)
  440. || (p_authorize_request->request.write.handle != p_dfu->dfu_ctrl_pt_handles.value_handle)
  441. || (p_authorize_request->request.write.op != BLE_GATTS_OP_WRITE_REQ))
  442. {
  443. return false;
  444. }
  445. ble_gatts_rw_authorize_reply_params_t auth_reply =
  446. {
  447. .type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
  448. .params.write.update = 1,
  449. .params.write.offset = p_ble_write_evt->offset,
  450. .params.write.len = p_ble_write_evt->len,
  451. .params.write.p_data = p_ble_write_evt->data,
  452. };
  453. if (!is_cccd_configured(p_dfu))
  454. {
  455. /* Send an error response to the peer indicating that the CCCD is improperly configured. */
  456. auth_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR;
  457. /* Ignore response of auth reply */
  458. (void) sd_ble_gatts_rw_authorize_reply(m_conn_handle, &auth_reply);
  459. return false;
  460. }
  461. else
  462. {
  463. auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
  464. err_code = sd_ble_gatts_rw_authorize_reply(m_conn_handle, &auth_reply);
  465. return err_code == NRF_SUCCESS ? true : false;
  466. }
  467. }
  468. static void on_flash_write(void * p_buf)
  469. {
  470. NRF_LOG_DEBUG("Freeing buffer %p", p_buf);
  471. nrf_balloc_free(&m_buffer_pool, p_buf);
  472. }
  473. /**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice.
  474. *
  475. * @param[in] p_dfu DFU Service Structure.
  476. * @param[in] p_ble_evt Pointer to the event received from BLE stack.
  477. */
  478. static void on_write(ble_dfu_t * p_dfu, ble_evt_t const * p_ble_evt)
  479. {
  480. ble_gatts_evt_write_t const * const p_write_evt = &p_ble_evt->evt.gatts_evt.params.write;
  481. if (p_write_evt->handle != p_dfu->dfu_pkt_handles.value_handle)
  482. {
  483. return;
  484. }
  485. /* Allocate a buffer to receive data. */
  486. uint8_t * p_balloc_buf = nrf_balloc_alloc(&m_buffer_pool);
  487. if (p_balloc_buf == NULL)
  488. {
  489. /* Operations are retried by the host; do not give up here. */
  490. NRF_LOG_WARNING("cannot allocate memory buffer!");
  491. return;
  492. }
  493. NRF_LOG_DEBUG("Buffer %p acquired, len %d (%d)",
  494. p_balloc_buf, p_write_evt->len, MAX_DFU_PKT_LEN);
  495. /* Copy payload into buffer. */
  496. memcpy(p_balloc_buf, p_write_evt->data, p_write_evt->len);
  497. /* Set up the request. */
  498. nrf_dfu_request_t request =
  499. {
  500. .request = NRF_DFU_OP_OBJECT_WRITE,
  501. .p_context = p_dfu,
  502. .callback =
  503. {
  504. .response = ble_dfu_req_handler_callback,
  505. .write = on_flash_write,
  506. }
  507. };
  508. /* Set up the request buffer. */
  509. request.write.p_data = p_balloc_buf;
  510. request.write.len = p_write_evt->len;
  511. /* Schedule handling of the request. */
  512. ret_code_t rc = nrf_dfu_req_handler_on_req(&request);
  513. if (rc != NRF_SUCCESS)
  514. {
  515. /* The error is logged in nrf_dfu_req_handler_on_req().
  516. * Free the buffer.
  517. */
  518. (void) nrf_balloc_free(&m_buffer_pool, p_balloc_buf);
  519. }
  520. }
  521. /**@brief Function for the Application's SoftDevice event handler.
  522. *
  523. * @param[in] p_ble_evt SoftDevice event.
  524. */
  525. static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
  526. {
  527. uint32_t err_code;
  528. ble_gap_evt_t const * const p_gap = &p_ble_evt->evt.gap_evt;
  529. switch (p_ble_evt->header.evt_id)
  530. {
  531. case BLE_GAP_EVT_CONNECTED:
  532. {
  533. NRF_LOG_DEBUG("Connected");
  534. m_conn_handle = p_gap->conn_handle;
  535. if (m_observer)
  536. {
  537. m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED);
  538. }
  539. err_code = sd_ble_gap_conn_param_update(m_conn_handle, &m_gap_conn_params);
  540. if (err_code != NRF_SUCCESS)
  541. {
  542. NRF_LOG_ERROR("Failure to update connection parameters: 0x%x", err_code);
  543. }
  544. } break;
  545. case BLE_GAP_EVT_DISCONNECTED:
  546. {
  547. m_conn_handle = BLE_CONN_HANDLE_INVALID;
  548. /* Restart advertising so that the DFU Controller can reconnect if possible. */
  549. if (!(m_flags & DFU_BLE_RESETTING_SOON))
  550. {
  551. err_code = advertising_start();
  552. APP_ERROR_CHECK(err_code);
  553. }
  554. if (m_observer)
  555. {
  556. m_observer(NRF_DFU_EVT_TRANSPORT_DEACTIVATED);
  557. }
  558. } break;
  559. case BLE_GATTS_EVT_WRITE:
  560. {
  561. on_write(&m_dfu, p_ble_evt);
  562. } break;
  563. case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
  564. {
  565. uint16_t const mtu_requested =
  566. p_ble_evt->evt.gatts_evt.params.exchange_mtu_request.client_rx_mtu;
  567. /* If the requested MTU is smaller than the maximum, we can accept with the given
  568. * stack configuration, and the payload is not word-aligned, reply with a smaller MTU
  569. * that has a word-aligned payload. This ensures that the length of data we write to
  570. * flash is a multiple of the word size.
  571. */
  572. uint16_t mtu_reply;
  573. if (mtu_requested < NRF_SDH_BLE_GATT_MAX_MTU_SIZE)
  574. {
  575. /* Round the payload size down to a multiple of 4 so it is word-aligned. */
  576. if (GATT_PAYLOAD(mtu_requested) % 4)
  577. {
  578. mtu_reply = GATT_PAYLOAD(mtu_requested) - 4;
  579. mtu_reply = ALIGN_NUM(4, mtu_reply);
  580. /* Add the header len to the MTU. */
  581. mtu_reply += GATT_HEADER_LEN;
  582. }
  583. else
  584. {
  585. mtu_reply = mtu_requested;
  586. }
  587. }
  588. else
  589. {
  590. mtu_reply = NRF_SDH_BLE_GATT_MAX_MTU_SIZE;
  591. }
  592. NRF_LOG_DEBUG("Received BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST (request: %d, reply: %d).",
  593. mtu_requested, mtu_reply);
  594. err_code = sd_ble_gatts_exchange_mtu_reply(m_conn_handle, mtu_reply);
  595. APP_ERROR_CHECK(err_code);
  596. } break;
  597. #ifndef S112
  598. case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
  599. {
  600. NRF_LOG_DEBUG("Received BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST.");
  601. ble_gap_data_length_params_t const dlp =
  602. {
  603. .max_rx_octets = BLE_GAP_DATA_LENGTH_AUTO,
  604. .max_tx_octets = BLE_GAP_DATA_LENGTH_AUTO,
  605. };
  606. err_code = sd_ble_gap_data_length_update(p_ble_evt->evt.gatts_evt.conn_handle,
  607. &dlp, NULL);
  608. APP_ERROR_CHECK(err_code);
  609. } break;
  610. case BLE_GAP_EVT_DATA_LENGTH_UPDATE:
  611. {
  612. NRF_LOG_DEBUG("Received BLE_GAP_EVT_DATA_LENGTH_UPDATE (%u, max_rx_time %u).",
  613. p_gap->params.data_length_update.effective_params.max_rx_octets,
  614. p_gap->params.data_length_update.effective_params.max_rx_time_us);
  615. } break;
  616. #endif
  617. case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
  618. {
  619. NRF_LOG_DEBUG("Received BLE_GAP_EVT_SEC_PARAMS_REQUEST");
  620. uint16_t cccd;
  621. ble_gatts_value_t gatts_value =
  622. {
  623. .len = BLE_CCCD_VALUE_LEN,
  624. .p_value = (uint8_t*)&cccd
  625. };
  626. err_code = sd_ble_gatts_value_get(m_conn_handle,
  627. BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED,
  628. &gatts_value);
  629. APP_ERROR_CHECK(err_code);
  630. NRF_LOG_DEBUG("CCCD for service changed is 0x%04x", cccd);
  631. err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
  632. BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP,
  633. NULL,
  634. NULL);
  635. APP_ERROR_CHECK(err_code);
  636. } break;
  637. case BLE_GAP_EVT_CONN_PARAM_UPDATE:
  638. {
  639. NRF_LOG_DEBUG("Received BLE_GAP_EVT_CONN_PARAM_UPDATE");
  640. ble_gap_conn_params_t const * p_conn =
  641. &p_gap->params.conn_param_update.conn_params;
  642. NRF_LOG_DEBUG("max_conn_interval: %d", p_conn->max_conn_interval);
  643. NRF_LOG_DEBUG("min_conn_interval: %d", p_conn->min_conn_interval);
  644. NRF_LOG_DEBUG("slave_latency: %d", p_conn->slave_latency);
  645. NRF_LOG_DEBUG("conn_sup_timeout: %d", p_conn->conn_sup_timeout);
  646. } break;
  647. #if !defined(S112) && !defined(S113)
  648. case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
  649. {
  650. NRF_LOG_DEBUG("Received BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST");
  651. err_code = sd_ble_gap_conn_param_update(m_conn_handle,
  652. &p_gap->params.conn_param_update_request.conn_params);
  653. if (err_code != NRF_SUCCESS)
  654. {
  655. NRF_LOG_ERROR("Failure to update connection parameter request: 0x%x", err_code);
  656. }
  657. APP_ERROR_CHECK(err_code);
  658. } break;
  659. #endif
  660. case BLE_GAP_EVT_PHY_UPDATE:
  661. {
  662. NRF_LOG_DEBUG("Received BLE_GAP_EVT_PHY_UPDATE (RX:%d, TX:%d, status:%d)",
  663. p_gap->params.phy_update.rx_phy,
  664. p_gap->params.phy_update.tx_phy,
  665. p_gap->params.phy_update.status);
  666. break;
  667. }
  668. case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
  669. {
  670. NRF_LOG_DEBUG("Received BLE_GAP_EVT_PHY_UPDATE_REQUEST.");
  671. ble_gap_phys_t const phys =
  672. {
  673. .rx_phys = BLE_GAP_PHY_AUTO,
  674. .tx_phys = BLE_GAP_PHY_AUTO,
  675. };
  676. err_code = sd_ble_gap_phy_update(p_gap->conn_handle, &phys);
  677. APP_ERROR_CHECK(err_code);
  678. } break;
  679. case BLE_GATTS_EVT_TIMEOUT:
  680. {
  681. if (p_ble_evt->evt.gatts_evt.params.timeout.src == BLE_GATT_TIMEOUT_SRC_PROTOCOL)
  682. {
  683. err_code = sd_ble_gap_disconnect(m_conn_handle,
  684. BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
  685. APP_ERROR_CHECK(err_code);
  686. }
  687. } break;
  688. case BLE_EVT_USER_MEM_REQUEST:
  689. {
  690. err_code = sd_ble_user_mem_reply(m_conn_handle, NULL);
  691. APP_ERROR_CHECK(err_code);
  692. } break;
  693. case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
  694. {
  695. if (p_ble_evt->evt.gatts_evt.params.authorize_request.type
  696. != BLE_GATTS_AUTHORIZE_TYPE_INVALID)
  697. {
  698. if (on_rw_authorize_req(&m_dfu, p_ble_evt))
  699. {
  700. err_code = on_ctrl_pt_write(&m_dfu,
  701. &(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write));
  702. if (err_code != NRF_SUCCESS)
  703. {
  704. NRF_LOG_ERROR("Could not handle on_ctrl_pt_write. err_code: 0x%04x", err_code);
  705. }
  706. }
  707. }
  708. } break;
  709. case BLE_GAP_EVT_SEC_INFO_REQUEST:
  710. {
  711. NRF_LOG_DEBUG("Received BLE_GAP_EVT_SEC_INFO_REQUEST");
  712. ble_gap_enc_info_t * p_enc_info = NULL;
  713. ble_gap_irk_t * p_id_info = NULL;
  714. #if (NRF_DFU_BLE_REQUIRES_BONDS)
  715. /* If there is a match in diversifier, then set the correct keys. */
  716. if (p_gap->params.sec_info_request.master_id.ediv ==
  717. m_peer_data.enc_key.master_id.ediv)
  718. {
  719. p_enc_info = &m_peer_data.enc_key.enc_info;
  720. }
  721. p_id_info = &m_peer_data.ble_id.id_info;
  722. #endif
  723. err_code = sd_ble_gap_sec_info_reply(p_gap->conn_handle, p_enc_info, p_id_info, NULL);
  724. APP_ERROR_CHECK(err_code);
  725. } break;
  726. case BLE_GAP_EVT_CONN_SEC_UPDATE:
  727. case BLE_GATTS_EVT_SYS_ATTR_MISSING:
  728. {
  729. #if (NRF_DFU_BLE_REQUIRES_BONDS)
  730. err_code = service_changed_send();
  731. #else
  732. err_code = sd_ble_gatts_sys_attr_set(p_gap->conn_handle, NULL, 0, 0);
  733. #endif
  734. APP_ERROR_CHECK(err_code);
  735. NRF_LOG_DEBUG("Finished handling conn sec update");
  736. } break;
  737. default:
  738. /* No implementation needed. */
  739. break;
  740. }
  741. }
  742. #if (!NRF_DFU_BLE_REQUIRES_BONDS)
  743. static uint32_t gap_address_change(void)
  744. {
  745. uint32_t err_code;
  746. ble_gap_addr_t addr;
  747. err_code = sd_ble_gap_addr_get(&addr);
  748. VERIFY_SUCCESS(err_code);
  749. /* Increase the BLE address by one when advertising openly. */
  750. addr.addr[0] += 1;
  751. err_code = sd_ble_gap_addr_set(&addr);
  752. VERIFY_SUCCESS(err_code);
  753. return NRF_SUCCESS;
  754. }
  755. #endif
  756. /**@brief Function for initializing GAP.
  757. *
  758. * @details This function sets up all necessary GAP (Generic Access Profile) parameters of
  759. * the device. It also sets the permissions and appearance.
  760. */
  761. static uint32_t gap_params_init(void)
  762. {
  763. uint32_t err_code;
  764. ble_gap_conn_sec_mode_t sec_mode;
  765. uint8_t const * device_name;
  766. uint32_t name_len;
  767. BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
  768. #if (!NRF_DFU_BLE_REQUIRES_BONDS)
  769. err_code = gap_address_change();
  770. VERIFY_SUCCESS(err_code);
  771. if ((m_flags & DFU_BLE_FLAG_USE_ADV_NAME) != 0)
  772. {
  773. NRF_LOG_DEBUG("Setting adv name: %s, length: %d", m_adv_name.name, m_adv_name.len);
  774. device_name = m_adv_name.name;
  775. name_len = m_adv_name.len;
  776. }
  777. else
  778. #endif
  779. {
  780. NRF_LOG_DEBUG("Using default advertising name");
  781. device_name = (uint8_t const *)(NRF_DFU_BLE_ADV_NAME);
  782. name_len = strlen(NRF_DFU_BLE_ADV_NAME);
  783. }
  784. err_code = sd_ble_gap_device_name_set(&sec_mode, device_name, name_len);
  785. VERIFY_SUCCESS(err_code);
  786. err_code = sd_ble_gap_ppcp_set(&m_gap_conn_params);
  787. return err_code;
  788. }
  789. static uint32_t ble_stack_init()
  790. {
  791. ret_code_t err_code;
  792. uint32_t ram_start = 0;
  793. /* Register as a BLE event observer to receive BLE events. */
  794. NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
  795. #if (!defined(NRF_DFU_BLE_SKIP_SD_INIT)) || (NRF_DFU_BLE_SKIP_SD_INIT == 0)
  796. err_code = nrf_dfu_mbr_init_sd();
  797. VERIFY_SUCCESS(err_code);
  798. NRF_LOG_DEBUG("Setting up vector table: 0x%08x", BOOTLOADER_START_ADDR);
  799. err_code = sd_softdevice_vector_table_base_set(BOOTLOADER_START_ADDR);
  800. VERIFY_SUCCESS(err_code);
  801. #endif
  802. NRF_LOG_DEBUG("Enabling SoftDevice.");
  803. err_code = nrf_sdh_enable_request();
  804. VERIFY_SUCCESS(err_code);
  805. /* Fetch the start address of the application RAM. */
  806. err_code = nrf_sdh_ble_app_ram_start_get(&ram_start);
  807. VERIFY_SUCCESS(err_code);
  808. NRF_LOG_DEBUG("Configuring BLE stack.");
  809. err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
  810. VERIFY_SUCCESS(err_code);
  811. /* Enable the BLE stack. */
  812. NRF_LOG_DEBUG("Enabling the BLE stack.");
  813. return nrf_sdh_ble_enable(&ram_start);
  814. }
  815. /**@brief Function for adding DFU Packet characteristic to the BLE Stack.
  816. *
  817. * @param[in] p_dfu DFU Service structure.
  818. *
  819. * @return NRF_SUCCESS on success. Otherwise an error code.
  820. */
  821. static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu)
  822. {
  823. ble_gatts_char_md_t char_md =
  824. {
  825. .char_props.write_wo_resp = 1,
  826. };
  827. ble_uuid_t char_uuid =
  828. {
  829. .type = p_dfu->uuid_type,
  830. .uuid = BLE_DFU_PKT_CHAR_UUID,
  831. };
  832. ble_gatts_attr_md_t attr_md =
  833. {
  834. .vloc = BLE_GATTS_VLOC_STACK,
  835. .vlen = 1,
  836. .write_perm =
  837. {
  838. .sm = 1,
  839. #if NRF_DFU_BLE_REQUIRES_BONDS
  840. .lv = 2,
  841. #else
  842. .lv = 1,
  843. #endif
  844. }
  845. };
  846. ble_gatts_attr_t attr_char_value =
  847. {
  848. .p_uuid = &char_uuid,
  849. .p_attr_md = &attr_md,
  850. .max_len = MAX_DFU_PKT_LEN,
  851. };
  852. return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
  853. &char_md,
  854. &attr_char_value,
  855. &p_dfu->dfu_pkt_handles);
  856. }
  857. /**@brief Function for adding DFU Control Point characteristic to the BLE Stack.
  858. *
  859. * @param[in] p_dfu DFU Service structure.
  860. *
  861. * @return NRF_SUCCESS on success. Otherwise an error code.
  862. */
  863. static uint32_t dfu_ctrl_pt_add(ble_dfu_t * const p_dfu)
  864. {
  865. ble_gatts_char_md_t char_md =
  866. {
  867. .char_props.write = 1,
  868. .char_props.notify = 1,
  869. };
  870. ble_uuid_t char_uuid =
  871. {
  872. .type = p_dfu->uuid_type,
  873. .uuid = BLE_DFU_CTRL_PT_UUID,
  874. };
  875. ble_gatts_attr_md_t attr_md =
  876. {
  877. .vloc = BLE_GATTS_VLOC_STACK,
  878. .wr_auth = 1,
  879. .vlen = 1,
  880. .write_perm =
  881. {
  882. .sm = 1,
  883. #if NRF_DFU_BLE_REQUIRES_BONDS
  884. .lv = 2,
  885. #else
  886. .lv = 1,
  887. #endif
  888. },
  889. };
  890. ble_gatts_attr_t attr_char_value =
  891. {
  892. .p_uuid = &char_uuid,
  893. .p_attr_md = &attr_md,
  894. .max_len = BLE_GATT_ATT_MTU_DEFAULT,
  895. };
  896. return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
  897. &char_md,
  898. &attr_char_value,
  899. &p_dfu->dfu_ctrl_pt_handles);
  900. }
  901. /**@brief Function for checking if the CCCD of DFU Control point is configured for Notification.
  902. *
  903. * @details This function checks if the CCCD of DFU Control Point characteristic is configured
  904. * for Notification by the DFU Controller.
  905. *
  906. * @param[in] p_dfu DFU Service structure.
  907. *
  908. * @return True if the CCCD of DFU Control Point characteristic is configured for Notification.
  909. * False otherwise.
  910. */
  911. uint32_t ble_dfu_init(ble_dfu_t * p_dfu)
  912. {
  913. ASSERT(p_dfu != NULL);
  914. ble_uuid_t service_uuid;
  915. uint32_t err_code;
  916. m_conn_handle = BLE_CONN_HANDLE_INVALID;
  917. BLE_UUID_BLE_ASSIGN(service_uuid, BLE_DFU_SERVICE_UUID);
  918. err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
  919. &service_uuid,
  920. &(p_dfu->service_handle));
  921. VERIFY_SUCCESS(err_code);
  922. ble_uuid128_t const base_uuid128 =
  923. {
  924. {
  925. 0x50, 0xEA, 0xDA, 0x30, 0x88, 0x83, 0xB8, 0x9F,
  926. 0x60, 0x4F, 0x15, 0xF3, 0x00, 0x00, 0xC9, 0x8E
  927. }
  928. };
  929. err_code = sd_ble_uuid_vs_add(&base_uuid128, &p_dfu->uuid_type);
  930. VERIFY_SUCCESS(err_code);
  931. err_code = dfu_pkt_char_add(p_dfu);
  932. VERIFY_SUCCESS(err_code);
  933. err_code = dfu_ctrl_pt_add(p_dfu);
  934. VERIFY_SUCCESS(err_code);
  935. return NRF_SUCCESS;
  936. }
  937. uint32_t ble_dfu_transport_init(nrf_dfu_observer_t observer)
  938. {
  939. uint32_t err_code = NRF_SUCCESS;
  940. if (m_flags & DFU_BLE_FLAG_INITIALIZED)
  941. {
  942. return err_code;
  943. }
  944. NRF_LOG_DEBUG("Initializing BLE DFU transport");
  945. m_observer = observer;
  946. err_code = nrf_balloc_init(&m_buffer_pool);
  947. UNUSED_RETURN_VALUE(err_code);
  948. err_code = ble_stack_init();
  949. VERIFY_SUCCESS(err_code);
  950. #if (NRF_DFU_BLE_REQUIRES_BONDS)
  951. /* Copy out the peer data if bonds are required */
  952. if (nrf_dfu_settings_peer_data_is_valid())
  953. {
  954. NRF_LOG_DEBUG("Copying peer data");
  955. err_code = nrf_dfu_settings_peer_data_copy(&m_peer_data);
  956. UNUSED_RETURN_VALUE(err_code);
  957. }
  958. else
  959. {
  960. APP_ERROR_HANDLER(NRF_ERROR_INTERNAL);
  961. }
  962. #else
  963. /* Copy out the new advertisement name when bonds are not required and the name is set. */
  964. if (nrf_dfu_settings_adv_name_is_valid())
  965. {
  966. err_code = nrf_dfu_settings_adv_name_copy(&m_adv_name);
  967. UNUSED_RETURN_VALUE(err_code);
  968. /* Set flags for advertisement name that is to be used */
  969. m_flags |= DFU_BLE_FLAG_USE_ADV_NAME;
  970. }
  971. else
  972. {
  973. NRF_LOG_DEBUG("No advertising name found");
  974. }
  975. #endif
  976. err_code = gap_params_init();
  977. VERIFY_SUCCESS(err_code);
  978. /* Initialize the Device Firmware Update Service. */
  979. err_code = ble_dfu_init(&m_dfu);
  980. VERIFY_SUCCESS(err_code);
  981. err_code = advertising_start();
  982. VERIFY_SUCCESS(err_code);
  983. m_flags |= DFU_BLE_FLAG_INITIALIZED;
  984. NRF_LOG_DEBUG("BLE DFU transport initialized.");
  985. return NRF_SUCCESS;
  986. }
  987. uint32_t ble_dfu_transport_close(nrf_dfu_transport_t const * p_exception)
  988. {
  989. uint32_t err_code = NRF_SUCCESS;
  990. if ((m_flags & DFU_BLE_FLAG_INITIALIZED) && (p_exception != &ble_dfu_transport))
  991. {
  992. NRF_LOG_DEBUG("Shutting down BLE transport.");
  993. if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
  994. {
  995. NRF_LOG_DEBUG("Disconnecting.");
  996. /* Set flag to prevent advertisement from starting */
  997. m_flags |= DFU_BLE_RESETTING_SOON;
  998. /* Disconnect from the peer. */
  999. err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
  1000. VERIFY_SUCCESS(err_code);
  1001. /* Wait a bit for the disconnect event to be sent on air. */
  1002. nrf_delay_ms(200);
  1003. }
  1004. else
  1005. {
  1006. err_code = sd_ble_gap_adv_stop(m_adv_handle);
  1007. UNUSED_RETURN_VALUE(err_code);
  1008. }
  1009. err_code = nrf_sdh_disable_request();
  1010. if (err_code == NRF_SUCCESS)
  1011. {
  1012. NRF_LOG_DEBUG("BLE transport shut down.");
  1013. }
  1014. }
  1015. return err_code;
  1016. }
  1017. uint32_t ble_dfu_transport_disconnect(void)
  1018. {
  1019. uint32_t err_code = NRF_SUCCESS;
  1020. if (m_flags & DFU_BLE_FLAG_INITIALIZED)
  1021. {
  1022. NRF_LOG_DEBUG("Disconnect from BLE peer.");
  1023. if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
  1024. {
  1025. NRF_LOG_DEBUG("Disconnecting.");
  1026. /* Disconnect from the peer. */
  1027. err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
  1028. VERIFY_SUCCESS(err_code);
  1029. }
  1030. }
  1031. return err_code;
  1032. }