Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bluetooth: BAS: add battery critical status char to bas service #79966

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions include/zephyr/bluetooth/services/bas.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@
extern "C" {
#endif

/**
* @brief Battery Critical Status Characteristic flags.
*
* Enumeration for the flags indicating the presence
* of various fields in the Battery Critical Status characteristic.
*/
enum bt_bas_bcs_flags {
/** Battery Critical Status Bit 0: Critical Power State */
BT_BAS_BCS_BATTERY_CRITICAL_STATE = BIT(0),

/** Battery Critical Status Bit 1: Immediate Service Required */
BT_BAS_BCS_IMMEDIATE_SERVICE_REQUIRED = BIT(1),
};

/**
* @brief Battery Level Status Characteristic flags.
*
Expand Down
1 change: 1 addition & 0 deletions subsys/bluetooth/services/bas/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: Apache-2.0
zephyr_sources_ifdef(CONFIG_BT_BAS bas.c)
zephyr_sources_ifdef(CONFIG_BT_BAS_BLS bas_bls.c)
zephyr_sources_ifdef(CONFIG_BT_BAS_BCS bas_bcs.c)
5 changes: 5 additions & 0 deletions subsys/bluetooth/services/bas/Kconfig.bas
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,9 @@ config BT_BAS_BLS_ADDITIONAL_STATUS_PRESENT
bool "Additional Battery Status Present"
help
Enable this option if Additional Battery Status information is present.

config BT_BAS_BCS
bool "Battery Critical Status"
help
Enable this option to include Battery Critical Status Characteristic.
endif
6 changes: 6 additions & 0 deletions subsys/bluetooth/services/bas/bas.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ BT_GATT_SERVICE_DEFINE(
BT_GATT_PERM_READ, bt_bas_bls_read_blvl_status, NULL, NULL),
BT_GATT_CCC(blvl_status_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
#endif
#if defined(CONFIG_BT_BAS_BCS)
BT_GATT_CHARACTERISTIC(BT_UUID_BAS_BATTERY_CRIT_STATUS,
BT_GATT_CHRC_READ | BT_GATT_CHRC_INDICATE, BT_GATT_PERM_READ,
bt_bas_bcs_read_critical_status, NULL, NULL),
BT_GATT_CCC(bt_bas_bcs_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
#endif /* CONFIG_BT_BAS_BCS */
);

static int bas_init(void)
Expand Down
98 changes: 98 additions & 0 deletions subsys/bluetooth/services/bas/bas_bcs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2024 Demant A/S
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/bluetooth/services/bas.h>
#include <zephyr/bluetooth/gatt.h>
#include "bas_internal.h"

#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(bas, CONFIG_BT_BAS_LOG_LEVEL);

#define BATTERY_CRITICAL_STATUS_CHAR_IDX 9
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now this is fine, but if you start adding the other optional characteristics, then we can no longer rely on a static index.

An alternative is to use the UUID when calling bt_gatt_indicate which will be futureproof


static uint8_t battery_critical_status;

void bt_bas_bcs_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
ARG_UNUSED(attr);

bool ind_enabled = (value == BT_GATT_CCC_INDICATE);

LOG_DBG("BAS Critical status Indication %s", ind_enabled ? "enabled" : "disabled");
}

ssize_t bt_bas_bcs_read_critical_status(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset)
{

return bt_gatt_attr_read(conn, attr, buf, len, offset, &battery_critical_status,
sizeof(uint8_t));
}

static void bcs_indicate_cb(struct bt_conn *conn, struct bt_gatt_indicate_params *params,
uint8_t err)
{
if (err != 0) {
LOG_DBG("BCS Indication failed with error %u\n", err);
} else {
LOG_DBG("BCS Indication sent successfully\n");
}
}

static void bt_bas_bcs_update_battery_critical_status(void)
{
/* Indicate all connections */
const struct bt_gatt_attr *attr = bt_bas_get_bas_attr(BATTERY_CRITICAL_STATUS_CHAR_IDX);

if (attr) {
uint8_t err;
/* Indicate battery critical status to all connections */
static struct bt_gatt_indicate_params bcs_ind_params;

bcs_ind_params.attr = attr;
bcs_ind_params.data = &battery_critical_status;
bcs_ind_params.len = sizeof(battery_critical_status);
bcs_ind_params.func = bcs_indicate_cb;
err = bt_gatt_indicate(NULL, &bcs_ind_params);
if (err && err != -ENOTCONN) {
LOG_DBG("Failed to send critical status ind to all conns (err %d)\n", err);
}
}
}

void bt_bas_bcs_set_battery_critical_state(bool critical_state)
{
bool current_state = (battery_critical_status & BT_BAS_BCS_BATTERY_CRITICAL_STATE) != 0;

if (current_state == critical_state) {
LOG_DBG("Already battery_critical_state is %d\n", critical_state);
return;
}

if (critical_state) {
battery_critical_status |= BT_BAS_BCS_BATTERY_CRITICAL_STATE;
} else {
battery_critical_status &= ~BT_BAS_BCS_BATTERY_CRITICAL_STATE;
}
bt_bas_bcs_update_battery_critical_status();
}

void bt_bas_bcs_set_immediate_service_required(bool service_required)
{
bool current_state = (battery_critical_status & BT_BAS_BCS_IMMEDIATE_SERVICE_REQUIRED) != 0;

if (current_state == service_required) {
LOG_DBG("Already immediate_service_required is %d\n", service_required);
return;
}

if (service_required) {
battery_critical_status |= BT_BAS_BCS_IMMEDIATE_SERVICE_REQUIRED;
} else {
battery_critical_status &= ~BT_BAS_BCS_IMMEDIATE_SERVICE_REQUIRED;
}
bt_bas_bcs_update_battery_critical_status();
}
28 changes: 28 additions & 0 deletions subsys/bluetooth/services/bas/bas_bls.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,20 @@ void bt_bas_bls_set_battery_charge_level(enum bt_bas_bls_battery_charge_level le
bls.power_state &= ~BATTERY_CHARGE_LEVEL_MASK;
bls.power_state |= (level << BATTERY_CHARGE_LEVEL_SHIFT) & BATTERY_CHARGE_LEVEL_MASK;
bt_bas_bls_update_battery_level_status();

if (IS_ENABLED(CONFIG_BT_BAS_BCS)) {
/*
* Set the BCS Critical Power State bit as per BAS 1.1 specification
* section 3.4.1.1: The BCS Critical Power State bit should be set to true if the
* Battery Charge Level is set to Critical in the Power State field.
*/
if (level == BT_BAS_BLS_CHARGE_LEVEL_CRITICAL) {
bt_bas_bcs_set_battery_critical_state(true);
return;
} else if (level != BT_BAS_BLS_CHARGE_LEVEL_UNKNOWN) {
bt_bas_bcs_set_battery_critical_state(false);
}
}
}

void bt_bas_bls_set_battery_charge_type(enum bt_bas_bls_battery_charge_type type)
Expand Down Expand Up @@ -232,6 +246,20 @@ void bt_bas_bls_set_service_required(enum bt_bas_bls_service_required value)
bls.additional_status &= ~SERVICE_REQUIRED_MASK;
bls.additional_status |= (value << SERVICE_REQUIRED_SHIFT) & SERVICE_REQUIRED_MASK;
bt_bas_bls_update_battery_level_status();

if (IS_ENABLED(CONFIG_BT_BAS_BCS)) {
/*
* Set the BCS Immediate Service Required bit as per BAS 1.1 specification
* section 3.4.1.1: The BCS Immediate Service Required bit should be set to true if
* the service Required bit is set to true in the Additional Status field.
*/
if (value == BT_BAS_BLS_SERVICE_REQUIRED_TRUE) {
bt_bas_bcs_set_immediate_service_required(true);
return;
} else if (value != BT_BAS_BLS_SERVICE_REQUIRED_UNKNOWN) {
bt_bas_bcs_set_immediate_service_required(false);
}
}
}

void bt_bas_bls_set_battery_fault(enum bt_bas_bls_battery_fault value)
Expand Down
39 changes: 39 additions & 0 deletions subsys/bluetooth/services/bas/bas_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,52 @@ struct bt_bas_bls {
*/
void bt_bas_bls_init(void);

/**
* @brief Read the Battery Critical Status characteristic.
*
* @param conn Pointer to the Bluetooth connection object representing the client requesting
* the characteristic.
* @param attr Pointer to the GATT attribute of Battery Critical Status characteristic.
* @param buf Buffer to store the read value.
* @param len Length of the buffer.
* @param offset Offset within the characteristic value to start reading.
*
* @return The number of bytes read and sent to the client, or a negative error code on failure.
*/
ssize_t bt_bas_bcs_read_critical_status(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset);
jhedberg marked this conversation as resolved.
Show resolved Hide resolved

/**
* @brief Callback function for BCS Client Characteristic Configuration changes.
*
*
* @param attr Pointer to the GATT attribute of battery critical status char.
* @param value The new value of the CCC. This value indicates whether
* notifications or indications are enabled or disabled.
*/
void bt_bas_bcs_ccc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value);

/**
* @brief Set the battery level characteristic value.
*
* @param battery_level The new battery level value in percent (0-100).
*/
void bt_bas_bls_set_battery_level(uint8_t battery_level);

/**
* @brief Set the battery critical state flag.
*
* @param critical_state The battery critical state to set (true for critical, false otherwise).
*/
void bt_bas_bcs_set_battery_critical_state(bool critical_state);

/**
* @brief Set the immediate service required flag.
*
* @param service_required The immediate service required status to set.
*/
void bt_bas_bcs_set_immediate_service_required(bool service_required);

/**
* @brief Read the Battery Level Status characteristic.
*
Expand Down
3 changes: 2 additions & 1 deletion tests/bsim/bluetooth/samples/battery_service/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ CONFIG_BT_SMP=y
CONFIG_BT_BAS=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_DEVICE_NAME="bsim_bas"
CONFIG_BT_ATT_TX_COUNT=5
CONFIG_BT_ATT_TX_COUNT=10
Thalley marked this conversation as resolved.
Show resolved Hide resolved

CONFIG_BT_BAS_BLS=y
CONFIG_BT_BAS_BCS=y
CONFIG_BT_BAS_BLS_IDENTIFIER_PRESENT=y
CONFIG_BT_BAS_BLS_BATTERY_LEVEL_PRESENT=y
CONFIG_BT_BAS_BLS_ADDITIONAL_STATUS_PRESENT=y
Loading
Loading