diff --git a/include/bluetooth/services/hrs.h b/include/bluetooth/services/hrs.h new file mode 100644 index 00000000000000..81434a463a39c2 --- /dev/null +++ b/include/bluetooth/services/hrs.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_HRS_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_HRS_H_ + +/** + * @brief Heart Rate Service (HRS) + * @defgroup bt_gatt_hrs Heart Rate Service (HRS) + * @ingroup bluetooth + * @{ + * + * [Experimental] Users should note that the APIs can change + * as a part of ongoing development. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Notify heart rate measurement. + * + * This will send a GATT notification to all current subscribers. + * + * @param heartrate The heartrate measuremennt in beats per minute. + * + * @return Zero in case of success and error code in case of error. + */ +int bt_gatt_hrs_notify(u16_t heartrate); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_SERVICES_HRS_H_ */ diff --git a/samples/bluetooth/gatt/hrs.h b/samples/bluetooth/gatt/hrs.h deleted file mode 100644 index 09639e6c93e5a6..00000000000000 --- a/samples/bluetooth/gatt/hrs.h +++ /dev/null @@ -1,20 +0,0 @@ -/** @file - * @brief HRS Service sample - */ - -/* - * Copyright (c) 2016 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifdef __cplusplus -extern "C" { -#endif - -void hrs_init(u8_t blsc); -void hrs_notify(void); - -#ifdef __cplusplus -} -#endif diff --git a/samples/bluetooth/peripheral/CMakeLists.txt b/samples/bluetooth/peripheral/CMakeLists.txt index c422689447a806..8527169a88b1d5 100644 --- a/samples/bluetooth/peripheral/CMakeLists.txt +++ b/samples/bluetooth/peripheral/CMakeLists.txt @@ -6,7 +6,6 @@ project(peripheral) target_sources(app PRIVATE src/main.c - ../gatt/hrs.c ../gatt/cts.c ) diff --git a/samples/bluetooth/peripheral/prj.conf b/samples/bluetooth/peripheral/prj.conf index 7aca9a68571a63..9c3d5385ea3558 100644 --- a/samples/bluetooth/peripheral/prj.conf +++ b/samples/bluetooth/peripheral/prj.conf @@ -9,6 +9,7 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT_GATT_DIS=y CONFIG_BT_ATT_PREPARE_COUNT=5 CONFIG_BT_GATT_BAS=y +CONFIG_BT_GATT_HRS=y CONFIG_BT_PRIVACY=y CONFIG_BT_DEVICE_NAME="Zephyr Peripheral Sample Long Name" CONFIG_BT_DEVICE_APPEARANCE=833 diff --git a/samples/bluetooth/peripheral/src/main.c b/samples/bluetooth/peripheral/src/main.c index 8b3c3ad83c5431..95dce1e0843aaf 100644 --- a/samples/bluetooth/peripheral/src/main.c +++ b/samples/bluetooth/peripheral/src/main.c @@ -22,8 +22,8 @@ #include #include #include +#include -#include #include /* Custom Service Variables */ @@ -254,7 +254,6 @@ static void bt_ready(int err) printk("Bluetooth initialized\n"); - hrs_init(0x01); cts_init(); if (IS_ENABLED(CONFIG_SETTINGS)) { @@ -307,6 +306,19 @@ static void bas_notify(void) bt_gatt_bas_set_battery_level(battery_level); } +static void hrs_notify(void) +{ + static u8_t heartrate = 90U; + + /* Heartrate measurements simulation */ + heartrate++; + if (heartrate == 160U) { + heartrate = 90U; + } + + bt_gatt_hrs_notify(heartrate); +} + void main(void) { int err; diff --git a/samples/bluetooth/peripheral_hr/CMakeLists.txt b/samples/bluetooth/peripheral_hr/CMakeLists.txt index 06415c207644c2..279e6af9d35259 100644 --- a/samples/bluetooth/peripheral_hr/CMakeLists.txt +++ b/samples/bluetooth/peripheral_hr/CMakeLists.txt @@ -8,7 +8,6 @@ project(peripheral_hr) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources} - ../gatt/hrs.c ) zephyr_library_include_directories($ENV{ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/peripheral_hr/prj.conf b/samples/bluetooth/peripheral_hr/prj.conf index 7d290e0c645351..3dfa8796b8cc8e 100644 --- a/samples/bluetooth/peripheral_hr/prj.conf +++ b/samples/bluetooth/peripheral_hr/prj.conf @@ -5,5 +5,6 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT_GATT_DIS=y CONFIG_BT_GATT_DIS_PNP=n CONFIG_BT_GATT_BAS=y +CONFIG_BT_GATT_HRS=y CONFIG_BT_DEVICE_NAME="Zephyr Heartrate Sensor" CONFIG_BT_DEVICE_APPEARANCE=833 diff --git a/samples/bluetooth/peripheral_hr/src/main.c b/samples/bluetooth/peripheral_hr/src/main.c index 720f4cc49a493d..30fd6c73650e4f 100644 --- a/samples/bluetooth/peripheral_hr/src/main.c +++ b/samples/bluetooth/peripheral_hr/src/main.c @@ -20,8 +20,7 @@ #include #include #include - -#include +#include struct bt_conn *default_conn; @@ -64,8 +63,6 @@ static void bt_ready(int err) printk("Bluetooth initialized\n"); - hrs_init(0x01); - err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); if (err) { printk("Advertising failed to start (err %d)\n", err); @@ -101,6 +98,19 @@ static void bas_notify(void) bt_gatt_bas_set_battery_level(battery_level); } +static void hrs_notify(void) +{ + static u8_t heartrate = 90U; + + /* Heartrate measurements simulation */ + heartrate++; + if (heartrate == 160U) { + heartrate = 90U; + } + + bt_gatt_hrs_notify(heartrate); +} + void main(void) { int err; diff --git a/subsys/bluetooth/services/CMakeLists.txt b/subsys/bluetooth/services/CMakeLists.txt index 5e18d549884032..a321120997c103 100644 --- a/subsys/bluetooth/services/CMakeLists.txt +++ b/subsys/bluetooth/services/CMakeLists.txt @@ -4,3 +4,5 @@ zephyr_sources_ifdef(CONFIG_BT_GATT_DIS dis.c) zephyr_sources_ifdef(CONFIG_BT_GATT_BAS bas.c) + +zephyr_sources_ifdef(CONFIG_BT_GATT_HRS hrs.c) diff --git a/subsys/bluetooth/services/Kconfig b/subsys/bluetooth/services/Kconfig index 45555181fab59c..5000256bc17ecd 100644 --- a/subsys/bluetooth/services/Kconfig +++ b/subsys/bluetooth/services/Kconfig @@ -13,6 +13,8 @@ source "subsys/bluetooth/services/Kconfig.dis" source "subsys/bluetooth/services/Kconfig.bas" +source "subsys/bluetooth/services/Kconfig.hrs" + endmenu endif #BT_CONN diff --git a/subsys/bluetooth/services/Kconfig.hrs b/subsys/bluetooth/services/Kconfig.hrs new file mode 100644 index 00000000000000..f3a77303b381e3 --- /dev/null +++ b/subsys/bluetooth/services/Kconfig.hrs @@ -0,0 +1,28 @@ +# Kconfig - Bluetooth GATT Heart Rate service +# +# Copyright (c) 2018 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig BT_GATT_HRS + bool "Enable GATT Heart Rate service" + default n + +if BT_GATT_HRS + +config BT_GATT_HRS_LOG_LEVEL + int "Heart Rate service log level" + depends on LOG + range 0 4 + default 0 + help + Sets log level for the Heart Rate service. + Levels are: + 0 OFF, do not write + 1 ERROR, only write LOG_ERR + 2 WARNING, write LOG_WRN in addition to previous level + 3 INFO, write LOG_INF in addition to previous levels + 4 DEBUG, write LOG_DBG in addition to previous levels + +endif #BT_GATT_BAS diff --git a/samples/bluetooth/gatt/hrs.c b/subsys/bluetooth/services/hrs.c similarity index 70% rename from samples/bluetooth/gatt/hrs.c rename to subsys/bluetooth/services/hrs.c index 2a4b1907c83aa4..187575171a5e75 100644 --- a/samples/bluetooth/gatt/hrs.c +++ b/subsys/bluetooth/services/hrs.c @@ -12,9 +12,8 @@ #include #include #include -#include -#include #include +#include #include #include @@ -22,15 +21,20 @@ #include #include +#define LOG_LEVEL CONFIG_BT_GATT_HRS_LOG_LEVEL +#include +LOG_MODULE_REGISTER(hrs); + static struct bt_gatt_ccc_cfg hrmc_ccc_cfg[BT_GATT_CCC_MAX] = {}; -static u8_t simulate_hrm; -static u8_t heartrate = 90U; static u8_t hrs_blsc; -static void hrmc_ccc_cfg_changed(const struct bt_gatt_attr *attr, - u16_t value) +static void hrmc_ccc_cfg_changed(const struct bt_gatt_attr *attr, u16_t value) { - simulate_hrm = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0; + ARG_UNUSED(attr); + + bool notif_enabled = (value == BT_GATT_CCC_NOTIFY); + + LOG_INF("HRS notifications %s", notif_enabled ? "enabled" : "disabled"); } static ssize_t read_blsc(struct bt_conn *conn, const struct bt_gatt_attr *attr, @@ -52,27 +56,26 @@ BT_GATT_SERVICE_DEFINE(hrs_svc, BT_GATT_PERM_NONE, NULL, NULL, NULL), ); -void hrs_init(u8_t blsc) +static int hrs_init(struct device *dev) { - hrs_blsc = blsc; + ARG_UNUSED(dev); + + hrs_blsc = 0x01; + + return 0; } -void hrs_notify(void) +int bt_gatt_hrs_notify(u16_t heartrate) { + int rc; static u8_t hrm[2]; - /* Heartrate measurements simulation */ - if (!simulate_hrm) { - return; - } - - heartrate++; - if (heartrate == 160U) { - heartrate = 90U; - } - hrm[0] = 0x06; /* uint8, sensor contact */ hrm[1] = heartrate; - bt_gatt_notify(NULL, &hrs_svc.attrs[1], &hrm, sizeof(hrm)); + rc = bt_gatt_notify(NULL, &hrs_svc.attrs[1], &hrm, sizeof(hrm)); + + return rc == -ENOTCONN ? 0 : rc; } + +SYS_INIT(hrs_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/tests/bluetooth/bsim_bt/bsim_test_app/CMakeLists.txt b/tests/bluetooth/bsim_bt/bsim_test_app/CMakeLists.txt index 257eac2a1990c6..a9218c3e8b5424 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_app/CMakeLists.txt +++ b/tests/bluetooth/bsim_bt/bsim_test_app/CMakeLists.txt @@ -17,7 +17,6 @@ target_sources(app PRIVATE src/test_empty.c src/test_connect1.c src/test_connect2.c - ../../../../samples/bluetooth/gatt/hrs.c ) zephyr_include_directories( diff --git a/tests/bluetooth/bsim_bt/bsim_test_app/prj.conf b/tests/bluetooth/bsim_bt/bsim_test_app/prj.conf index 998f1c683b91c5..b225ccacfb138b 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_app/prj.conf +++ b/tests/bluetooth/bsim_bt/bsim_test_app/prj.conf @@ -6,6 +6,7 @@ CONFIG_BT_PRIVACY=y CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_BT_GATT_BAS=y +CONFIG_BT_GATT_HRS=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y diff --git a/tests/bluetooth/bsim_bt/bsim_test_app/prj_split.conf b/tests/bluetooth/bsim_bt/bsim_test_app/prj_split.conf index 2d8892d2167587..70031a196c282e 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_app/prj_split.conf +++ b/tests/bluetooth/bsim_bt/bsim_test_app/prj_split.conf @@ -6,6 +6,7 @@ CONFIG_BT_PRIVACY=y CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_BT_GATT_BAS=y +CONFIG_BT_GATT_HRS=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_GATT_CLIENT=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y diff --git a/tests/bluetooth/bsim_bt/bsim_test_app/src/test_connect2.c b/tests/bluetooth/bsim_bt/bsim_test_app/src/test_connect2.c index 2375096464ed70..384b20e768c92b 100644 --- a/tests/bluetooth/bsim_bt/bsim_test_app/src/test_connect2.c +++ b/tests/bluetooth/bsim_bt/bsim_test_app/src/test_connect2.c @@ -23,9 +23,9 @@ #include #include #include -#include +#include -#include +#include static struct bt_conn *default_conn; @@ -108,8 +108,6 @@ static void bt_ready(int err) printk("Bluetooth initialized\n"); - hrs_init(0x01); - err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); if (err) { FAIL("Advertising failed to start (err %d)\n", err); @@ -132,6 +130,19 @@ static void bas_notify(void) bt_gatt_bas_set_battery_level(battery_level); } +static void hrs_notify(void) +{ + static u8_t heartrate = 90U; + + /* Heartrate measurements simulation */ + heartrate++; + if (heartrate == 160U) { + heartrate = 90U; + } + + bt_gatt_hrs_notify(heartrate); +} + static void test_con2_main(void) { static int notify_count; diff --git a/tests/bluetooth/shell/CMakeLists.txt b/tests/bluetooth/shell/CMakeLists.txt index 03f97e2d8aa193..715e6c70d2c75e 100644 --- a/tests/bluetooth/shell/CMakeLists.txt +++ b/tests/bluetooth/shell/CMakeLists.txt @@ -7,4 +7,3 @@ project(bluetooth_shell) zephyr_library_include_directories($ENV{ZEPHYR_BASE}/samples/bluetooth) target_sources(app PRIVATE src/main.c) -target_sources_ifdef(CONFIG_BT_CONN app PRIVATE src/hrs.c) diff --git a/tests/bluetooth/shell/mesh.conf b/tests/bluetooth/shell/mesh.conf index 723848040c24f2..aad65d2cc5cf4f 100644 --- a/tests/bluetooth/shell/mesh.conf +++ b/tests/bluetooth/shell/mesh.conf @@ -17,6 +17,7 @@ CONFIG_SHELL=y CONFIG_BT_SHELL=y CONFIG_BT_DEVICE_NAME="test shell" CONFIG_BT_L2CAP_TX_BUF_COUNT=6 +CONFIG_BT_GATT_HRS=y CONFIG_BT_L2CAP_RX_MTU=69 CONFIG_BT_L2CAP_TX_MTU=69 diff --git a/tests/bluetooth/shell/prj.conf b/tests/bluetooth/shell/prj.conf index 940b728cd2064b..beff3c346e4310 100644 --- a/tests/bluetooth/shell/prj.conf +++ b/tests/bluetooth/shell/prj.conf @@ -21,6 +21,7 @@ CONFIG_BT_DEVICE_NAME_DYNAMIC=y CONFIG_BT_L2CAP_TX_BUF_COUNT=4 CONFIG_BT_ID_MAX=2 CONFIG_BT_GATT_DYNAMIC_DB=y +CONFIG_BT_GATT_HRS=y CONFIG_BT_SETTINGS=y CONFIG_FLASH=y diff --git a/tests/bluetooth/shell/prj_arduino_101.conf b/tests/bluetooth/shell/prj_arduino_101.conf index 82d726a0524e7a..f8109731e8c709 100644 --- a/tests/bluetooth/shell/prj_arduino_101.conf +++ b/tests/bluetooth/shell/prj_arduino_101.conf @@ -8,6 +8,7 @@ CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_GATT_HRS=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y CONFIG_BT_TINYCRYPT_ECC=y CONFIG_SHELL=y diff --git a/tests/bluetooth/shell/prj_br.conf b/tests/bluetooth/shell/prj_br.conf index b4c8fae1b31645..42f663e28378e6 100644 --- a/tests/bluetooth/shell/prj_br.conf +++ b/tests/bluetooth/shell/prj_br.conf @@ -12,6 +12,7 @@ CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_BT_ATT_PREPARE_COUNT=2 CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_GATT_HRS=y CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_DEVICE_NAME="test shell" diff --git a/tests/bluetooth/shell/src/hrs.c b/tests/bluetooth/shell/src/hrs.c deleted file mode 100644 index 9ad7166f5652b4..00000000000000 --- a/tests/bluetooth/shell/src/hrs.c +++ /dev/null @@ -1,2 +0,0 @@ -/* Workaround build system bug that will put objects in source dir */ -#include "../../../../samples/bluetooth/gatt/hrs.c" diff --git a/tests/bluetooth/shell/src/main.c b/tests/bluetooth/shell/src/main.c index aeaae9c36c2085..e02a34e2a04ae0 100644 --- a/tests/bluetooth/shell/src/main.c +++ b/tests/bluetooth/shell/src/main.c @@ -23,11 +23,11 @@ #include -#include +#include #define DEVICE_NAME CONFIG_BT_DEVICE_NAME -#if defined(CONFIG_BT_CONN) +#if defined(CONFIG_BT_GATT_HRS) static bool hrs_simulate; static int cmd_hrs_simulate(const struct shell *shell, @@ -38,7 +38,6 @@ static int cmd_hrs_simulate(const struct shell *shell, if (!hrs_registered) { shell_print(shell, "Registering HRS Service"); - hrs_init(0x01); hrs_registered = true; } @@ -55,17 +54,17 @@ static int cmd_hrs_simulate(const struct shell *shell, return 0; } -#endif /* CONFIG_BT_CONN */ +#endif /* CONFIG_BT_GATT_HRS */ #define HELP_NONE "[none]" #define HELP_ADDR_LE " " SHELL_STATIC_SUBCMD_SET_CREATE(hrs_cmds, -#if defined(CONFIG_BT_CONN) +#if defined(CONFIG_BT_GATT_HRS) SHELL_CMD_ARG(hrs-simulate, NULL, "register and simulate Heart Rate Service ", cmd_hrs_simulate, 2, 0), -#endif /* CONFIG_BT_CONN */ +#endif /* CONFIG_BT_GATT_HRS*/ SHELL_SUBCMD_SET_END ); @@ -79,6 +78,21 @@ static int cmd_hrs(const struct shell *shell, size_t argc, char **argv) SHELL_CMD_ARG_REGISTER(hrs, &hrs_cmds, "Heart Rate Service shell commands", cmd_hrs, 2, 0); +#if defined(CONFIG_BT_GATT_HRS) +static void hrs_notify(void) +{ + static u8_t heartrate = 90U; + + /* Heartrate measurements simulation */ + heartrate++; + if (heartrate == 160U) { + heartrate = 90U; + } + + bt_gatt_hrs_notify(heartrate); +} +#endif /* CONFIG_BT_GATT_HRS */ + void main(void) { printk("Type \"help\" for supported commands."); @@ -88,11 +102,11 @@ void main(void) while (1) { k_sleep(MSEC_PER_SEC); -#if defined(CONFIG_BT_CONN) +#if defined(CONFIG_BT_GATT_HRS) /* Heartrate measurements simulation */ if (hrs_simulate) { hrs_notify(); } -#endif /* CONFIG_BT_CONN */ +#endif /* CONFIG_BT_GATT_HRS */ } }