diff --git a/include/zephyr/bluetooth/services/hrs.h b/include/zephyr/bluetooth/services/hrs.h index 097998f5caf..f19b2924ce0 100644 --- a/include/zephyr/bluetooth/services/hrs.h +++ b/include/zephyr/bluetooth/services/hrs.h @@ -19,10 +19,50 @@ #include +#include + #ifdef __cplusplus extern "C" { #endif +/** @brief Heart rate service callback structure */ +struct bt_hrs_cb { + /** @brief Heart rate notifications changed + * + * @param enabled Flag that is true if notifications were enabled, false + * if they were disabled. + */ + void (*ntf_changed)(bool enabled); + + /** Internal member to form a list of callbacks */ + sys_snode_t _node; +}; + +/** @brief Heart rate service callback register + * + * This function will register callbacks that will be called in + * certain events related to Heart rate service. + * + * @param cb Pointer to callbacks structure. Must point to memory that remains valid + * until unregistered. + * + * @return 0 on success + * @return -EINVAL in case @p cb is NULL + */ +int bt_hrs_cb_register(struct bt_hrs_cb *cb); + +/** @brief Heart rate service callback unregister + * + * This function will unregister callback from Heart rate service. + * + * @param cb Pointer to callbacks structure + * + * @return 0 on success + * @return -EINVAL in case @p cb is NULL + * @return -ENOENT in case the @p cb was not found in registered callbacks + */ +int bt_hrs_cb_unregister(struct bt_hrs_cb *cb); + /** @brief Notify heart rate measurement. * * This will send a GATT notification to all current subscribers. diff --git a/subsys/bluetooth/services/hrs.c b/subsys/bluetooth/services/hrs.c index 013591516a1..875129ac185 100644 --- a/subsys/bluetooth/services/hrs.c +++ b/subsys/bluetooth/services/hrs.c @@ -14,12 +14,14 @@ #include #include #include +#include #include #include #include #include #include +#include #define LOG_LEVEL CONFIG_BT_HRS_LOG_LEVEL #include @@ -51,14 +53,23 @@ LOG_MODULE_REGISTER(hrs); (BT_GATT_PERM_READ | BT_GATT_PERM_WRITE)) \ static uint8_t hrs_blsc; +static sys_slist_t hrs_cbs = SYS_SLIST_STATIC_INIT(&hrs_cbs); static void hrmc_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value) { ARG_UNUSED(attr); + struct bt_hrs_cb *listener; + bool notif_enabled = (value == BT_GATT_CCC_NOTIFY); LOG_INF("HRS notifications %s", notif_enabled ? "enabled" : "disabled"); + + SYS_SLIST_FOR_EACH_CONTAINER(&hrs_cbs, listener, _node) { + if (listener->ntf_changed) { + listener->ntf_changed(notif_enabled); + } + } } static ssize_t read_blsc(struct bt_conn *conn, const struct bt_gatt_attr *attr, @@ -91,6 +102,30 @@ static int hrs_init(void) return 0; } +int bt_hrs_cb_register(struct bt_hrs_cb *cb) +{ + CHECKIF(cb == NULL) { + return -EINVAL; + } + + sys_slist_append(&hrs_cbs, &cb->_node); + + return 0; +} + +int bt_hrs_cb_unregister(struct bt_hrs_cb *cb) +{ + CHECKIF(cb == NULL) { + return -EINVAL; + } + + if (!sys_slist_find_and_remove(&hrs_cbs, &cb->_node)) { + return -ENOENT; + } + + return 0; +} + int bt_hrs_notify(uint16_t heartrate) { int rc;