bluetooth: BAS: add battery critical status char to bas service
Added the battery critical status char to bas service as per bas_1.1 spec. Updated BSIM test for BAS service to test the INDs of BAS critical characteristic. Signed-off-by: Nithin Ramesh Myliattil <niym@demant.com>
This commit is contained in:
parent
298c01cb97
commit
b717488be2
10 changed files with 334 additions and 37 deletions
|
@ -26,6 +26,20 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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.
|
* @brief Battery Level Status Characteristic flags.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
zephyr_sources_ifdef(CONFIG_BT_BAS bas.c)
|
zephyr_sources_ifdef(CONFIG_BT_BAS bas.c)
|
||||||
zephyr_sources_ifdef(CONFIG_BT_BAS_BLS bas_bls.c)
|
zephyr_sources_ifdef(CONFIG_BT_BAS_BLS bas_bls.c)
|
||||||
|
zephyr_sources_ifdef(CONFIG_BT_BAS_BCS bas_bcs.c)
|
||||||
|
|
|
@ -27,4 +27,9 @@ config BT_BAS_BLS_ADDITIONAL_STATUS_PRESENT
|
||||||
bool "Additional Battery Status Present"
|
bool "Additional Battery Status Present"
|
||||||
help
|
help
|
||||||
Enable this option if Additional Battery Status information is present.
|
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
|
endif
|
||||||
|
|
|
@ -84,6 +84,12 @@ BT_GATT_SERVICE_DEFINE(
|
||||||
BT_GATT_PERM_READ, bt_bas_bls_read_blvl_status, NULL, NULL),
|
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),
|
BT_GATT_CCC(blvl_status_ccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
|
||||||
#endif
|
#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)
|
static int bas_init(void)
|
||||||
|
|
98
subsys/bluetooth/services/bas/bas_bcs.c
Normal file
98
subsys/bluetooth/services/bas/bas_bcs.c
Normal file
|
@ -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
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
|
@ -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 &= ~BATTERY_CHARGE_LEVEL_MASK;
|
||||||
bls.power_state |= (level << BATTERY_CHARGE_LEVEL_SHIFT) & BATTERY_CHARGE_LEVEL_MASK;
|
bls.power_state |= (level << BATTERY_CHARGE_LEVEL_SHIFT) & BATTERY_CHARGE_LEVEL_MASK;
|
||||||
bt_bas_bls_update_battery_level_status();
|
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)
|
void bt_bas_bls_set_battery_charge_type(enum bt_bas_bls_battery_charge_type type)
|
||||||
|
@ -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 &= ~SERVICE_REQUIRED_MASK;
|
||||||
bls.additional_status |= (value << SERVICE_REQUIRED_SHIFT) & SERVICE_REQUIRED_MASK;
|
bls.additional_status |= (value << SERVICE_REQUIRED_SHIFT) & SERVICE_REQUIRED_MASK;
|
||||||
bt_bas_bls_update_battery_level_status();
|
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)
|
void bt_bas_bls_set_battery_fault(enum bt_bas_bls_battery_fault value)
|
||||||
|
|
|
@ -111,6 +111,31 @@ struct bt_bas_bls {
|
||||||
*/
|
*/
|
||||||
void bt_bas_bls_init(void);
|
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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.
|
* @brief Set the battery level characteristic value.
|
||||||
*
|
*
|
||||||
|
@ -118,6 +143,20 @@ void bt_bas_bls_init(void);
|
||||||
*/
|
*/
|
||||||
void bt_bas_bls_set_battery_level(uint8_t battery_level);
|
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.
|
* @brief Read the Battery Level Status characteristic.
|
||||||
*
|
*
|
||||||
|
|
|
@ -6,9 +6,10 @@ CONFIG_BT_SMP=y
|
||||||
CONFIG_BT_BAS=y
|
CONFIG_BT_BAS=y
|
||||||
CONFIG_BT_GATT_CLIENT=y
|
CONFIG_BT_GATT_CLIENT=y
|
||||||
CONFIG_BT_DEVICE_NAME="bsim_bas"
|
CONFIG_BT_DEVICE_NAME="bsim_bas"
|
||||||
CONFIG_BT_ATT_TX_COUNT=5
|
CONFIG_BT_ATT_TX_COUNT=10
|
||||||
|
|
||||||
CONFIG_BT_BAS_BLS=y
|
CONFIG_BT_BAS_BLS=y
|
||||||
|
CONFIG_BT_BAS_BCS=y
|
||||||
CONFIG_BT_BAS_BLS_IDENTIFIER_PRESENT=y
|
CONFIG_BT_BAS_BLS_IDENTIFIER_PRESENT=y
|
||||||
CONFIG_BT_BAS_BLS_BATTERY_LEVEL_PRESENT=y
|
CONFIG_BT_BAS_BLS_BATTERY_LEVEL_PRESENT=y
|
||||||
CONFIG_BT_BAS_BLS_ADDITIONAL_STATUS_PRESENT=y
|
CONFIG_BT_BAS_BLS_ADDITIONAL_STATUS_PRESENT=y
|
||||||
|
|
|
@ -43,6 +43,7 @@ static struct bt_gatt_discover_params discover_params;
|
||||||
|
|
||||||
static struct bt_gatt_subscribe_params battery_level_notify_params;
|
static struct bt_gatt_subscribe_params battery_level_notify_params;
|
||||||
static struct bt_gatt_subscribe_params battery_level_status_sub_params;
|
static struct bt_gatt_subscribe_params battery_level_status_sub_params;
|
||||||
|
static struct bt_gatt_subscribe_params battery_critical_status_sub_params;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Battery Service test:
|
* Battery Service test:
|
||||||
|
@ -58,6 +59,56 @@ static struct bt_gatt_subscribe_params battery_level_status_sub_params;
|
||||||
|
|
||||||
static DEFINE_FLAG(notification_count_reached);
|
static DEFINE_FLAG(notification_count_reached);
|
||||||
static DEFINE_FLAG(indication_count_reached);
|
static DEFINE_FLAG(indication_count_reached);
|
||||||
|
static DEFINE_FLAG(bcs_char_read);
|
||||||
|
|
||||||
|
/* Callback for handling Battery Critical Status Read Response */
|
||||||
|
static uint8_t battery_critical_status_read_cb(struct bt_conn *conn, uint8_t err,
|
||||||
|
struct bt_gatt_read_params *params, const void *data,
|
||||||
|
uint16_t length)
|
||||||
|
{
|
||||||
|
TEST_ASSERT(err == 0, "Failed to read Battery critical status (err %d)", err);
|
||||||
|
TEST_ASSERT(length > 0, "No data is sent");
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
uint8_t status_byte = *(uint8_t *)data;
|
||||||
|
|
||||||
|
printk("[READ] BAS Critical Status:\n");
|
||||||
|
printk("Battery state: %s\n",
|
||||||
|
(status_byte & BT_BAS_BCS_BATTERY_CRITICAL_STATE) ? "Critical" : "Normal");
|
||||||
|
printk("Immediate service: %s\n",
|
||||||
|
(status_byte & BT_BAS_BCS_IMMEDIATE_SERVICE_REQUIRED) ? "Required"
|
||||||
|
: "Not Required");
|
||||||
|
}
|
||||||
|
SET_FLAG(bcs_char_read);
|
||||||
|
return BT_GATT_ITER_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_gatt_read_params read_bcs_params = {
|
||||||
|
.func = battery_critical_status_read_cb,
|
||||||
|
.by_uuid.uuid = BT_UUID_BAS_BATTERY_CRIT_STATUS,
|
||||||
|
.by_uuid.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE,
|
||||||
|
.by_uuid.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Callback for handling Battery Level Read Response */
|
||||||
|
static uint8_t battery_level_read_cb(struct bt_conn *conn, uint8_t err,
|
||||||
|
struct bt_gatt_read_params *params, const void *data,
|
||||||
|
uint16_t length)
|
||||||
|
{
|
||||||
|
TEST_ASSERT(err == 0, "Failed to read Battery Level (err %d)", err);
|
||||||
|
if (data) {
|
||||||
|
LOG_DBG("[READ] BAS Battery Level: %d%%\n", *(const uint8_t *)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BT_GATT_ITER_STOP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct bt_gatt_read_params read_blvl_params = {
|
||||||
|
.func = battery_level_read_cb,
|
||||||
|
.by_uuid.uuid = BT_UUID_BAS_BATTERY_LEVEL_STATUS,
|
||||||
|
.by_uuid.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE,
|
||||||
|
.by_uuid.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE,
|
||||||
|
};
|
||||||
|
|
||||||
extern enum bst_result_t bst_result;
|
extern enum bst_result_t bst_result;
|
||||||
|
|
||||||
|
@ -91,19 +142,6 @@ static uint8_t battery_level_notify_cb(struct bt_conn *conn,
|
||||||
return BT_GATT_ITER_CONTINUE;
|
return BT_GATT_ITER_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback for handling Battery Level Read Response */
|
|
||||||
static uint8_t battery_level_read_cb(struct bt_conn *conn, uint8_t err,
|
|
||||||
struct bt_gatt_read_params *params, const void *data,
|
|
||||||
uint16_t length)
|
|
||||||
{
|
|
||||||
TEST_ASSERT(err == 0, "Failed to read Battery Level (err %d)", err);
|
|
||||||
if (data) {
|
|
||||||
LOG_DBG("[READ] BAS Battery Level: %d%%\n", *(const uint8_t *)data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return BT_GATT_ITER_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool parse_battery_level_status(const uint8_t *data, uint16_t length)
|
static bool parse_battery_level_status(const uint8_t *data, uint16_t length)
|
||||||
{
|
{
|
||||||
/* Check minimum length for parsing flags and power state */
|
/* Check minimum length for parsing flags and power state */
|
||||||
|
@ -311,6 +349,25 @@ static bool parse_battery_level_status(const uint8_t *data, uint16_t length)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned char battery_critical_status_indicate_cb(struct bt_conn *conn,
|
||||||
|
struct bt_gatt_subscribe_params *params,
|
||||||
|
const void *data, uint16_t length)
|
||||||
|
{
|
||||||
|
if (!data) {
|
||||||
|
LOG_INF("BAS critical status indication disabled\n");
|
||||||
|
} else {
|
||||||
|
uint8_t status_byte = ((uint8_t *)data)[0];
|
||||||
|
|
||||||
|
printk("[INDICATION] BAS Critical Status:\n");
|
||||||
|
printk("Battery state: %s\n",
|
||||||
|
(status_byte & BT_BAS_BCS_BATTERY_CRITICAL_STATE) ? "Critical" : "Normal");
|
||||||
|
printk("Immediate service: %s\n",
|
||||||
|
(status_byte & BT_BAS_BCS_IMMEDIATE_SERVICE_REQUIRED) ? "Required"
|
||||||
|
: "Not Required");
|
||||||
|
}
|
||||||
|
return BT_GATT_ITER_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned char battery_level_status_indicate_cb(struct bt_conn *conn,
|
static unsigned char battery_level_status_indicate_cb(struct bt_conn *conn,
|
||||||
struct bt_gatt_subscribe_params *params,
|
struct bt_gatt_subscribe_params *params,
|
||||||
const void *data, uint16_t length)
|
const void *data, uint16_t length)
|
||||||
|
@ -367,27 +424,13 @@ static uint8_t battery_level_status_notify_cb(struct bt_conn *conn,
|
||||||
return BT_GATT_ITER_CONTINUE;
|
return BT_GATT_ITER_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void read_battery_level(const struct bt_gatt_attr *attr)
|
|
||||||
{
|
|
||||||
/* Read the battery level after subscribing */
|
|
||||||
static struct bt_gatt_read_params read_params;
|
|
||||||
|
|
||||||
read_params.func = battery_level_read_cb;
|
|
||||||
read_params.handle_count = 1;
|
|
||||||
read_params.single.handle = bt_gatt_attr_get_handle(attr);
|
|
||||||
read_params.single.offset = 0;
|
|
||||||
bt_gatt_read(default_conn, &read_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void subscribe_battery_level(const struct bt_gatt_attr *attr)
|
static void subscribe_battery_level(const struct bt_gatt_attr *attr)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
struct bt_gatt_attr *ccc_attr = bt_gatt_find_by_uuid(attr, 0, BT_UUID_GATT_CCC);
|
||||||
|
|
||||||
battery_level_notify_params = (struct bt_gatt_subscribe_params){
|
battery_level_notify_params = (struct bt_gatt_subscribe_params){
|
||||||
/* In Zephyr, it is common practice for the CCC handle
|
.ccc_handle = bt_gatt_attr_get_handle(ccc_attr),
|
||||||
* to be positioned two handles after the characteristic handle.
|
|
||||||
*/
|
|
||||||
.ccc_handle = bt_gatt_attr_get_handle(attr) + 2,
|
|
||||||
.value_handle = bt_gatt_attr_value_handle(attr),
|
.value_handle = bt_gatt_attr_value_handle(attr),
|
||||||
.value = BT_GATT_CCC_NOTIFY,
|
.value = BT_GATT_CCC_NOTIFY,
|
||||||
.notify = battery_level_notify_cb,
|
.notify = battery_level_notify_cb,
|
||||||
|
@ -399,26 +442,53 @@ static void subscribe_battery_level(const struct bt_gatt_attr *attr)
|
||||||
} else {
|
} else {
|
||||||
LOG_DBG("Battery level [SUBSCRIBED]\n");
|
LOG_DBG("Battery level [SUBSCRIBED]\n");
|
||||||
}
|
}
|
||||||
read_battery_level(attr);
|
|
||||||
|
err = bt_gatt_read(default_conn, &read_blvl_params);
|
||||||
|
if (err != 0) {
|
||||||
|
TEST_FAIL("Battery Level Read failed (err %d)\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void subscribe_battery_critical_status(const struct bt_gatt_attr *attr)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct bt_gatt_attr *ccc_attr = bt_gatt_find_by_uuid(attr, 0, BT_UUID_GATT_CCC);
|
||||||
|
|
||||||
|
battery_critical_status_sub_params = (struct bt_gatt_subscribe_params){
|
||||||
|
.ccc_handle = bt_gatt_attr_get_handle(ccc_attr),
|
||||||
|
.value_handle = bt_gatt_attr_value_handle(attr),
|
||||||
|
.value = BT_GATT_CCC_INDICATE,
|
||||||
|
.notify = battery_critical_status_indicate_cb,
|
||||||
|
};
|
||||||
|
|
||||||
|
err = bt_gatt_subscribe(default_conn, &battery_critical_status_sub_params);
|
||||||
|
if (err && err != -EALREADY) {
|
||||||
|
TEST_FAIL("Subscribe failed (err %d)\n", err);
|
||||||
|
} else {
|
||||||
|
LOG_DBG("Battery critical status [SUBSCRIBED]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bt_gatt_read(default_conn, &read_bcs_params);
|
||||||
|
if (err != 0) {
|
||||||
|
TEST_FAIL("Battery Critical Status Read failed (err %d)\n", err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subscribe_battery_level_status(const struct bt_gatt_attr *attr)
|
static void subscribe_battery_level_status(const struct bt_gatt_attr *attr)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
struct bt_gatt_attr *ccc_attr = bt_gatt_find_by_uuid(attr, 0, BT_UUID_GATT_CCC);
|
||||||
|
|
||||||
if (get_device_nbr() == 1) { /* One device for Indication */
|
if (get_device_nbr() == 1) { /* One device for Indication */
|
||||||
battery_level_status_sub_params = (struct bt_gatt_subscribe_params){
|
battery_level_status_sub_params = (struct bt_gatt_subscribe_params){
|
||||||
/* In Zephyr, it is common practice for the CCC handle
|
.ccc_handle = bt_gatt_attr_get_handle(ccc_attr),
|
||||||
* to be positioned two handles after the characteristic handle.
|
|
||||||
*/
|
|
||||||
.ccc_handle = bt_gatt_attr_get_handle(attr) + 2,
|
|
||||||
.value_handle = bt_gatt_attr_value_handle(attr),
|
.value_handle = bt_gatt_attr_value_handle(attr),
|
||||||
.value = BT_GATT_CCC_INDICATE,
|
.value = BT_GATT_CCC_INDICATE,
|
||||||
.notify = battery_level_status_indicate_cb,
|
.notify = battery_level_status_indicate_cb,
|
||||||
};
|
};
|
||||||
} else { /* Other device for Notification */
|
} else { /* Other device for Notification */
|
||||||
battery_level_status_sub_params = (struct bt_gatt_subscribe_params){
|
battery_level_status_sub_params = (struct bt_gatt_subscribe_params){
|
||||||
.ccc_handle = bt_gatt_attr_get_handle(attr) + 2,
|
.ccc_handle = bt_gatt_attr_get_handle(ccc_attr),
|
||||||
.value_handle = bt_gatt_attr_value_handle(attr),
|
.value_handle = bt_gatt_attr_value_handle(attr),
|
||||||
.value = BT_GATT_CCC_NOTIFY,
|
.value = BT_GATT_CCC_NOTIFY,
|
||||||
.notify = battery_level_status_notify_cb,
|
.notify = battery_level_status_notify_cb,
|
||||||
|
@ -474,6 +544,19 @@ static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *at
|
||||||
} else if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_BAS_BATTERY_LEVEL_STATUS)) {
|
} else if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_BAS_BATTERY_LEVEL_STATUS)) {
|
||||||
LOG_DBG("Subscribe Batterry Level Status Char\n");
|
LOG_DBG("Subscribe Batterry Level Status Char\n");
|
||||||
subscribe_battery_level_status(attr);
|
subscribe_battery_level_status(attr);
|
||||||
|
|
||||||
|
memcpy(&uuid, BT_UUID_BAS_BATTERY_CRIT_STATUS, sizeof(uuid));
|
||||||
|
discover_params.uuid = &uuid.uuid;
|
||||||
|
discover_params.start_handle = attr->handle + 1;
|
||||||
|
discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||||
|
|
||||||
|
err = bt_gatt_discover(conn, &discover_params);
|
||||||
|
if (err) {
|
||||||
|
TEST_FAIL("Discover failed (err %d)\n", err);
|
||||||
|
}
|
||||||
|
} else if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_BAS_BATTERY_CRIT_STATUS)) {
|
||||||
|
LOG_DBG("Subscribe Batterry Critical Status Char\n");
|
||||||
|
subscribe_battery_critical_status(attr);
|
||||||
}
|
}
|
||||||
return BT_GATT_ITER_STOP;
|
return BT_GATT_ITER_STOP;
|
||||||
}
|
}
|
||||||
|
@ -531,12 +614,26 @@ static void test_bas_central_main(void)
|
||||||
WAIT_FOR_FLAG(notification_count_reached);
|
WAIT_FOR_FLAG(notification_count_reached);
|
||||||
LOG_INF("Notification Count Reached!");
|
LOG_INF("Notification Count Reached!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bk_sync_send only works between two devices in a simulation, with IDs 0 and 1. */
|
/* bk_sync_send only works between two devices in a simulation, with IDs 0 and 1. */
|
||||||
if (get_device_nbr() == 1) {
|
if (get_device_nbr() == 1) {
|
||||||
bk_sync_send();
|
bk_sync_send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printk("Read BCS once peripheral sets BLS Addl Status Service Required Flag to false\n");
|
||||||
|
|
||||||
|
UNSET_FLAG(bcs_char_read);
|
||||||
|
|
||||||
|
err = bt_gatt_read(default_conn, &read_bcs_params);
|
||||||
|
if (err != 0) {
|
||||||
|
TEST_FAIL("Battery Critical Status Read failed (err %d)\n", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
WAIT_FOR_FLAG(bcs_char_read);
|
||||||
|
|
||||||
|
if (get_device_nbr() == 1) {
|
||||||
|
bk_sync_send();
|
||||||
|
}
|
||||||
|
|
||||||
bst_result = Passed;
|
bst_result = Passed;
|
||||||
TEST_PASS("Central Test Passed");
|
TEST_PASS("Central Test Passed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,6 +160,14 @@ static void test_bas_peripheral_main(void)
|
||||||
/* Main thread waits for the sync signal from other device */
|
/* Main thread waits for the sync signal from other device */
|
||||||
bk_sync_wait();
|
bk_sync_wait();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Once BLS Additional status service required flag is set to false,
|
||||||
|
* BCS Immediate service flag is also set to false. BCS char is
|
||||||
|
* read from central.
|
||||||
|
*/
|
||||||
|
bt_bas_bls_set_service_required(BT_BAS_BLS_SERVICE_REQUIRED_FALSE);
|
||||||
|
bk_sync_wait();
|
||||||
|
|
||||||
bst_result = Passed;
|
bst_result = Passed;
|
||||||
TEST_PASS_AND_EXIT("Peripheral Test Passed");
|
TEST_PASS_AND_EXIT("Peripheral Test Passed");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue