ruuvi.drivers.c ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
Loading...
Searching...
No Matches
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"
56#include "ruuvi_interface_log.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
109APP_TIMER_DEF (
110 m_conn_param_retry_timer); //<! Timer for retrying comm param renegotiation.
111
112NRF_BLE_GATT_DEF (m_gatt);
113NRF_BLE_QWR_DEF (m_qwr);
114BLE_NUS_DEF (m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT);
115static uint16_t m_conn_handle =
116 BLE_CONN_HANDLE_INVALID;
117static bool m_gatt_is_init = false;
119static ri_comm_channel_t * channel = NULL;
120
121static ble_gap_conn_params_t m_gatt_params;
122
123static uint8_t m_gatt_retries;
124
126static 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
133static 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
167static 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
189static void conn_params_error_handler (uint32_t nrf_error)
190{
192 RD_SUCCESS);
193}
194
206static 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
221static 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
247static 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
290static 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
415static 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
432static 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).
443static 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
477static 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
578static 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 {
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
616static 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
634 m_phys.rx_phys = BLE_GAP_PHY_2MBPS;
635 m_phys.tx_phys = BLE_GAP_PHY_2MBPS;
636 break;
637
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
654static 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 {
698 }
699
700 if (!ri_radio_is_init())
701 {
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");
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
799static 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
829static rd_status_t ri_gatt_nus_read (ri_comm_message_t * const message)
830{
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
853bool 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
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
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.
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_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.
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
#define NRF_SDH_BLE_TOTAL_LINK_COUNT
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.