ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ble_dfu.c
Go to the documentation of this file.
1 
40 /* Attention!
41  * To maintain compliance with Nordic Semiconductor ASA's Bluetooth profile
42  * qualification listings, this section of source code must not be modified.
43  */
44 
45 #include "ble_dfu.h"
46 #include <string.h>
47 #include "ble_hci.h"
48 #include "sdk_macros.h"
49 #include "ble_srv_common.h"
50 #include "nrf_nvic.h"
51 #include "nrf_sdm.h"
52 #include "nrf_soc.h"
53 #include "nrf_log.h"
54 #include "nrf_dfu_ble_svci_bond_sharing.h"
55 #include "nrf_bootloader_info.h"
56 #include "nrf_svci_async_function.h"
57 #include "nrf_pwr_mgmt.h"
58 #include "peer_manager.h"
59 #include "gatts_cache_manager.h"
60 #include "peer_id.h"
61 #if NRF_MODULE_ENABLED(BLE_DFU)
62 
63 #define MAX_CTRL_POINT_RESP_PARAM_LEN 3
65 #define BLE_DFU_SERVICE_UUID 0xFE59
67 static ble_dfu_buttonless_t m_dfu;
69 NRF_SDH_BLE_OBSERVER(m_dfus_obs, BLE_DFU_BLE_OBSERVER_PRIO, ble_dfu_buttonless_on_ble_evt, &m_dfu);
70 
71 
74 static void dummy_evt_handler(ble_dfu_buttonless_evt_type_t evt)
75 {
76  NRF_LOG_DEBUG("Dummy event handler received event 0x%x", evt);
77 }
78 
79 
84 static void on_ctrlpt_write(ble_gatts_evt_write_t const * p_evt_write)
85 {
86  uint32_t err_code;
87 
88 
89  ble_gatts_rw_authorize_reply_params_t write_authorize_reply;
90  memset(&write_authorize_reply, 0, sizeof(write_authorize_reply));
91 
92  write_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
93 
94  if (m_dfu.is_ctrlpt_indication_enabled)
95  {
96  write_authorize_reply.params.write.update = 1;
97  write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
98  }
99  else
100  {
101  write_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR;
102  }
103 
104  // Authorize the write request
105  do {
106  err_code = sd_ble_gatts_rw_authorize_reply(m_dfu.conn_handle, &write_authorize_reply);
107  } while (err_code == NRF_ERROR_BUSY);
108 
109 
110  if (write_authorize_reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS)
111  {
112  return;
113  }
114 
115  // Forward the write event to the Buttonless DFU module.
116  ble_dfu_buttonless_on_ctrl_pt_write(p_evt_write);
117 }
118 
119 
126 static void on_rw_authorize_req(ble_evt_t const * p_ble_evt)
127 {
128  if (p_ble_evt->evt.gatts_evt.conn_handle != m_dfu.conn_handle)
129  {
130  return;
131  }
132 
133  const ble_gatts_evt_rw_authorize_request_t * p_auth_req =
134  &p_ble_evt->evt.gatts_evt.params.authorize_request;
135 
136  if (
137  (p_auth_req->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) &&
138  (p_auth_req->request.write.handle == m_dfu.control_point_char.value_handle) &&
139  (p_auth_req->request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ) &&
140  (p_auth_req->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) &&
141  (p_auth_req->request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)
142  )
143  {
144  on_ctrlpt_write(&p_auth_req->request.write);
145  }
146 }
147 
148 
153 static void on_connect(ble_evt_t const * p_ble_evt)
154 {
155  m_dfu.conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
156 }
157 
158 
163 static void on_disconnect(ble_evt_t const * p_ble_evt)
164 {
165  if (m_dfu.conn_handle != p_ble_evt->evt.gap_evt.conn_handle)
166  {
167  return;
168  }
169 
170  m_dfu.conn_handle = BLE_CONN_HANDLE_INVALID;
171 }
172 
173 
178 static void on_write(ble_evt_t const * p_ble_evt)
179 {
180  const ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
181 
182  if (p_evt_write->handle != m_dfu.control_point_char.cccd_handle)
183  {
184  return;
185  }
186 
187  if (p_evt_write->len == BLE_CCCD_VALUE_LEN)
188  {
189  // CCCD written, update indications state
190  m_dfu.is_ctrlpt_indication_enabled = ble_srv_is_indication_enabled(p_evt_write->data);
191 
192  NRF_LOG_INFO("Received indication state %d",
193  m_dfu.is_ctrlpt_indication_enabled);
194  }
195 }
196 
197 
204 static void on_hvc(ble_evt_t const * p_ble_evt)
205 {
206  uint32_t err_code;
207  ble_gatts_evt_hvc_t const * p_hvc = &p_ble_evt->evt.gatts_evt.params.hvc;
208 
209  if (p_hvc->handle == m_dfu.control_point_char.value_handle)
210  {
211  // Enter bootloader if we were waiting for reset after hvc indication confimation.
212  if (m_dfu.is_waiting_for_reset)
213  {
214  err_code = ble_dfu_buttonless_bootloader_start_prepare();
215  if (err_code != NRF_SUCCESS)
216  {
217  m_dfu.evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED);
218  }
219  }
220  }
221 }
222 
223 
224 void ble_dfu_buttonless_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
225 {
226  VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
227 
228  switch (p_ble_evt->header.evt_id)
229  {
230  case BLE_GAP_EVT_CONNECTED:
231  on_connect(p_ble_evt);
232  break;
233 
234  case BLE_GAP_EVT_DISCONNECTED:
235  on_disconnect(p_ble_evt);
236  break;
237 
238  case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
239  on_rw_authorize_req(p_ble_evt);
240  break;
241 
242  case BLE_GATTS_EVT_WRITE:
243  on_write(p_ble_evt);
244  break;
245 
246  case BLE_GATTS_EVT_HVC:
247  on_hvc(p_ble_evt);
248  break;
249 
250  default:
251  // no implementation
252  break;
253  }
254 }
255 
256 
257 uint32_t ble_dfu_buttonless_resp_send(ble_dfu_buttonless_op_code_t op_code, ble_dfu_buttonless_rsp_code_t rsp_code)
258 {
259  // Send notification
260  uint32_t err_code;
261  const uint16_t len = 3;
262  uint16_t hvx_len;
263  uint8_t hvx_data[MAX_CTRL_POINT_RESP_PARAM_LEN];
264  ble_gatts_hvx_params_t hvx_params;
265 
266  memset(&hvx_params, 0, sizeof(hvx_params));
267 
268  hvx_len = len;
269  hvx_data[0] = DFU_OP_RESPONSE_CODE;
270  hvx_data[1] = (uint8_t)op_code;
271  hvx_data[2] = (uint8_t)rsp_code;
272 
273  hvx_params.handle = m_dfu.control_point_char.value_handle;
274  hvx_params.type = BLE_GATT_HVX_INDICATION;
275  hvx_params.offset = 0;
276  hvx_params.p_len = &hvx_len;
277  hvx_params.p_data = hvx_data;
278 
279 
280  err_code = sd_ble_gatts_hvx(m_dfu.conn_handle, &hvx_params);
281  if ((err_code == NRF_SUCCESS) && (hvx_len != len))
282  {
283  err_code = NRF_ERROR_DATA_SIZE;
284  }
285 
286  return err_code;
287 }
288 
289 
290 uint32_t ble_dfu_buttonless_bootloader_start_finalize(void)
291 {
292  uint32_t err_code;
293 
294  NRF_LOG_DEBUG("In ble_dfu_buttonless_bootloader_start_finalize\r\n");
295 
296  err_code = sd_power_gpregret_clr(0, 0xffffffff);
297  VERIFY_SUCCESS(err_code);
298 
299  err_code = sd_power_gpregret_set(0, BOOTLOADER_DFU_START);
300  VERIFY_SUCCESS(err_code);
301 
302  // Indicate that the Secure DFU bootloader will be entered
303  m_dfu.evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER);
304 
305  // Signal that DFU mode is to be enter to the power management module
306  nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU);
307 
308  return NRF_SUCCESS;
309 }
310 
311 
312 uint32_t ble_dfu_buttonless_init(const ble_dfu_buttonless_init_t * p_dfu_init)
313 {
314  uint32_t err_code;
315  ble_uuid_t service_uuid;
316  ble_uuid128_t nordic_base_uuid = BLE_NORDIC_VENDOR_BASE_UUID;
317 
318  VERIFY_PARAM_NOT_NULL(p_dfu_init);
319 
320  // Initialize the service structure.
321  m_dfu.conn_handle = BLE_CONN_HANDLE_INVALID;
322  m_dfu.evt_handler = p_dfu_init->evt_handler;
323  m_dfu.is_waiting_for_reset = false;
324  m_dfu.is_ctrlpt_indication_enabled = false;
325 
326  if (m_dfu.evt_handler == NULL)
327  {
328  m_dfu.evt_handler = dummy_evt_handler;
329  }
330 
331  err_code = ble_dfu_buttonless_backend_init(&m_dfu);
332  VERIFY_SUCCESS(err_code);
333 
334  BLE_UUID_BLE_ASSIGN(service_uuid, BLE_DFU_SERVICE_UUID);
335 
336  // Add the DFU service declaration.
337  err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
338  &service_uuid,
339  &(m_dfu.service_handle));
340 
341  VERIFY_SUCCESS(err_code);
342 
343  // Add vendor specific base UUID to use with the Buttonless DFU characteristic.
344  err_code = sd_ble_uuid_vs_add(&nordic_base_uuid, &m_dfu.uuid_type);
345  VERIFY_SUCCESS(err_code);
346 
347  // Add the Buttonless DFU Characteristic (with bonds/without bonds).
348  err_code = ble_dfu_buttonless_char_add(&m_dfu);
349  VERIFY_SUCCESS(err_code);
350 
351  return NRF_SUCCESS;
352 }
353 #endif
#define BLE_DFU_BLE_OBSERVER_PRIO
Definition: sdk_config.h:12049