From 4d5a1bb8d1df855790defad88a43e5acf62c5a74 Mon Sep 17 00:00:00 2001 From: zhaohe Date: Sun, 21 Jan 2024 16:08:34 +0800 Subject: [PATCH] update --- .vscode/settings.json | 6 +- README.md | 15 ++ app/app.uvoptx | 134 +++++----- app/app.uvprojx | 18 +- app/main.c | 68 +++-- app/src/zble_module.c | 276 +++++++++++++++++++ app/src/zble_module.h | 20 ++ app/src/zble_service copy.c | 584 ----------------------------------------- app/src/zble_service.c | 284 -------------------- app/src/zble_service.h | 27 -- app/src/zdatachannel_service.c | 249 ++++++++++++++++++ app/src/zdatachannel_service.h | 95 +++++++ libznordic | 2 +- 13 files changed, 791 insertions(+), 987 deletions(-) create mode 100644 app/src/zble_module.c create mode 100644 app/src/zble_module.h delete mode 100644 app/src/zble_service copy.c delete mode 100644 app/src/zble_service.c delete mode 100644 app/src/zble_service.h create mode 100644 app/src/zdatachannel_service.c create mode 100644 app/src/zdatachannel_service.h diff --git a/.vscode/settings.json b/.vscode/settings.json index a818b7e..9ba7cb6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -30,13 +30,15 @@ "sys.h": "c", "nrf_log.h": "c", "version.h": "c", - "zble_service.h": "c", + "zble_module.h": "c", "pca10112.h": "c", "pca10100.h": "c", "board.h": "c", "stdio.h": "c", "nrf_log_ctrl.h": "c", "nrf_log_default_backends.h": "c", - "nrf_delay.h": "c" + "nrf_delay.h": "c", + "zhrs_service.h": "c", + "ble_srv_common.h": "c" } } \ No newline at end of file diff --git a/README.md b/README.md index d446a89..de8b202 100644 --- a/README.md +++ b/README.md @@ -26,4 +26,19 @@ sdk\components\boards\pca10100.h +``` + +``` +设备行为: +1. 按下按键或者电极触发后开始广播 + +2. 当电极没有触发,且蓝牙没有连接,且超时10s后,停止广播,进入低功耗模式 + +3. 设备状态 + + 关机(休眠) + 开机蓝牙未连接(广播中) + 蓝牙已连接 + + ``` \ No newline at end of file diff --git a/app/app.uvoptx b/app/app.uvoptx index da0a52e..c2bba90 100644 --- a/app/app.uvoptx +++ b/app/app.uvoptx @@ -398,8 +398,8 @@ 0 0 0 - .\src\zble_service.c - zble_service.c + .\src\zble_module.c + zble_module.c 0 0 @@ -415,6 +415,18 @@ 0 0 + + 1 + 5 + 1 + 0 + 0 + 0 + .\src\zdatachannel_service.c + zdatachannel_service.c + 0 + 0 + @@ -425,7 +437,7 @@ 0 2 - 5 + 6 1 0 0 @@ -445,7 +457,7 @@ 0 3 - 6 + 7 1 0 0 @@ -457,7 +469,7 @@ 3 - 7 + 8 1 0 0 @@ -477,7 +489,7 @@ 0 4 - 8 + 9 1 0 0 @@ -497,7 +509,7 @@ 0 5 - 9 + 10 1 0 0 @@ -509,7 +521,7 @@ 5 - 10 + 11 1 0 0 @@ -521,7 +533,7 @@ 5 - 11 + 12 1 0 0 @@ -533,7 +545,7 @@ 5 - 12 + 13 1 0 0 @@ -545,7 +557,7 @@ 5 - 13 + 14 1 0 0 @@ -557,7 +569,7 @@ 5 - 14 + 15 1 0 0 @@ -569,7 +581,7 @@ 5 - 15 + 16 1 0 0 @@ -581,7 +593,7 @@ 5 - 16 + 17 1 0 0 @@ -601,7 +613,7 @@ 0 6 - 17 + 18 1 0 0 @@ -621,7 +633,7 @@ 0 7 - 18 + 19 1 0 0 @@ -633,7 +645,7 @@ 7 - 19 + 20 1 0 0 @@ -645,7 +657,7 @@ 7 - 20 + 21 1 0 0 @@ -657,7 +669,7 @@ 7 - 21 + 22 1 0 0 @@ -669,7 +681,7 @@ 7 - 22 + 23 1 0 0 @@ -681,7 +693,7 @@ 7 - 23 + 24 1 0 0 @@ -693,7 +705,7 @@ 7 - 24 + 25 1 0 0 @@ -705,7 +717,7 @@ 7 - 25 + 26 1 0 0 @@ -725,7 +737,7 @@ 0 8 - 26 + 27 1 0 0 @@ -737,7 +749,7 @@ 8 - 27 + 28 1 0 0 @@ -749,7 +761,7 @@ 8 - 28 + 29 1 0 0 @@ -761,7 +773,7 @@ 8 - 29 + 30 1 0 0 @@ -773,7 +785,7 @@ 8 - 30 + 31 1 0 0 @@ -785,7 +797,7 @@ 8 - 31 + 32 1 0 0 @@ -797,7 +809,7 @@ 8 - 32 + 33 1 0 0 @@ -809,7 +821,7 @@ 8 - 33 + 34 1 0 0 @@ -821,7 +833,7 @@ 8 - 34 + 35 1 0 0 @@ -833,7 +845,7 @@ 8 - 35 + 36 1 0 0 @@ -845,7 +857,7 @@ 8 - 36 + 37 1 0 0 @@ -857,7 +869,7 @@ 8 - 37 + 38 1 0 0 @@ -869,7 +881,7 @@ 8 - 38 + 39 1 0 0 @@ -881,7 +893,7 @@ 8 - 39 + 40 1 0 0 @@ -893,7 +905,7 @@ 8 - 40 + 41 1 0 0 @@ -905,7 +917,7 @@ 8 - 41 + 42 1 0 0 @@ -917,7 +929,7 @@ 8 - 42 + 43 1 0 0 @@ -929,7 +941,7 @@ 8 - 43 + 44 1 0 0 @@ -941,7 +953,7 @@ 8 - 44 + 45 1 0 0 @@ -953,7 +965,7 @@ 8 - 45 + 46 1 0 0 @@ -965,7 +977,7 @@ 8 - 46 + 47 1 0 0 @@ -977,7 +989,7 @@ 8 - 47 + 48 1 0 0 @@ -989,7 +1001,7 @@ 8 - 48 + 49 1 0 0 @@ -1001,7 +1013,7 @@ 8 - 49 + 50 1 0 0 @@ -1013,7 +1025,7 @@ 8 - 50 + 51 1 0 0 @@ -1033,7 +1045,7 @@ 0 9 - 51 + 52 1 0 0 @@ -1045,7 +1057,7 @@ 9 - 52 + 53 1 0 0 @@ -1057,7 +1069,7 @@ 9 - 53 + 54 1 0 0 @@ -1069,7 +1081,7 @@ 9 - 54 + 55 1 0 0 @@ -1081,7 +1093,7 @@ 9 - 55 + 56 1 0 0 @@ -1093,7 +1105,7 @@ 9 - 56 + 57 1 0 0 @@ -1113,7 +1125,7 @@ 0 10 - 57 + 58 1 0 0 @@ -1125,7 +1137,7 @@ 10 - 58 + 59 1 0 0 @@ -1137,7 +1149,7 @@ 10 - 59 + 60 1 0 0 @@ -1157,7 +1169,7 @@ 0 11 - 60 + 61 1 0 0 @@ -1169,7 +1181,7 @@ 11 - 61 + 62 1 0 0 @@ -1181,7 +1193,7 @@ 11 - 62 + 63 1 0 0 @@ -1201,7 +1213,7 @@ 0 12 - 63 + 64 1 0 0 diff --git a/app/app.uvprojx b/app/app.uvprojx index 4f40246..e9e26aa 100644 --- a/app/app.uvprojx +++ b/app/app.uvprojx @@ -394,15 +394,20 @@ main.c - zble_service.c + zble_module.c 1 - .\src\zble_service.c + .\src\zble_module.c board.c 1 .\src\board.c + + zdatachannel_service.c + 1 + .\src\zdatachannel_service.c + @@ -4058,15 +4063,20 @@ main.c - zble_service.c + zble_module.c 1 - .\src\zble_service.c + .\src\zble_module.c board.c 1 .\src\board.c + + zdatachannel_service.c + 1 + .\src\zdatachannel_service.c + diff --git a/app/main.c b/app/main.c index f71b293..ac3afaa 100644 --- a/app/main.c +++ b/app/main.c @@ -1,27 +1,13 @@ +#if 1 #include "board.h" #include "nrf_delay.h" #include "project_cfg.h" #include "sys.h" #include "version.h" -#include "zble_service.h" - -zble_service_cfg_t cfg = {.deviceName = "iflytop"}; +#include "zble_module.h" +#include "zdatachannel_service.h" #if 0 -void developer_test(void) { - // 测试LED - debug_light_init(DEBUG_LIGHT_IO_INDEX); - - // 测试BUTTON - uint8_t io_index[] = {11, 12, 24}; - zbsp_gpio_state_monitor(1000, (uint8_t*)io_index, ZARRAY_SIZE(io_index)); - - // 测试睡眠唤醒 - zbsp_enter_sleep(3000, 11, true); -} -#endif -// #define BUTTON_1 -// #define BUTTON_2 void qingfengboard_test(void) { // 测试LED debug_light_init(15); @@ -33,18 +19,52 @@ void qingfengboard_test(void) { // 测试睡眠唤醒 zbsp_enter_sleep(3000, 5, true); } +#endif + +ZDATACANNEL_DEF(m_zhrs, 2 /*回调事件优先级*/, 1 /*client num*/); + +static const char* hex2str(uint8_t data, int32_t len) { + static char rx[64] = {0}; + memset(rx, 0, sizeof(rx)); + for (int32_t i = 0; i < len; i++) { + sprintf(rx + i * 2, "%02X", data); + } + return rx; +} + +void zdatachannel_data_handler(zdatachannel_evt_t* p_evt) { + /** + * @brief 接收到指令数据 + */ + if (p_evt->type == ZDATACANNEL_EVT_RX_DATA) { + ZLOGI("rx:%s", hex2str(p_evt->params.rx_data.p_data[0], p_evt->params.rx_data.length)); + } +} +void on_service_init(void) { + /** + * @brief 数据通道初始化 + */ + ZLOGI("init zdatachannel service"); + zdatachannel_init_t zdatachannle_init; + memset(&zdatachannle_init, 0, sizeof(zdatachannle_init)); + zdatachannle_init.data_handler = zdatachannel_data_handler; + ZERROR_CHECK(zdatachannel_init(&m_zhrs, &zdatachannle_init)); +} int main(void) { zsys_init(); - zble_service_init(&cfg); - - NRF_LOG_INFO("compile time :%s", __TIME__); NRF_LOG_INFO("Version :%d", VERSION); NRF_LOG_INFO("Manufacturer :%s", MANUFACTURER_NAME); - /******************************************************************************* - * 开发板测试 * - *******************************************************************************/ - qingfengboard_test(); + + static zble_module_cfg_t cfg = // + { + .deviceName = "iflytop", + .on_service_init = on_service_init, + }; + zble_module_init(&cfg); + + zble_module_start_adv(); zsys_loop(); } +#endif diff --git a/app/src/zble_module.c b/app/src/zble_module.c new file mode 100644 index 0000000..fcd9864 --- /dev/null +++ b/app/src/zble_module.c @@ -0,0 +1,276 @@ + + +#include "zble_module.h" + +#include +#include + +#include "sys.h" +BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */ +NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/ +/******************************************************************************* + * 广播包配置 * + *******************************************************************************/ +#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */ +#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */ +#define SLAVE_LATENCY 0 /**< Slave latency. */ +#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */ +#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */ +static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ + {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; +#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */ +#define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */ +BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ + +/******************************************************************************* + * GATT配置 * + *******************************************************************************/ +NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ + +/******************************************************************************* + * 连接参数配置 * + *******************************************************************************/ +#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ +#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ +#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */ + +/******************************************************************************* + * CODE * + *******************************************************************************/ + +static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< 当前连接句柄 */ +static uint16_t m_mtu_size = BLE_GATT_ATT_MTU_DEFAULT - 3; + +/**@brief Function for putting the chip into sleep mode. + * + * @note This function will not return. + */ +static void sleep_mode_enter(void) { +#if 0 + uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); + ZERROR_CHECK(err_code); + + // Prepare wakeup buttons. + err_code = bsp_btn_ble_sleep_mode_prepare(); + ZERROR_CHECK(err_code); + + // Go to system-off mode (this function will not return; wakeup will cause a reset). + err_code = sd_power_system_off(); + ZERROR_CHECK(err_code); +#endif +} + +static void ble_evt_handler(ble_evt_t const* p_ble_evt, void* p_context) { + uint32_t err_code; + switch (p_ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + NRF_LOG_INFO("Connected"); + m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + break; + + case BLE_GAP_EVT_DISCONNECTED: + NRF_LOG_INFO("Disconnected"); + m_conn_handle = BLE_CONN_HANDLE_INVALID; + break; + + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { + NRF_LOG_DEBUG("PHY update request."); + ble_gap_phys_t const phys = { + .rx_phys = BLE_GAP_PHY_AUTO, + .tx_phys = BLE_GAP_PHY_AUTO, + }; + err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); + ZERROR_CHECK(err_code); + } break; + + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + // Pairing not supported + err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); + ZERROR_CHECK(err_code); + break; + + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + // No system attributes have been stored. + err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); + ZERROR_CHECK(err_code); + break; + + case BLE_GATTC_EVT_TIMEOUT: + // Disconnect on GATT Client timeout event. + err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + ZERROR_CHECK(err_code); + break; + + case BLE_GATTS_EVT_TIMEOUT: + // Disconnect on GATT Server timeout event. + err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + ZERROR_CHECK(err_code); + break; + + default: + // No implementation needed. + break; + } +} +static void gatt_evt_handler(nrf_ble_gatt_t* p_gatt, nrf_ble_gatt_evt_t const* p_evt) { + /******************************************************************************* + * MTU SIZE 更新 * + *******************************************************************************/ + if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) { + m_mtu_size = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; + NRF_LOG_DEBUG("ATT MTU exchange completed. central %d peripheral %d", p_gatt->att_mtu_desired_central, p_gatt->att_mtu_desired_periph); + } +} +static void on_conn_params_evt(ble_conn_params_evt_t* p_evt) { + uint32_t err_code; + if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) { + err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); + ZERROR_CHECK(err_code); + } +} +static void conn_params_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } +static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { + uint32_t err_code; + switch (ble_adv_evt) { + case BLE_ADV_EVT_FAST: + // err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); + // ZERROR_CHECK(err_code); + break; + case BLE_ADV_EVT_IDLE: + // sleep_mode_enter(); + break; + default: + break; + } +} + +void zble_module_start_adv() { + uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); + ZERROR_CHECK(err_code); +} +void zble_module_stop_adv() { + uint32_t err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle); + ZERROR_CHECK(err_code); +} + +/******************************************************************************* + * INIT * + *******************************************************************************/ +void zble_module_init(zble_module_cfg_t* cfg) { + /** + * @brief + * 初始化蓝牙协议栈,并注册蓝牙事件处理函数,固定代码,勿修改 + */ + { NRF_SDH_BLE_OBSERVER(m_ble_observer, 3, ble_evt_handler, NULL); } + /******************************************************************************* + * GAP初始化 * + *******************************************************************************/ + { + uint32_t err_code; + ble_gap_conn_params_t gap_conn_params; + ble_gap_conn_sec_mode_t sec_mode; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t*)cfg->deviceName, strlen(cfg->deviceName)); + ZERROR_CHECK(err_code); + + memset(&gap_conn_params, 0, sizeof(gap_conn_params)); + + gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; + gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; + gap_conn_params.slave_latency = SLAVE_LATENCY; + gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; + + err_code = sd_ble_gap_ppcp_set(&gap_conn_params); + ZERROR_CHECK(err_code); + } + + /******************************************************************************* + * GATT 初始化 * + *******************************************************************************/ + { + ret_code_t err_code; + + err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler); + ZERROR_CHECK(err_code); + + err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); + ZERROR_CHECK(err_code); + } + + /******************************************************************************* + * 蓝牙服务初始化 * + *******************************************************************************/ + { + // if (cfg->on_service_init) cfg->on_service_init(); + + uint32_t err_code; + ble_nus_init_t nus_init; + nrf_ble_qwr_init_t qwr_init = {0}; + + // Initialize Queued Write Module. + qwr_init.error_handler = NULL; + + err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init); + APP_ERROR_CHECK(err_code); + + // Initialize NUS. + memset(&nus_init, 0, sizeof(nus_init)); + + nus_init.data_handler = NULL; + + err_code = ble_nus_init(&m_nus, &nus_init); + APP_ERROR_CHECK(err_code); + } + + /******************************************************************************* + * 广播初始化 * + *******************************************************************************/ + { + uint32_t err_code; + ble_advertising_init_t init; + + memset(&init, 0, sizeof(init)); + + init.advdata.name_type = BLE_ADVDATA_FULL_NAME; + init.advdata.include_appearance = false; + init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; + + init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); + init.srdata.uuids_complete.p_uuids = m_adv_uuids; + + init.config.ble_adv_fast_enabled = true; + init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; + init.config.ble_adv_fast_timeout = APP_ADV_DURATION; + init.evt_handler = on_adv_evt; + + err_code = ble_advertising_init(&m_advertising, &init); + ZERROR_CHECK(err_code); + + ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); + } + /******************************************************************************* + * 连接参数初始化 * + *******************************************************************************/ + { + uint32_t err_code; + ble_conn_params_init_t cp_init; + + memset(&cp_init, 0, sizeof(cp_init)); + + cp_init.p_conn_params = NULL; + cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; + cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; + cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; + cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; + cp_init.disconnect_on_fail = false; + cp_init.evt_handler = on_conn_params_evt; + cp_init.error_handler = conn_params_error_handler; + + err_code = ble_conn_params_init(&cp_init); + ZERROR_CHECK(err_code); + } + + // zble_module_start_adv(); +} \ No newline at end of file diff --git a/app/src/zble_module.h b/app/src/zble_module.h new file mode 100644 index 0000000..a630a0a --- /dev/null +++ b/app/src/zble_module.h @@ -0,0 +1,20 @@ +#pragma once +#include + +/** + * @brief + */ + +typedef void (*on_service_init_t)(void); + +typedef struct { + const char* deviceName; + on_service_init_t on_service_init; +} zble_module_cfg_t; + +void zble_module_init(zble_module_cfg_t* cfg); + +void zble_module_start_adv(); +void zble_module_stop_adv(); + +void zble_module_is_connected(); diff --git a/app/src/zble_service copy.c b/app/src/zble_service copy.c deleted file mode 100644 index b098a86..0000000 --- a/app/src/zble_service copy.c +++ /dev/null @@ -1,584 +0,0 @@ - - -#include -#include - -#include "app_timer.h" -#include "app_uart.h" -#include "app_util_platform.h" -#include "ble_advdata.h" -#include "ble_advertising.h" -#include "ble_conn_params.h" -#include "ble_hci.h" -#include "ble_nus.h" -#include "bsp_btn_ble.h" -#include "nordic_common.h" -#include "nrf.h" -#include "nrf_ble_gatt.h" -#include "nrf_ble_qwr.h" -#include "nrf_pwr_mgmt.h" -#include "nrf_sdh.h" -#include "nrf_sdh_ble.h" -#include "nrf_sdh_soc.h" - -#if defined(UART_PRESENT) -#include "nrf_uart.h" -#endif -#if defined(UARTE_PRESENT) -#include "nrf_uarte.h" -#endif - -#include "nrf_log.h" -#include "nrf_log_ctrl.h" -#include "nrf_log_default_backends.h" - -#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */ - -#define DEVICE_NAME "Nordic_UART" /**< Name of device. Will be included in the advertising data. */ -#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */ - -#define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */ - -#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */ - -#define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */ - -#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */ -#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */ -#define SLAVE_LATENCY 0 /**< Slave latency. */ -#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */ -#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ -#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ -#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */ - -#define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */ - -#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */ -#define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */ - -BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */ -NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ -NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/ -BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ - -static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ -static uint16_t m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3; /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */ -static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ - {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; - -/**@brief Function for assert macro callback. - * - * @details This function will be called in case of an assert in the SoftDevice. - * - * @warning This handler is an example only and does not fit a final product. You need to analyse - * how your product is supposed to react in case of Assert. - * @warning On assert from the SoftDevice, the system can only recover on reset. - * - * @param[in] line_num Line number of the failing ASSERT call. - * @param[in] p_file_name File name of the failing ASSERT call. - */ -void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name) { app_error_handler(DEAD_BEEF, line_num, p_file_name); } - -/**@brief Function for initializing the timer module. - */ -static void timers_init(void) { - ret_code_t err_code = app_timer_init(); - APP_ERROR_CHECK(err_code); -} - -/**@brief Function for the GAP initialization. - * - * @details This function will set up all the necessary GAP (Generic Access Profile) parameters of - * the device. It also sets the permissions and appearance. - */ -static void gap_params_init(void) { - uint32_t err_code; - ble_gap_conn_params_t gap_conn_params; - ble_gap_conn_sec_mode_t sec_mode; - - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); - - err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)DEVICE_NAME, strlen(DEVICE_NAME)); - APP_ERROR_CHECK(err_code); - - memset(&gap_conn_params, 0, sizeof(gap_conn_params)); - - gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; - gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; - gap_conn_params.slave_latency = SLAVE_LATENCY; - gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; - - err_code = sd_ble_gap_ppcp_set(&gap_conn_params); - APP_ERROR_CHECK(err_code); -} - -/**@brief Function for handling Queued Write Module errors. - * - * @details A pointer to this function will be passed to each service which may need to inform the - * application about an error. - * - * @param[in] nrf_error Error code containing information about what went wrong. - */ -static void nrf_qwr_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } - -/**@brief Function for handling the data from the Nordic UART Service. - * - * @details This function will process the data received from the Nordic UART BLE Service and send - * it to the UART module. - * - * @param[in] p_evt Nordic UART Service event. - */ -/**@snippet [Handling the data received over BLE] */ -static void nus_data_handler(ble_nus_evt_t *p_evt) { - if (p_evt->type == BLE_NUS_EVT_RX_DATA) { - uint32_t err_code; - - NRF_LOG_DEBUG("Received data from BLE NUS. Writing data on UART."); - NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length); - - for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++) { - do { - err_code = app_uart_put(p_evt->params.rx_data.p_data[i]); - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) { - NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code); - APP_ERROR_CHECK(err_code); - } - } while (err_code == NRF_ERROR_BUSY); - } - if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == '\r') { - while (app_uart_put('\n') == NRF_ERROR_BUSY) - ; - } - } -} -/**@snippet [Handling the data received over BLE] */ - -/**@brief Function for initializing services that will be used by the application. - */ -static void services_init(void) { - uint32_t err_code; - ble_nus_init_t nus_init; - nrf_ble_qwr_init_t qwr_init = {0}; - - // Initialize Queued Write Module. - qwr_init.error_handler = nrf_qwr_error_handler; - - err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init); - APP_ERROR_CHECK(err_code); - - // Initialize NUS. - memset(&nus_init, 0, sizeof(nus_init)); - - nus_init.data_handler = nus_data_handler; - - err_code = ble_nus_init(&m_nus, &nus_init); - APP_ERROR_CHECK(err_code); -} - -/**@brief Function for handling an event from the Connection Parameters Module. - * - * @details This function will be called for all events in the Connection Parameters Module - * which are passed to the application. - * - * @note All this function does is to disconnect. This could have been done by simply setting - * the disconnect_on_fail config parameter, but instead we use the event handler - * mechanism to demonstrate its use. - * - * @param[in] p_evt Event received from the Connection Parameters Module. - */ -static void on_conn_params_evt(ble_conn_params_evt_t *p_evt) { - uint32_t err_code; - - if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) { - err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); - APP_ERROR_CHECK(err_code); - } -} - -/**@brief Function for handling errors from the Connection Parameters module. - * - * @param[in] nrf_error Error code containing information about what went wrong. - */ -static void conn_params_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } - -/**@brief Function for initializing the Connection Parameters module. - */ -static void conn_params_init(void) { - uint32_t err_code; - ble_conn_params_init_t cp_init; - - memset(&cp_init, 0, sizeof(cp_init)); - - cp_init.p_conn_params = NULL; - cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; - cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; - cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; - cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; - cp_init.disconnect_on_fail = false; - cp_init.evt_handler = on_conn_params_evt; - cp_init.error_handler = conn_params_error_handler; - - err_code = ble_conn_params_init(&cp_init); - APP_ERROR_CHECK(err_code); -} - -/**@brief Function for putting the chip into sleep mode. - * - * @note This function will not return. - */ -static void sleep_mode_enter(void) { - uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); - APP_ERROR_CHECK(err_code); - - // Prepare wakeup buttons. - err_code = bsp_btn_ble_sleep_mode_prepare(); - APP_ERROR_CHECK(err_code); - - // Go to system-off mode (this function will not return; wakeup will cause a reset). - err_code = sd_power_system_off(); - APP_ERROR_CHECK(err_code); -} - -/**@brief Function for handling advertising events. - * - * @details This function will be called for advertising events which are passed to the application. - * - * @param[in] ble_adv_evt Advertising event. - */ -static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { - uint32_t err_code; - - switch (ble_adv_evt) { - case BLE_ADV_EVT_FAST: - err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); - APP_ERROR_CHECK(err_code); - break; - case BLE_ADV_EVT_IDLE: - sleep_mode_enter(); - break; - default: - break; - } -} - -/**@brief Function for handling BLE events. - * - * @param[in] p_ble_evt Bluetooth stack event. - * @param[in] p_context Unused. - */ -static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) { - uint32_t err_code; - - switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: - NRF_LOG_INFO("Connected"); - err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); - APP_ERROR_CHECK(err_code); - m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle); - APP_ERROR_CHECK(err_code); - break; - - case BLE_GAP_EVT_DISCONNECTED: - NRF_LOG_INFO("Disconnected"); - // LED indication will be changed when advertising starts. - m_conn_handle = BLE_CONN_HANDLE_INVALID; - break; - - case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { - NRF_LOG_DEBUG("PHY update request."); - ble_gap_phys_t const phys = { - .rx_phys = BLE_GAP_PHY_AUTO, - .tx_phys = BLE_GAP_PHY_AUTO, - }; - err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); - APP_ERROR_CHECK(err_code); - } break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - // Pairing not supported - err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); - APP_ERROR_CHECK(err_code); - break; - - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - // No system attributes have been stored. - err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); - APP_ERROR_CHECK(err_code); - break; - - case BLE_GATTC_EVT_TIMEOUT: - // Disconnect on GATT Client timeout event. - err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); - APP_ERROR_CHECK(err_code); - break; - - case BLE_GATTS_EVT_TIMEOUT: - // Disconnect on GATT Server timeout event. - err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); - APP_ERROR_CHECK(err_code); - break; - - default: - // No implementation needed. - break; - } -} - -/**@brief Function for the SoftDevice initialization. - * - * @details This function initializes the SoftDevice and the BLE event interrupt. - */ -static void ble_stack_init(void) { - ret_code_t err_code; - - err_code = nrf_sdh_enable_request(); - APP_ERROR_CHECK(err_code); - - // Configure the BLE stack using the default settings. - // Fetch the start address of the application RAM. - uint32_t ram_start = 0; - err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); - APP_ERROR_CHECK(err_code); - - // Enable BLE stack. - err_code = nrf_sdh_ble_enable(&ram_start); - APP_ERROR_CHECK(err_code); - - // Register a handler for BLE events. - NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); -} - -/**@brief Function for handling events from the GATT library. */ -void gatt_evt_handler(nrf_ble_gatt_t *p_gatt, nrf_ble_gatt_evt_t const *p_evt) { - if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) { - m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; - NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len); - } - NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x", p_gatt->att_mtu_desired_central, p_gatt->att_mtu_desired_periph); -} - -/**@brief Function for initializing the GATT library. */ -void gatt_init(void) { - ret_code_t err_code; - - err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler); - APP_ERROR_CHECK(err_code); - - err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); - APP_ERROR_CHECK(err_code); -} - -/**@brief Function for handling events from the BSP module. - * - * @param[in] event Event generated by button press. - */ -void bsp_event_handler(bsp_event_t event) { - uint32_t err_code; - switch (event) { - case BSP_EVENT_SLEEP: - sleep_mode_enter(); - break; - - case BSP_EVENT_DISCONNECT: - err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); - if (err_code != NRF_ERROR_INVALID_STATE) { - APP_ERROR_CHECK(err_code); - } - break; - - case BSP_EVENT_WHITELIST_OFF: - if (m_conn_handle == BLE_CONN_HANDLE_INVALID) { - err_code = ble_advertising_restart_without_whitelist(&m_advertising); - if (err_code != NRF_ERROR_INVALID_STATE) { - APP_ERROR_CHECK(err_code); - } - } - break; - - default: - break; - } -} - -/**@brief Function for handling app_uart events. - * - * @details This function will receive a single character from the app_uart module and append it to - * a string. The string will be be sent over BLE when the last character received was a - * 'new line' '\n' (hex 0x0A) or if the string has reached the maximum data length. - */ -/**@snippet [Handling the data received over UART] */ -void uart_event_handle(app_uart_evt_t *p_event) { - static uint8_t data_array[BLE_NUS_MAX_DATA_LEN]; - static uint8_t index = 0; - uint32_t err_code; - - switch (p_event->evt_type) { - case APP_UART_DATA_READY: - UNUSED_VARIABLE(app_uart_get(&data_array[index])); - index++; - - if ((data_array[index - 1] == '\n') || (data_array[index - 1] == '\r') || (index >= m_ble_nus_max_data_len)) { - if (index > 1) { - NRF_LOG_DEBUG("Ready to send data over BLE NUS"); - NRF_LOG_HEXDUMP_DEBUG(data_array, index); - - do { - uint16_t length = (uint16_t)index; - err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle); - if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_ERROR_RESOURCES) && (err_code != NRF_ERROR_NOT_FOUND)) { - APP_ERROR_CHECK(err_code); - } - } while (err_code == NRF_ERROR_RESOURCES); - } - - index = 0; - } - break; - - case APP_UART_COMMUNICATION_ERROR: - APP_ERROR_HANDLER(p_event->data.error_communication); - break; - - case APP_UART_FIFO_ERROR: - APP_ERROR_HANDLER(p_event->data.error_code); - break; - - default: - break; - } -} -/**@snippet [Handling the data received over UART] */ - -/**@brief Function for initializing the UART module. - */ -/**@snippet [UART Initialization] */ -static void uart_init(void) { - uint32_t err_code; - app_uart_comm_params_t const comm_params = { - .rx_pin_no = RX_PIN_NUMBER, - .tx_pin_no = TX_PIN_NUMBER, - .rts_pin_no = RTS_PIN_NUMBER, - .cts_pin_no = CTS_PIN_NUMBER, - .flow_control = APP_UART_FLOW_CONTROL_DISABLED, - .use_parity = false, -#if defined(UART_PRESENT) - .baud_rate = NRF_UART_BAUDRATE_115200 -#else - .baud_rate = NRF_UARTE_BAUDRATE_115200 -#endif - }; - - APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE, uart_event_handle, APP_IRQ_PRIORITY_LOWEST, err_code); - APP_ERROR_CHECK(err_code); -} -/**@snippet [UART Initialization] */ - -/**@brief Function for initializing the Advertising functionality. - */ -static void advertising_init(void) { - uint32_t err_code; - ble_advertising_init_t init; - - memset(&init, 0, sizeof(init)); - - init.advdata.name_type = BLE_ADVDATA_FULL_NAME; - init.advdata.include_appearance = false; - init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; - - init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); - init.srdata.uuids_complete.p_uuids = m_adv_uuids; - - init.config.ble_adv_fast_enabled = true; - init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; - init.config.ble_adv_fast_timeout = APP_ADV_DURATION; - init.evt_handler = on_adv_evt; - - err_code = ble_advertising_init(&m_advertising, &init); - APP_ERROR_CHECK(err_code); - - ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); -} - -/**@brief Function for initializing buttons and leds. - * - * @param[out] p_erase_bonds Will be true if the clear bonding button was pressed to wake the application up. - */ -static void buttons_leds_init(bool *p_erase_bonds) { - bsp_event_t startup_event; - - uint32_t err_code = bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler); - APP_ERROR_CHECK(err_code); - - err_code = bsp_btn_ble_init(NULL, &startup_event); - APP_ERROR_CHECK(err_code); - - *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); -} - -/**@brief Function for initializing the nrf log module. - */ -static void log_init(void) { - ret_code_t err_code = NRF_LOG_INIT(NULL); - APP_ERROR_CHECK(err_code); - - NRF_LOG_DEFAULT_BACKENDS_INIT(); -} - -/**@brief Function for initializing power management. - */ -static void power_management_init(void) { - ret_code_t err_code; - err_code = nrf_pwr_mgmt_init(); - APP_ERROR_CHECK(err_code); -} - -/**@brief Function for handling the idle state (main loop). - * - * @details If there is no pending log operation, then sleep until next the next event occurs. - */ -static void idle_state_handle(void) { - if (NRF_LOG_PROCESS() == false) { - nrf_pwr_mgmt_run(); - } -} - -/**@brief Function for starting advertising. - */ -static void advertising_start(void) { - uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); - APP_ERROR_CHECK(err_code); -} - -/**@brief Application main function. - */ -int main(void) { - bool erase_bonds; - // // Initialize. - // uart_init(); - // log_init(); - - // timers_init(); - // buttons_leds_init(&erase_bonds); - // power_management_init(); - // ble_stack_init(); - // gap_params_init(); - // gatt_init(); - services_init(); - advertising_init(); - conn_params_init(); - - // Start execution. - printf("\r\nUART started.\r\n"); - NRF_LOG_INFO("Debug logging for UART over RTT started."); - advertising_start(); - - // Enter main loop. - for (;;) { - idle_state_handle(); - } -} - -/** - * @} - */ diff --git a/app/src/zble_service.c b/app/src/zble_service.c deleted file mode 100644 index c06b26f..0000000 --- a/app/src/zble_service.c +++ /dev/null @@ -1,284 +0,0 @@ - - -#include "zble_service.h" - -#include -#include - -#include "sys.h" -BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */ -NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/ -/******************************************************************************* - * 广播包配置 * - *******************************************************************************/ -#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */ -#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */ -#define SLAVE_LATENCY 0 /**< Slave latency. */ -#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */ -#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */ -static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ - {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; -#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */ -#define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */ -BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ -#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */ - -/******************************************************************************* - * GATT配置 * - *******************************************************************************/ -NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ - -/******************************************************************************* - * 连接参数配置 * - *******************************************************************************/ -#define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */ -#define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(30000) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */ -#define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */ - -/******************************************************************************* - * CODE * - *******************************************************************************/ - -static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< 当前连接句柄 */ -static uint16_t m_mtu_size = BLE_GATT_ATT_MTU_DEFAULT - 3; - -/**@brief Function for putting the chip into sleep mode. - * - * @note This function will not return. - */ -static void sleep_mode_enter(void) { -#if 0 - uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); - APP_ERROR_CHECK(err_code); - - // Prepare wakeup buttons. - err_code = bsp_btn_ble_sleep_mode_prepare(); - APP_ERROR_CHECK(err_code); - - // Go to system-off mode (this function will not return; wakeup will cause a reset). - err_code = sd_power_system_off(); - APP_ERROR_CHECK(err_code); -#endif -} - -static void ble_evt_handler(ble_evt_t const* p_ble_evt, void* p_context) { - uint32_t err_code; - switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: - NRF_LOG_INFO("Connected"); - m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; - break; - - case BLE_GAP_EVT_DISCONNECTED: - NRF_LOG_INFO("Disconnected"); - m_conn_handle = BLE_CONN_HANDLE_INVALID; - break; - - case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { - NRF_LOG_DEBUG("PHY update request."); - ble_gap_phys_t const phys = { - .rx_phys = BLE_GAP_PHY_AUTO, - .tx_phys = BLE_GAP_PHY_AUTO, - }; - err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); - APP_ERROR_CHECK(err_code); - } break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - // Pairing not supported - err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); - APP_ERROR_CHECK(err_code); - break; - - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - // No system attributes have been stored. - err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); - APP_ERROR_CHECK(err_code); - break; - - case BLE_GATTC_EVT_TIMEOUT: - // Disconnect on GATT Client timeout event. - err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); - APP_ERROR_CHECK(err_code); - break; - - case BLE_GATTS_EVT_TIMEOUT: - // Disconnect on GATT Server timeout event. - err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); - APP_ERROR_CHECK(err_code); - break; - - default: - // No implementation needed. - break; - } -} -static void gatt_evt_handler(nrf_ble_gatt_t* p_gatt, nrf_ble_gatt_evt_t const* p_evt) { - /******************************************************************************* - * MTU SIZE 更新 * - *******************************************************************************/ - if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) { - m_mtu_size = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; - NRF_LOG_DEBUG("ATT MTU exchange completed. central %d peripheral %d", p_gatt->att_mtu_desired_central, p_gatt->att_mtu_desired_periph); - } -} -static void on_conn_params_evt(ble_conn_params_evt_t* p_evt) { - uint32_t err_code; - if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED) { - err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE); - APP_ERROR_CHECK(err_code); - } -} -static void conn_params_error_handler(uint32_t nrf_error) { APP_ERROR_HANDLER(nrf_error); } -static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { - uint32_t err_code; - switch (ble_adv_evt) { - case BLE_ADV_EVT_FAST: - err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING); - APP_ERROR_CHECK(err_code); - break; - case BLE_ADV_EVT_IDLE: - sleep_mode_enter(); - break; - default: - break; - } -} - -void zble_service_start_adv() { - uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); - APP_ERROR_CHECK(err_code); -} -void zble_service_stop_adv() {} - -/******************************************************************************* - * INIT * - *******************************************************************************/ -void zble_service_init(zble_service_cfg_t* cfg) { - /** - * @brief - * 初始化蓝牙协议栈,并注册蓝牙事件处理函数,固定代码,勿修改 - */ - { - ret_code_t err_code; - err_code = nrf_sdh_enable_request(); - APP_ERROR_CHECK(err_code); - uint32_t ram_start = 0; - err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); - APP_ERROR_CHECK(err_code); - // Enable BLE stack. - err_code = nrf_sdh_ble_enable(&ram_start); - APP_ERROR_CHECK(err_code); - // Register a handler for BLE events. - NRF_SDH_BLE_OBSERVER(m_ble_observer, 3, ble_evt_handler, NULL); - } - /******************************************************************************* - * GAP初始化 * - *******************************************************************************/ - { - uint32_t err_code; - ble_gap_conn_params_t gap_conn_params; - ble_gap_conn_sec_mode_t sec_mode; - - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); - - err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t*)cfg->deviceName, strlen(cfg->deviceName)); - APP_ERROR_CHECK(err_code); - - memset(&gap_conn_params, 0, sizeof(gap_conn_params)); - - gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; - gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; - gap_conn_params.slave_latency = SLAVE_LATENCY; - gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; - - err_code = sd_ble_gap_ppcp_set(&gap_conn_params); - APP_ERROR_CHECK(err_code); - } - - /******************************************************************************* - * GATT 初始化 * - *******************************************************************************/ - { - ret_code_t err_code; - - err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler); - APP_ERROR_CHECK(err_code); - - err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); - APP_ERROR_CHECK(err_code); - } - - /******************************************************************************* - * 蓝牙服务初始化 * - *******************************************************************************/ - { - uint32_t err_code; - ble_nus_init_t nus_init; - nrf_ble_qwr_init_t qwr_init = {0}; - - // Initialize Queued Write Module. - qwr_init.error_handler = NULL; - - err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init); - APP_ERROR_CHECK(err_code); - - // Initialize NUS. - memset(&nus_init, 0, sizeof(nus_init)); - - nus_init.data_handler = NULL; - - err_code = ble_nus_init(&m_nus, &nus_init); - APP_ERROR_CHECK(err_code); - } - - /******************************************************************************* - * 广播初始化 * - *******************************************************************************/ - { - uint32_t err_code; - ble_advertising_init_t init; - - memset(&init, 0, sizeof(init)); - - init.advdata.name_type = BLE_ADVDATA_FULL_NAME; - init.advdata.include_appearance = false; - init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE; - - init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); - init.srdata.uuids_complete.p_uuids = m_adv_uuids; - - init.config.ble_adv_fast_enabled = true; - init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; - init.config.ble_adv_fast_timeout = APP_ADV_DURATION; - init.evt_handler = on_adv_evt; - - err_code = ble_advertising_init(&m_advertising, &init); - APP_ERROR_CHECK(err_code); - - ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); - } - /******************************************************************************* - * 连接参数初始化 * - *******************************************************************************/ - { - uint32_t err_code; - ble_conn_params_init_t cp_init; - - memset(&cp_init, 0, sizeof(cp_init)); - - cp_init.p_conn_params = NULL; - cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; - cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; - cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; - cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; - cp_init.disconnect_on_fail = false; - cp_init.evt_handler = on_conn_params_evt; - cp_init.error_handler = conn_params_error_handler; - - err_code = ble_conn_params_init(&cp_init); - APP_ERROR_CHECK(err_code); - } - - // zble_service_start_adv(); -} \ No newline at end of file diff --git a/app/src/zble_service.h b/app/src/zble_service.h deleted file mode 100644 index e5564d1..0000000 --- a/app/src/zble_service.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include - -typedef struct { - uint8_t mark; // 占位 - // const char *service_uuid; // 服务UUID - // const char *cmd_tx_uuid; // - // const char *cmd_rx_uuid; - // const char *special_tx_uuid; - - const char* deviceName; - -} zble_service_cfg_t; - -typedef enum { - konconnect, - kdisconnect, -} event_t; - -typedef void (*zble_service_cmd_rx_cb_t)(uint8_t* data, uint32_t len); - -void zble_service_init(zble_service_cfg_t* cfg); -void zble_service_send_by_cmd_channel(uint8_t* data, uint32_t len); -void zble_service_send_by_record_channel(uint8_t* data, uint32_t len); - -void zble_service_start_adv(); -void zble_service_stop_adv(); diff --git a/app/src/zdatachannel_service.c b/app/src/zdatachannel_service.c new file mode 100644 index 0000000..4a45c70 --- /dev/null +++ b/app/src/zdatachannel_service.c @@ -0,0 +1,249 @@ +#include "zdatachannel_service.h" + +#include "ble.h" +#include "ble_srv_common.h" +#include "nrf_log.h" +#include "sdk_common.h" + +#define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */ +#define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */ + +#define ZDATACANNEL_MAX_RX_CHAR_LEN ZDATACANNEL_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */ +#define ZDATACANNEL_MAX_TX_CHAR_LEN ZDATACANNEL_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ + +#define NUS_BASE_UUID \ + { \ + { 0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E } \ + } /**< Used vendor specific UUID. */ + +/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_connect(zdatachannel_t *p_nus, ble_evt_t const *p_ble_evt) { + ret_code_t err_code; + zdatachannel_evt_t evt; + ble_gatts_value_t gatts_val; + uint8_t cccd_value[2]; + zdatachannel_client_context_t *p_client = NULL; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, p_ble_evt->evt.gap_evt.conn_handle, (void *)&p_client); + if (err_code != NRF_SUCCESS) { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", p_ble_evt->evt.gap_evt.conn_handle); + } + + /* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */ + memset(&gatts_val, 0, sizeof(ble_gatts_value_t)); + gatts_val.p_value = cccd_value; + gatts_val.len = sizeof(cccd_value); + gatts_val.offset = 0; + + err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle, p_nus->tx_handles.cccd_handle, &gatts_val); + + if ((err_code == NRF_SUCCESS) && (p_nus->data_handler != NULL) && ble_srv_is_notification_enabled(gatts_val.p_value)) { + if (p_client != NULL) { + p_client->is_notification_enabled = true; + } + + memset(&evt, 0, sizeof(zdatachannel_evt_t)); + evt.type = ZDATACANNEL_EVT_COMM_STARTED; + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + evt.p_link_ctx = p_client; + + p_nus->data_handler(&evt); + } +} + +/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_write(zdatachannel_t *p_nus, ble_evt_t const *p_ble_evt) { + ret_code_t err_code; + zdatachannel_evt_t evt; + zdatachannel_client_context_t *p_client; + ble_gatts_evt_write_t const *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, p_ble_evt->evt.gatts_evt.conn_handle, (void *)&p_client); + if (err_code != NRF_SUCCESS) { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", p_ble_evt->evt.gatts_evt.conn_handle); + } + + memset(&evt, 0, sizeof(zdatachannel_evt_t)); + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + evt.p_link_ctx = p_client; + + if ((p_evt_write->handle == p_nus->tx_handles.cccd_handle) && (p_evt_write->len == 2)) { + if (p_client != NULL) { + if (ble_srv_is_notification_enabled(p_evt_write->data)) { + p_client->is_notification_enabled = true; + evt.type = ZDATACANNEL_EVT_COMM_STARTED; + } else { + p_client->is_notification_enabled = false; + evt.type = ZDATACANNEL_EVT_COMM_STOPPED; + } + + if (p_nus->data_handler != NULL) { + p_nus->data_handler(&evt); + } + } + } else if ((p_evt_write->handle == p_nus->rx_handles.value_handle) && (p_nus->data_handler != NULL)) { + evt.type = ZDATACANNEL_EVT_RX_DATA; + evt.params.rx_data.p_data = p_evt_write->data; + evt.params.rx_data.length = p_evt_write->len; + + p_nus->data_handler(&evt); + } else { + // Do Nothing. This event is not relevant for this service. + } +} + +/**@brief Function for handling the @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_hvx_tx_complete(zdatachannel_t *p_nus, ble_evt_t const *p_ble_evt) { + ret_code_t err_code; + zdatachannel_evt_t evt; + zdatachannel_client_context_t *p_client; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, p_ble_evt->evt.gatts_evt.conn_handle, (void *)&p_client); + if (err_code != NRF_SUCCESS) { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", p_ble_evt->evt.gatts_evt.conn_handle); + return; + } + + if ((p_client->is_notification_enabled) && (p_nus->data_handler != NULL)) { + memset(&evt, 0, sizeof(zdatachannel_evt_t)); + evt.type = ZDATACANNEL_EVT_TX_RDY; + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + evt.p_link_ctx = p_client; + + p_nus->data_handler(&evt); + } +} + +void zdatachannel_on_ble_evt(ble_evt_t const *p_ble_evt, void *p_context) { + if ((p_context == NULL) || (p_ble_evt == NULL)) { + return; + } + + zdatachannel_t *p_nus = (zdatachannel_t *)p_context; + + switch (p_ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + on_connect(p_nus, p_ble_evt); + break; + + case BLE_GATTS_EVT_WRITE: + on_write(p_nus, p_ble_evt); + break; + + case BLE_GATTS_EVT_HVN_TX_COMPLETE: + on_hvx_tx_complete(p_nus, p_ble_evt); + break; + + default: + // No implementation needed. + break; + } +} + +uint32_t zdatachannel_init(zdatachannel_t *p_nus, zdatachannel_init_t const *p_nus_init) { + ret_code_t err_code; + ble_uuid_t ble_uuid; + ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; + ble_add_char_params_t add_char_params; + + VERIFY_PARAM_NOT_NULL(p_nus); + VERIFY_PARAM_NOT_NULL(p_nus_init); + + // Initialize the service structure. + p_nus->data_handler = p_nus_init->data_handler; + + /**@snippet [Adding proprietary Service to the SoftDevice] */ + // Add a custom base UUID. + err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); + VERIFY_SUCCESS(err_code); + + ble_uuid.type = p_nus->uuid_type; + ble_uuid.uuid = BLE_UUID_NUS_SERVICE; + + // Add the service. + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_nus->service_handle); + /**@snippet [Adding proprietary Service to the SoftDevice] */ + VERIFY_SUCCESS(err_code); + + // Add the RX Characteristic. + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = ZDATACANNEL_MAX_RX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.write = 1; + add_char_params.char_props.write_wo_resp = 1; + + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + + err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + // Add the TX Characteristic. + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = BLE_UUID_NUS_TX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = ZDATACANNEL_MAX_TX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.notify = 1; + + add_char_params.read_access = SEC_OPEN; + add_char_params.write_access = SEC_OPEN; + add_char_params.cccd_write_access = SEC_OPEN; + + return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles); + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ +} + +uint32_t zdatachannel_data_send(zdatachannel_t *p_nus, uint8_t *p_data, uint16_t *p_length, uint16_t conn_handle) { + ret_code_t err_code; + ble_gatts_hvx_params_t hvx_params; + zdatachannel_client_context_t *p_client; + + VERIFY_PARAM_NOT_NULL(p_nus); + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *)&p_client); + VERIFY_SUCCESS(err_code); + + if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL)) { + return NRF_ERROR_NOT_FOUND; + } + + if (!p_client->is_notification_enabled) { + return NRF_ERROR_INVALID_STATE; + } + + if (*p_length > ZDATACANNEL_MAX_DATA_LEN) { + return NRF_ERROR_INVALID_PARAM; + } + + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_nus->tx_handles.value_handle; + hvx_params.p_data = p_data; + hvx_params.p_len = p_length; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + + return sd_ble_gatts_hvx(conn_handle, &hvx_params); +} diff --git a/app/src/zdatachannel_service.h b/app/src/zdatachannel_service.h new file mode 100644 index 0000000..f9cffd0 --- /dev/null +++ b/app/src/zdatachannel_service.h @@ -0,0 +1,95 @@ +#ifndef ZDATACANNEL_H__ +#define ZDATACANNEL_H__ + +#include +#include + +#include "ble.h" +#include "ble_link_ctx_manager.h" +#include "ble_srv_common.h" +#include "nrf_sdh_ble.h" +#include "sdk_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**@brief Macro for defining a ble_nus instance. + * + * @param _name Name of the instance. + * @param[in] _nus_max_clients Maximum number of NUS clients connected at a time. + * @hideinitializer + */ +#define ZDATACANNEL_DEF(_name, _ble_observer_prio,_nus_max_clients) \ + BLE_LINK_CTX_MANAGER_DEF(CONCAT_2(_name, _link_ctx_storage), (_nus_max_clients), sizeof(zdatachannel_client_context_t)); \ + static zdatachannel_t _name = {.p_link_ctx_storage = &CONCAT_2(_name, _link_ctx_storage)}; \ + NRF_SDH_BLE_OBSERVER(_name##_obs, _ble_observer_prio, zdatachannel_on_ble_evt, &_name) + +#define BLE_UUID_NUS_SERVICE 0x0001 /**< The UUID of the Nordic UART Service. */ + +#define OPCODE_LENGTH 1 +#define HANDLE_LENGTH 2 + +/**@brief Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */ +#if defined(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) && (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 0) +#define ZDATACANNEL_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH) +#else +#define ZDATACANNEL_MAX_DATA_LEN (BLE_GATT_MTU_SIZE_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH) +#warning NRF_SDH_BLE_GATT_MAX_MTU_SIZE is not defined. +#endif + +/**@brief Nordic UART Service event types. */ +typedef enum { + ZDATACANNEL_EVT_RX_DATA, /**< Data received. */ + ZDATACANNEL_EVT_TX_RDY, /**< Service is ready to accept new data to be transmitted. */ + ZDATACANNEL_EVT_COMM_STARTED, /**< Notification has been enabled. */ + ZDATACANNEL_EVT_COMM_STOPPED, /**< Notification has been disabled. */ +} zdatachannel_evt_type_t; + +typedef struct zdatachannel_s zdatachannel_t; + +typedef struct { + uint8_t const* p_data; /**< A pointer to the buffer with received data. */ + uint16_t length; /**< Length of received data. */ +} zdatachannel_evt_rx_data_t; + +typedef struct { + bool is_notification_enabled; /**< Variable to indicate if the peer has enabled notification of the RX characteristic.*/ +} zdatachannel_client_context_t; + +typedef struct { + zdatachannel_evt_type_t type; /**< Event type. */ + zdatachannel_t* p_nus; /**< A pointer to the instance. */ + uint16_t conn_handle; /**< Connection handle. */ + zdatachannel_client_context_t* p_link_ctx; /**< A pointer to the link context. */ + union { + zdatachannel_evt_rx_data_t rx_data; /**< @ref ZDATACANNEL_EVT_RX_DATA event data. */ + } params; +} zdatachannel_evt_t; + +typedef void (*zdatachannel_data_handler_t)(zdatachannel_evt_t* p_evt); + +typedef struct { + zdatachannel_data_handler_t data_handler; /**< Event handler to be called for handling received data. */ +} zdatachannel_init_t; + +struct zdatachannel_s { + uint8_t uuid_type; /**< UUID type for Nordic UART Service Base UUID. */ + uint16_t service_handle; /**< Handle of Nordic UART Service (as provided by the SoftDevice). */ + ble_gatts_char_handles_t tx_handles; /**< Handles related to the TX characteristic (as provided by the SoftDevice). */ + ble_gatts_char_handles_t rx_handles; /**< Handles related to the RX characteristic (as provided by the SoftDevice). */ + blcm_link_ctx_storage_t* const p_link_ctx_storage; /**< Pointer to link context storage with handles of all current connections and its context. */ + zdatachannel_data_handler_t data_handler; /**< Event handler to be called for handling received data. */ +}; + +uint32_t zdatachannel_init(zdatachannel_t* p_nus, zdatachannel_init_t const* p_nus_init); +void zdatachannel_on_ble_evt(ble_evt_t const* p_ble_evt, void* p_context); +uint32_t zdatachannel_data_send(zdatachannel_t* p_nus, uint8_t* p_data, uint16_t* p_length, uint16_t conn_handle); + +#ifdef __cplusplus +} +#endif + +#endif // ZDATACANNEL_H__ + +/** @} */ diff --git a/libznordic b/libznordic index 3678551..5c809e7 160000 --- a/libznordic +++ b/libznordic @@ -1 +1 @@ -Subproject commit 3678551881438d95c91c36b2f2277219084e2a05 +Subproject commit 5c809e793ce8fc2f764a68f1eade7e59f39b1259