ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_nrf5_sdk15_communication_ble_gatt.c
Go to the documentation of this file.
1 
49 #if RUUVI_NRF5_SDK15_GATT_ENABLED
50 #include "ruuvi_driver_error.h"
51 #include "ruuvi_nrf5_sdk15_error.h"
55 #include "ruuvi_interface_flash.h"
56 #include "ruuvi_interface_log.h"
57 #include "ruuvi_interface_timer.h"
58 #include "ruuvi_interface_power.h"
59 #include "ruuvi_interface_yield.h"
60 
61 #include "app_timer.h"
62 #include "ble_advdata.h"
63 #include "ble_types.h"
64 #include "ble_conn_params.h"
65 #include "ble_dfu.h"
66 #include "ble_dis.h"
67 #include "ble_nus.h"
68 #include "fds.h"
69 #include "sdk_errors.h"
70 #include "nrf_error.h"
71 #include "nrf_sdh.h"
72 #include "nrf_sdh_soc.h"
73 #include "nrf_sdh_ble.h"
74 #include "nrf_ble_qwr.h"
75 #include "nrf_ble_gatt.h"
76 #include "peer_manager.h"
77 
78 #include <stdio.h>
79 #include <string.h>
80 
81 #define CENTRAL_LINK_COUNT 0
82 #define PERIPHERAL_LINK_COUNT 1
84 #define APP_BLE_OBSERVER_PRIO 3
86 #define NEXT_CONN_PARAMS_UPDATE_DELAY_MS (30000)
87 #define FIRST_CONN_PARAMS_UPDATE_DELAY_TICKS APP_TIMER_TICKS(5000)
88 #define NEXT_CONN_PARAMS_UPDATE_DELAY_TICKS APP_TIMER_TICKS(NEXT_CONN_PARAMS_UPDATE_DELAY_MS)
90 #define MAX_CONN_PARAMS_UPDATE_COUNT 3
92 #define SEC_PARAM_BOND 0
93 #define SEC_PARAM_MITM 0
94 #define SEC_PARAM_LESC 0
95 #define SEC_PARAM_KEYPRESS 0
96 #define SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE
97 #define SEC_PARAM_OOB 0
98 #define SEC_PARAM_MIN_KEY_SIZE 7
99 #define SEC_PARAM_MAX_KEY_SIZE 16
101 #ifndef RUUVI_NRF5_SDK15_COMMUNICATION_BLE4_GATT_LOG_LEVEL
102 #define RUUVI_NRF5_SDK15_COMMUNICATION_BLE4_GATT_LOG_LEVEL RI_LOG_LEVEL_DEBUG
103 #endif
104 #define LOG(msg) ri_log(RUUVI_NRF5_SDK15_COMMUNICATION_BLE4_GATT_LOG_LEVEL, msg)
105 #define LOGD(msg) ri_log(RI_LOG_LEVEL_DEBUG, msg)
106 #define LOGW(msg) ri_log(RI_LOG_LEVEL_WARNING, msg)
107 #define LOGHEX(msg, len) ri_log_hex(RUUVI_NRF5_SDK15_COMMUNICATION_BLE4_GATT_LOG_LEVEL, msg, len)
108 
109 APP_TIMER_DEF (
110  m_conn_param_retry_timer); //<! Timer for retrying comm param renegotiation.
111 
112 NRF_BLE_GATT_DEF (m_gatt);
113 NRF_BLE_QWR_DEF (m_qwr);
114 BLE_NUS_DEF (m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT);
115 static uint16_t m_conn_handle =
116  BLE_CONN_HANDLE_INVALID;
117 static bool m_gatt_is_init = false;
119 static ri_comm_channel_t * channel = NULL;
120 
121 static ble_gap_conn_params_t m_gatt_params;
122 
123 static uint8_t m_gatt_retries;
124 
126 static ble_gap_phys_t m_phys =
127 {
128  .rx_phys = BLE_GAP_PHY_1MBPS, //BLE_GAP_PHY_2MBPS, BLE_GAP_PHY_CODED
129  .tx_phys = BLE_GAP_PHY_1MBPS
130 };
131 
133 static char const * phy_str (ble_gap_phys_t phys)
134 {
135  static char const * str[] =
136  {
137  "1 Mbps",
138  "2 Mbps",
139  "Coded",
140  "Unknown"
141  };
142 
143  switch (phys.tx_phys)
144  {
145  case BLE_GAP_PHY_1MBPS:
146  return str[0];
147 
148  case BLE_GAP_PHY_2MBPS:
149  case BLE_GAP_PHY_2MBPS | BLE_GAP_PHY_1MBPS:
150  case BLE_GAP_PHY_2MBPS | BLE_GAP_PHY_1MBPS | BLE_GAP_PHY_CODED:
151  return str[1];
152 
153  case BLE_GAP_PHY_CODED:
154  return str[2];
155 
156  default:
157  return str[3];
158  }
159 }
160 
161 
167 static ret_code_t gap_params_init (void)
168 {
169  ret_code_t err_code;
170  ble_gap_conn_params_t gap_conn_params;
171  ble_gap_conn_sec_mode_t sec_mode;
172  BLE_GAP_CONN_SEC_MODE_SET_OPEN (&sec_mode);
173  memset (&gap_conn_params, 0, sizeof (gap_conn_params));
174  gap_conn_params.min_conn_interval = MSEC_TO_UNITS (RI_GATT_MIN_INTERVAL_STANDARD_MS,
175  UNIT_1_25_MS);
176  gap_conn_params.max_conn_interval = MSEC_TO_UNITS (RI_GATT_MAX_INTERVAL_STANDARD_MS,
177  UNIT_1_25_MS);
178  gap_conn_params.slave_latency = RI_GATT_SLAVE_LATENCY_STANDARD;
179  gap_conn_params.conn_sup_timeout = MSEC_TO_UNITS (RI_GATT_CONN_SUP_TIMEOUT_MS,
180  UNIT_10_MS);
181  err_code = sd_ble_gap_ppcp_set (&gap_conn_params);
182  return err_code;
183 }
184 
189 static void conn_params_error_handler (uint32_t nrf_error)
190 {
192  RD_SUCCESS);
193 }
194 
206 static void on_conn_params_evt (ble_conn_params_evt_t * p_evt)
207 {
208  uint32_t err_code;
209 
210  if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
211  {
212  err_code = sd_ble_gap_disconnect (m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
214  RD_SUCCESS);
215  }
216 }
217 
218 
221 static ret_code_t conn_params_init (void)
222 {
223  uint32_t err_code;
224  ble_conn_params_init_t cp_init;
225  memset (&cp_init, 0, sizeof (cp_init));
226  cp_init.p_conn_params = NULL;
227  cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY_TICKS;
228  cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY_TICKS;
229  cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT;
230  cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID;
231  cp_init.disconnect_on_fail = false;
232  cp_init.evt_handler = on_conn_params_evt;
233  cp_init.error_handler = conn_params_error_handler;
234  err_code = ble_conn_params_init (&cp_init);
235  return err_code;
236 }
237 
238 
247 static void nus_data_handler (ble_nus_evt_t * p_evt)
248 {
249  if (NULL == channel || NULL == channel->on_evt)
250  {
251  return;
252  }
253 
254  switch (p_evt->type)
255  {
256  case BLE_NUS_EVT_RX_DATA:
257  LOGD ("NUS RX \r\n");
258  channel->on_evt (RI_COMM_RECEIVED,
259  (void *) p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
260  break;
261 
262  case BLE_NUS_EVT_COMM_STARTED:
263  LOG ("NUS Started\r\n");
264  channel->on_evt (RI_COMM_CONNECTED, NULL, 0);
265  break;
266 
267  case BLE_NUS_EVT_COMM_STOPPED:
268  LOG ("NUS Finished\r\n");
269  channel->on_evt (RI_COMM_DISCONNECTED, NULL, 0);
270  break;
271 
272  case BLE_NUS_EVT_TX_RDY:
273  LOGD ("NUS TX Done\r\n");
274  channel->on_evt (RI_COMM_SENT, NULL, 0);
275  break;
276 
277  default:
278  break;
279  }
280 }
281 
290 static void ble_evt_handler (ble_evt_t const * p_ble_evt, void * p_context)
291 {
292  uint32_t err_code = NRF_SUCCESS;
293 
294  switch (p_ble_evt->header.evt_id)
295  {
296  case BLE_GAP_EVT_CONNECTED:
297  m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
298  err_code = nrf_ble_qwr_conn_handle_assign (&m_qwr, m_conn_handle);
299  LOG ("BLE Connected \r\n");
300  char msg[128];
301  sprintf (msg, "PHY: %s.\r\n", phy_str (m_phys));
303  RD_SUCCESS);
304 # if 0
305  // Request preferred PHY on connection -
306  // Crashes connection on older iOS devices and Macs.
307  err_code = sd_ble_gap_phy_update (p_ble_evt->evt.gap_evt.conn_handle, &m_phys);
308  char msg[128];
309  snprintf (msg, sizeof (msg), "Request PHY update to %s.\r\n", phy_str (m_phys));
310  LOG (msg);
311 # endif
312  break;
313 
314  case BLE_GAP_EVT_TIMEOUT:
315  LOG ("BLE GAP timeout \r\n");
316  break;
317 
318  case BLE_GAP_EVT_DISCONNECTED:
319  LOG ("BLE Disconnected \r\n");
320  // ble_nus.c does not call NUS callback on disconnect, call it here.
321  ble_nus_evt_t evt = { 0 };
322  evt.type = BLE_NUS_EVT_COMM_STOPPED;
323  nus_data_handler (&evt);
324  m_conn_handle = BLE_CONN_HANDLE_INVALID;
325  err_code |= app_timer_stop (m_conn_param_retry_timer);
327  RD_SUCCESS);
328  break;
329 
330  case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
331  err_code = sd_ble_gap_phy_update (p_ble_evt->evt.gap_evt.conn_handle, &m_phys);
332  LOG ("BLE PHY update requested \r\n");
334  RD_SUCCESS);
335  break;
336 
337  case BLE_GAP_EVT_PHY_UPDATE:
338  {
339  ble_gap_evt_phy_update_t const * p_phy_evt = &p_ble_evt->evt.gap_evt.params.phy_update;
340 
341  if (p_phy_evt->status == BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION)
342  {
343  LOGW ("BLE LL transaction collision during PHY update.\r\n");
344  break;
345  }
346 
347  ble_gap_phys_t evt_phys = {0};
348  evt_phys.tx_phys = p_phy_evt->tx_phy;
349  evt_phys.rx_phys = p_phy_evt->rx_phy;
350  char msg[128];
351  snprintf (msg, sizeof (msg), "PHY update %s. PHY set to %s.\r\n",
352  (p_phy_evt->status == BLE_HCI_STATUS_CODE_SUCCESS) ?
353  "accepted" : "rejected",
354  phy_str (evt_phys));
355  LOG (msg);
356  }
357  break;
358 
359  case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
360  // Pairing not supported
361  LOG ("BLE security parameters requested - denying \r\n");
362  err_code = sd_ble_gap_sec_params_reply (m_conn_handle,
363  BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP,
364  NULL, NULL);
366  ~RD_SUCCESS);
367 
368  if (NRF_ERROR_INVALID_STATE == err_code)
369  {
370  err_code = sd_ble_gap_disconnect (p_ble_evt->evt.gattc_evt.conn_handle,
371  BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
372  LOG ("BLE GATT Disconnected\r\n");
373  }
374 
375  break;
376 
377  case BLE_GATTS_EVT_SYS_ATTR_MISSING:
378  // No system attributes have been stored.
379  LOG ("BLE System attributes missing\r\n");
380  err_code = sd_ble_gatts_sys_attr_set (m_conn_handle, NULL, 0, 0);
382  RD_SUCCESS);
383  break;
384 
385  case BLE_GATTC_EVT_TIMEOUT:
386  // Disconnect on GATT Client timeout event.
387  LOG ("BLE GATT Client timeout\r\n");
388  err_code = sd_ble_gap_disconnect (p_ble_evt->evt.gattc_evt.conn_handle,
389  BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
391  RD_SUCCESS);
392  break;
393 
394  case BLE_GATTS_EVT_TIMEOUT:
395  // Disconnect on GATT Server timeout event.
396  LOG ("BLE GATT Server timeout\r\n");
397  err_code = sd_ble_gap_disconnect (p_ble_evt->evt.gatts_evt.conn_handle,
398  BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
400  RD_SUCCESS);
401  break;
402 
403  case BLE_GATTS_EVT_HVN_TX_COMPLETE:
404  LOGD ("BLE Notification sent\r\n");
405  break;
406 
407  default:
408  // No implementation needed.
409  LOGD ("BLE Unknown event\r\n");
410  break;
411  }
412 }
413 
415 static void gatt_evt_handler (nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
416 {
417  if ( (m_conn_handle == p_evt->conn_handle)
418  && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
419  {
420  //m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
421  LOGD ("Changing MTU size is not supported\r\n");
422  }
423 }
424 
432 static void nrf_qwr_error_handler (uint32_t nrf_error)
433 {
435  RD_SUCCESS);
436 }
437 
438 // YOUR_JOB: Update this code if you want to do anything given a DFU event (optional).
443 static void ble_dfu_evt_handler (ble_dfu_buttonless_evt_type_t event)
444 {
445  switch (event)
446  {
447  case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
448  // YOUR_JOB: Disconnect all bonded devices that currently are connected.
449  // This is required to receive a service changed indication
450  // on bootup after a successful (or aborted) Device Firmware Update.
451  break;
452 
453  case BLE_DFU_EVT_BOOTLOADER_ENTER:
454  // YOUR_JOB: Write app-specific unwritten data to FLASH, control finalization of this
455  // by delaying reset by reporting false in app_shutdown_handler
456  break;
457 
458  case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED:
459  // YOUR_JOB: Take corrective measures to resolve the issue
460  // like calling APP_ERROR_CHECK to reset the device.
461  break;
462 
463  case BLE_DFU_EVT_RESPONSE_SEND_ERROR:
464  // YOUR_JOB: Take corrective measures to resolve the issue
465  // like calling APP_ERROR_CHECK to reset the device.
466  break;
467 
468  default:
469  break;
470  }
471 }
472 
477 static void pm_evt_handler (pm_evt_t const * p_evt)
478 {
479  ret_code_t err_code;
480 
481  switch (p_evt->evt_id)
482  {
483  case PM_EVT_BONDED_PEER_CONNECTED:
484  {
485  } break;
486 
487  case PM_EVT_CONN_SEC_SUCCEEDED:
488  {
489  } break;
490 
491  case PM_EVT_CONN_SEC_FAILED:
492  {
493  /* Often, when securing fails, it shouldn't be restarted, for security reasons.
494  * Other times, it can be restarted directly.
495  * Sometimes it can be restarted, but only after changing some Security Parameters.
496  * Sometimes, it cannot be restarted until the link is disconnected and reconnected.
497  * Sometimes it is impossible, to secure the link, or the peer device does not support it.
498  * How to handle this error is highly application dependent. */
499  } break;
500 
501  case PM_EVT_CONN_SEC_CONFIG_REQ:
502  {
503  // Reject pairing request from an already bonded peer.
504  pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false};
505  pm_conn_sec_config_reply (p_evt->conn_handle, &conn_sec_config);
506  }
507  break;
508 
509  case PM_EVT_STORAGE_FULL:
510  {
511  // Run garbage collection on the flash.
512  err_code = fds_gc();
513 
514  if (err_code == FDS_ERR_NO_SPACE_IN_QUEUES)
515  {
516  // Retry.
517  }
518  else
519  {
520  APP_ERROR_CHECK (err_code);
521  }
522  }
523  break;
524 
525  case PM_EVT_PEERS_DELETE_SUCCEEDED:
526  {
527  } break;
528 
529  case PM_EVT_PEER_DATA_UPDATE_FAILED:
530  {
531  // Assert.
533  p_evt->params.peer_data_update_failed.error), RD_SUCCESS);
534  }
535  break;
536 
537  case PM_EVT_PEER_DELETE_FAILED:
538  {
539  // Assert.
541  p_evt->params.peer_delete_failed.error), RD_SUCCESS);
542  }
543  break;
544 
545  case PM_EVT_PEERS_DELETE_FAILED:
546  {
547  // Assert.
549  p_evt->params.peers_delete_failed_evt.error), RD_SUCCESS);
550  }
551  break;
552 
553  case PM_EVT_ERROR_UNEXPECTED:
554  {
555  // Assert.
557  p_evt->params.error_unexpected.error), RD_SUCCESS);
558  }
559  break;
560 
561  case PM_EVT_CONN_SEC_START:
562  case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
563  case PM_EVT_PEER_DELETE_SUCCEEDED:
564  case PM_EVT_LOCAL_DB_CACHE_APPLIED:
565  case PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED:
566  case PM_EVT_SERVICE_CHANGED_IND_SENT:
567  case PM_EVT_SERVICE_CHANGED_IND_CONFIRMED:
568  default:
569  break;
570  }
571 }
572 
573 
574 
578 static ret_code_t peer_manager_init()
579 {
580  ble_gap_sec_params_t sec_param;
581  ret_code_t err_code = NRF_SUCCESS;
582  err_code |= pm_init();
583 
584  // Failed because storage cannot be initialized.
585  if (NRF_SUCCESS != err_code)
586  {
587  ri_flash_purge();
588  ri_power_reset();
589  }
590 
591  memset (&sec_param, 0, sizeof (ble_gap_sec_params_t));
592  // Security parameters to be used for all security procedures.
593  sec_param.bond = SEC_PARAM_BOND;
594  sec_param.mitm = SEC_PARAM_MITM;
595  sec_param.lesc = SEC_PARAM_LESC;
596  sec_param.keypress = SEC_PARAM_KEYPRESS;
597  sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES;
598  sec_param.oob = SEC_PARAM_OOB;
599  sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE;
600  sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE;
601  sec_param.kdist_own.enc = 0;
602  sec_param.kdist_own.id = 0;
603  sec_param.kdist_peer.enc = 0;
604  sec_param.kdist_peer.id = 0;
605  err_code = pm_sec_params_set (&sec_param);
606  err_code |= pm_register (pm_evt_handler);
607  return err_code;
608 }
609 
616 static rd_status_t setup_phys (void)
617 {
618  rd_status_t err_code = RD_SUCCESS;
619  ri_radio_modulation_t modulation;
620  err_code |= ri_radio_get_modulation (&modulation);
621 
622  if (RD_SUCCESS == err_code)
623  {
624  if (ri_radio_supports (modulation))
625  {
626  switch (modulation)
627  {
629  m_phys.rx_phys = BLE_GAP_PHY_CODED;
630  m_phys.tx_phys = BLE_GAP_PHY_CODED;
631  break;
632 
633  case RI_RADIO_BLE_2MBPS:
634  m_phys.rx_phys = BLE_GAP_PHY_2MBPS;
635  m_phys.tx_phys = BLE_GAP_PHY_2MBPS;
636  break;
637 
638  case RI_RADIO_BLE_1MBPS:
639  default:
640  m_phys.rx_phys = BLE_GAP_PHY_1MBPS;
641  m_phys.tx_phys = BLE_GAP_PHY_1MBPS;
642  break;
643  }
644  }
645  else
646  {
647  err_code |= RD_ERROR_NOT_SUPPORTED;
648  }
649  }
650 
651  return err_code;
652 }
653 
654 static void gatt_params_request (void * const params)
655 {
656  ret_code_t nrf_status = NRF_SUCCESS;
657 
658  if (BLE_CONN_HANDLE_INVALID == m_conn_handle)
659  {
660  m_gatt_retries = 0;
661  LOG ("No connection, ignore param change\r\n");
662  }
663  else
664  {
665  nrf_status = ble_conn_params_change_conn_params (m_conn_handle, params);
666  LOG ("Requesting param change\r\n");
667  }
668 
669  if (NRF_SUCCESS != nrf_status)
670  {
671  nrf_status = app_timer_start (m_conn_param_retry_timer,
672  NEXT_CONN_PARAMS_UPDATE_DELAY_TICKS,
673  params);
675  RD_SUCCESS);
676  m_gatt_retries++;
677  LOG ("Param change failed, retry queued\r\n");
678  }
679 
680  if (m_gatt_retries > MAX_CONN_PARAMS_UPDATE_COUNT)
681  {
682  // Something is preventing update, disconnect.
683  nrf_status = sd_ble_gap_disconnect (m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
685  RD_SUCCESS);
686  LOG ("Param change errored too many times, cut connection\r\n");
687  }
688 }
689 
691 {
692  ret_code_t err_code = NRF_SUCCESS;
693  static bool qwr_is_init = false;
694 
695  if (m_gatt_is_init)
696  {
697  return RD_ERROR_INVALID_STATE;
698  }
699 
700  if (!ri_radio_is_init())
701  {
702  return RD_ERROR_INVALID_STATE;
703  }
704 
705  // Connection param module requires timers
706  if (!ri_timer_is_init())
707  {
708  LOGW ("NRF5 SDK15 BLE4 GATT module requires initialized timers\r\n");
709  return RD_ERROR_INVALID_STATE;
710  }
711  else
712  {
713  // Running timer cannot be recreated.
714  // Stopped timer can be created again, so stop, ignore error, (re)create
715  (void) app_timer_stop (m_conn_param_retry_timer);
716  err_code |= app_timer_create (&m_conn_param_retry_timer, APP_TIMER_MODE_SINGLE_SHOT,
717  &gatt_params_request);
719  }
720 
721  // Register a handler for BLE events.
722  NRF_SDH_BLE_OBSERVER (m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
723  err_code |= gap_params_init();
724  err_code |= nrf_ble_gatt_init (&m_gatt, gatt_evt_handler);
725  err_code |= nrf_ble_gatt_att_mtu_periph_set (&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
727  // Queued Write Module, peer manager cannot be uninitialized, initialize only once.
728 
729  if (!qwr_is_init)
730  {
731  nrf_ble_qwr_init_t qwr_init = {0};
732  qwr_init.error_handler = nrf_qwr_error_handler;
733  err_code |= nrf_ble_qwr_init (&m_qwr, &qwr_init);
734  err_code |= peer_manager_init();
736  qwr_is_init = true;
737  }
738 
739  err_code |= conn_params_init();
741  err_code |= setup_phys();
743 
744  if ( (NRF_SUCCESS == err_code))
745  {
746  m_gatt_is_init = true;
747  }
748 
750  return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
751 }
752 
754 {
755  rd_status_t err_code = RD_SUCCESS;
756 
757  // Radio must be completely disabled to uninit GATT.
758  if (ri_radio_is_init())
759  {
760  err_code |= RD_ERROR_INVALID_STATE;
761  }
762  // GATT is uninit when radio is uninit.
763  else
764  {
765  m_gatt_is_init = false;
766  }
767 
768  return err_code;
769 }
770 
772 {
773  rd_status_t err_code = RD_SUCCESS;
774 
775  if (NULL == _channel)
776  {
777  err_code |= RD_ERROR_NULL;
778  }
779  else
780  {
781  memset (_channel, 0, sizeof (ri_comm_channel_t));
782 
783  // disconnect
784  if (BLE_CONN_HANDLE_INVALID != m_conn_handle)
785  {
786  err_code |= sd_ble_gap_disconnect (m_conn_handle,
787  BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
788  m_conn_handle = BLE_CONN_HANDLE_INVALID;
789  }
790  }
791 
792  // Services cannot be uninitialized, GATT must be re-initialized.
793  return err_code;
794 }
795 
799 static rd_status_t ri_gatt_nus_send (ri_comm_message_t * const message)
800 {
801  rd_status_t err_code = RD_SUCCESS;
802  ret_code_t nrf_code = NRF_SUCCESS;
803 
804  if (NULL == message)
805  {
806  err_code |= RD_ERROR_NULL;
807  }
808  else if (BLE_NUS_MAX_DATA_LEN < message->data_length)
809  {
810  err_code |= RD_ERROR_DATA_SIZE;
811  }
812  else if (BLE_CONN_HANDLE_INVALID == m_conn_handle)
813  {
814  err_code |= RD_ERROR_INVALID_STATE;
815  }
816  else if (message->repeat_count > 1)
817  {
818  err_code |= RD_ERROR_NOT_IMPLEMENTED;
819  }
820  else
821  {
822  uint16_t data_len = message->data_length;
823  nrf_code |= ble_nus_data_send (&m_nus, message->data, &data_len, m_conn_handle);
824  }
825 
826  return err_code | ruuvi_nrf5_sdk15_to_ruuvi_error (nrf_code);
827 }
828 
829 static rd_status_t ri_gatt_nus_read (ri_comm_message_t * const message)
830 {
831  return RD_ERROR_NOT_SUPPORTED;
832 }
833 
835 {
836  if (NULL == _channel) { return RD_ERROR_NULL; }
837 
838  uint32_t err_code;
839  ble_nus_init_t nus_init;
840  // Initialize NUS.
841  memset (&nus_init, 0, sizeof (nus_init));
842  nus_init.data_handler = nus_data_handler;
843  err_code = ble_nus_init (&m_nus, &nus_init);
844  channel = _channel;
845  channel->init = ri_gatt_nus_init;
846  channel->uninit = ri_gatt_nus_uninit;
847  channel->send = ri_gatt_nus_send;
848  channel->read = ri_gatt_nus_read;
849  m_gatt_is_init = true;
850  return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
851 }
852 
853 bool ble_nus_is_connected (void)
854 {
855  ret_code_t err_code = NRF_SUCCESS;
856  ble_nus_client_context_t * p_client;
857  err_code = blcm_link_ctx_get (m_nus.p_link_ctx_storage, m_conn_handle,
858  (void *) &p_client);
859 
860  if (NRF_SUCCESS != err_code)
861  {
862  return false;
863  }
864 
865  if ( (m_conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL))
866  {
867  return false;
868  }
869 
870  if (!p_client->is_notification_enabled)
871  {
872  return false;
873  }
874 
875  return true;
876 }
877 
879 {
880  ret_code_t err_code = NRF_SUCCESS;
881  ble_dfu_buttonless_init_t dfus_init = {0};
882  // Initialize the async SVCI interface to bootloader.
883  err_code = ble_dfu_buttonless_async_svci_init();
884 
885  if (NRF_SUCCESS != err_code) {}
886 
887  dfus_init.evt_handler = ble_dfu_evt_handler;
888  err_code = ble_dfu_buttonless_init (&dfus_init);
889 
890  if (NRF_SUCCESS != err_code) {}
891 
892  return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
893 }
894 
900 rd_status_t ri_gatt_dis_init (const ri_comm_dis_init_t * const p_dis)
901 {
902  if (NULL == p_dis) { return RD_ERROR_NULL; }
903 
904  ret_code_t err_code = NRF_SUCCESS;
905  ble_dis_init_t dis_init;
906  ri_comm_dis_init_t dis_local;
907  memset (&dis_init, 0, sizeof (dis_init));
908  memcpy (&dis_local, p_dis, sizeof (dis_local));
909  ble_srv_ascii_to_utf8 (&dis_init.manufact_name_str, dis_local.manufacturer);
910  ble_srv_ascii_to_utf8 (&dis_init.model_num_str, dis_local.model);
911  ble_srv_ascii_to_utf8 (&dis_init.serial_num_str, dis_local.deviceid);
912  ble_srv_ascii_to_utf8 (&dis_init.hw_rev_str, dis_local.hw_version);
913  ble_srv_ascii_to_utf8 (&dis_init.fw_rev_str, dis_local.fw_version);
914  // Read security level 1, mode 1. OPEN, i.e. anyone can read without encryption.
915  // Write not allowed.
916  dis_init.dis_char_rd_sec = SEC_OPEN;
917  err_code = ble_dis_init (&dis_init);
918  return ruuvi_nrf5_sdk15_to_ruuvi_error (err_code);
919 }
920 
922  const uint16_t delay_ms)
923 {
924  rd_status_t err_code = RD_SUCCESS;
925  ret_code_t nrf_status = NRF_SUCCESS;
926  ble_gap_conn_params_t gap_conn_params = {0};
927  gap_conn_params.conn_sup_timeout = MSEC_TO_UNITS (RI_GATT_CONN_SUP_TIMEOUT_MS,
928  UNIT_10_MS);
929 
930  switch (params)
931  {
932  case RI_GATT_TURBO:
933  LOG ("RI_GATT_TURBO\r\n");
934  gap_conn_params.slave_latency = RI_GATT_SLAVE_LATENCY_TURBO;
935  gap_conn_params.min_conn_interval = MSEC_TO_UNITS (RI_GATT_MIN_INTERVAL_TURBO_MS,
936  UNIT_1_25_MS);
937  gap_conn_params.max_conn_interval = MSEC_TO_UNITS (RI_GATT_MAX_INTERVAL_TURBO_MS,
938  UNIT_1_25_MS);
939  break;
940 
941  case RI_GATT_LOW_POWER:
942  LOG ("RI_GATT_LOW_POWER\r\n");
943  gap_conn_params.slave_latency = RI_GATT_SLAVE_LATENCY_LOW_POWER;
944  gap_conn_params.min_conn_interval = MSEC_TO_UNITS (RI_GATT_MIN_INTERVAL_LOW_POWER_MS,
945  UNIT_1_25_MS);
946  gap_conn_params.max_conn_interval = MSEC_TO_UNITS (RI_GATT_MAX_INTERVAL_LOW_POWER_MS,
947  UNIT_1_25_MS);
948  break;
949 
950  case RI_GATT_STANDARD:
951  default:
952  LOG ("RI_GATT_STANDARD\r\n");
953  gap_conn_params.slave_latency = RI_GATT_SLAVE_LATENCY_STANDARD;
954  gap_conn_params.min_conn_interval = MSEC_TO_UNITS (RI_GATT_MIN_INTERVAL_STANDARD_MS,
955  UNIT_1_25_MS);
956  gap_conn_params.max_conn_interval = MSEC_TO_UNITS (RI_GATT_MAX_INTERVAL_STANDARD_MS,
957  UNIT_1_25_MS);
958  break;
959  }
960 
961  err_code |= ruuvi_nrf5_sdk15_to_ruuvi_error (app_timer_stop (m_conn_param_retry_timer));
962  memcpy (&m_gatt_params, &gap_conn_params, sizeof (gap_conn_params));
963 
964  if (0 == delay_ms)
965  {
966  nrf_status = ble_conn_params_change_conn_params (m_conn_handle, &gap_conn_params);
967 
968  if (NRF_SUCCESS != nrf_status)
969  {
970  err_code |= ruuvi_nrf5_sdk15_to_ruuvi_error (app_timer_start (m_conn_param_retry_timer,
971  NEXT_CONN_PARAMS_UPDATE_DELAY_TICKS, &m_gatt_params));
972  m_gatt_retries = 1;
973  RD_ERROR_CHECK (err_code, ~RD_ERROR_FATAL);
974  LOG ("Retrying new params soon\r\n");
975  }
976  else
977  {
978  LOG ("Switched to new params\r\n");
979  }
980  }
981  else
982  {
983  err_code |= ruuvi_nrf5_sdk15_to_ruuvi_error (app_timer_start (m_conn_param_retry_timer,
984  APP_TIMER_TICKS (delay_ms), &m_gatt_params));
985  m_gatt_retries = 0;
986  RD_ERROR_CHECK (err_code, ~RD_ERROR_FATAL);
987  LOG ("New params set after delay\r\n");
988  }
989 
990  return err_code;
991 }
992 
993 #endif
#define RD_ERROR_NULL
Null Pointer.
#define RD_ERROR_FATAL
Program should always reset after this.
uint32_t rd_status_t
bitfield for representing errors
rd_status_t ruuvi_nrf5_sdk15_to_ruuvi_error(const ret_code_t error)
convert nrf5 sdk15 error code into Ruuvi error code.
#define RD_ERROR_CHECK(error, mask)
Shorthand macro for calling the rd_error_check with current file & line.
#define RD_ERROR_NOT_IMPLEMENTED
Not implemented yet.
#define RD_ERROR_NOT_SUPPORTED
Not supported.
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_DATA_SIZE
Invalid Data size.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
void ri_flash_purge(void)
Purge flash.
rd_status_t ri_radio_get_modulation(ri_radio_modulation_t *const p_modulation)
Get the modulation used by application.
bool ri_radio_is_init()
Check if radio is initialized.
bool ri_radio_supports(ri_radio_modulation_t modulation)
Check if radio supports given modulation.
ri_radio_modulation_t
type of radio modulation to be used.
@ RI_RADIO_BLE_1MBPS
"Normal" BLE 4 modulation
@ RI_RADIO_BLE_2MBPS
"Fast BLE". Advertising uses 1MBPS primary advertisement followed by 2 MBit/s extended advertisement.
@ RI_RADIO_BLE_125KBPS
Also known as BLE Long Range S=8.
ret_code_t fds_gc(void)
Function for running garbage collection.
@ FDS_ERR_NO_SPACE_IN_QUEUES
Error. There is no space in the internal queues.
Definition: fds.h:98
bool ri_timer_is_init(void)
Check if timer is initialized.
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
@ RI_COMM_CONNECTED
Connection established, OK to send, may receive data.
@ RI_COMM_RECEIVED
New data received, available to read with read function.
@ RI_COMM_SENT
One queued message was sent with all repetitions.
@ RI_COMM_DISCONNECTED
Connection lost, cannot send, may not receive data.
rd_status_t ri_gatt_init(void)
Initializes GATT stack. Uses default values from sdk_config.h, these can be overridden in nrf5_sdk15_...
#define RI_GATT_MIN_INTERVAL_TURBO_MS
#define RI_GATT_SLAVE_LATENCY_STANDARD
#define RI_GATT_SLAVE_LATENCY_TURBO
#define RI_GATT_MAX_INTERVAL_LOW_POWER_MS
rd_status_t ri_gatt_nus_uninit(ri_comm_channel_t *const _channel)
Uninitialize Nordic UART Service as a communication channel.
rd_status_t ri_gatt_dfu_init(void)
Initialize BLE4 Device firmware update service.
#define RI_GATT_SLAVE_LATENCY_LOW_POWER
rd_status_t ri_gatt_uninit(void)
Uninitializes GATT stack.
#define RI_GATT_CONN_SUP_TIMEOUT_MS
rd_status_t ri_gatt_nus_init(ri_comm_channel_t *const channel)
Initialize Nordic UART Service as a communication channel. ri_communication_radio_init(RI_COMMUNICATI...
#define RI_GATT_MIN_INTERVAL_LOW_POWER_MS
#define RI_GATT_MIN_INTERVAL_STANDARD_MS
#define RI_GATT_MAX_INTERVAL_STANDARD_MS
#define RI_GATT_MAX_INTERVAL_TURBO_MS
rd_status_t ri_gatt_params_request(const ri_gatt_params_t params, const uint16_t delay_ms)
Request connection parameter update for current connection.
rd_status_t ri_gatt_dis_init(const ri_comm_dis_init_t *const dis)
Initialize BLE4 Device Information service.
Interface functions to persistent flash storage.
#define LOGD(fmt,...)
void ri_power_reset(void)
Reset IC.
Interface functions to timer.
#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE
Definition: sdk_config.h:11931
#define NRF_SDH_BLE_TOTAL_LINK_COUNT
Definition: sdk_config.h:11919
control API for communication via outside world
ri_comm_evt_handler_fp_t on_evt
Callback to application-level event handler, must be set in application.
ri_comm_xfer_fp_t send
Asynchronous send function.
ri_comm_init_fp_t init
Initialize and populate channel api control.
ri_comm_init_fp_t uninit
Uninitialize and depopulate channel api control.
ri_comm_xfer_fp_t read
Asynchronous read function.
char fw_version[RI_COMM_DIS_STRLEN]
Human readable firmware version.
char deviceid[RI_COMM_DIS_STRLEN]
Human readable device ID.
char manufacturer[RI_COMM_DIS_STRLEN]
Human readable manufacturer name.
char hw_version[RI_COMM_DIS_STRLEN]
Human readable hardware version.
char model[RI_COMM_DIS_STRLEN]
Human readable board model.
Application message structure used for communication.
uint8_t data[RI_COMM_MESSAGE_MAX_LENGTH]
Data payload.
uint8_t repeat_count
Number of times to repeat the message,.
uint8_t data_length
Length of data.