Skip to content

Commit

Permalink
Bluetooth: Add support for Path Loss Monitoring feature
Browse files Browse the repository at this point in the history
This commit adds host support for the Path Loss Monitoring
feature see Bluetooth Core specification, Version 5.4,
Vol 6, Part B, Section 4.6.32.

Limited logic is required, just adding a wrapper around the
HCI command and callback for HCI event.

Add new zone - BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE, to
convert 0xFF path loss to a useful zone.

Add new Kconfigs and functionality to the bt shell.

Signed-off-by: Sean Madigan <[email protected]>
  • Loading branch information
sean-madigan authored and aescolar committed Jun 7, 2024
1 parent 9e2c773 commit 0b327db
Show file tree
Hide file tree
Showing 8 changed files with 350 additions and 0 deletions.
93 changes: 93 additions & 0 deletions include/zephyr/bluetooth/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,57 @@ struct bt_conn_le_tx_power_report {
int8_t delta;
};

/** @brief Path Loss zone that has been entered.
*
* The path loss zone that has been entered in the most recent LE Path Loss Monitoring
* Threshold Change event as documented in Core Spec. Version 5.4 Vol.4, Part E, 7.7.65.32.
*
* @note BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE has been added to notify when path loss becomes
* unavailable.
*/
enum bt_conn_le_path_loss_zone {
/** Low path loss zone entered. */
BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_LOW,
/** Middle path loss zone entered. */
BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_MIDDLE,
/** High path loss zone entered. */
BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_HIGH,
/** Path loss has become unavailable. */
BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE,
};

BUILD_ASSERT(BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_LOW == BT_HCI_LE_ZONE_ENTERED_LOW);
BUILD_ASSERT(BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_MIDDLE == BT_HCI_LE_ZONE_ENTERED_MIDDLE);
BUILD_ASSERT(BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_HIGH == BT_HCI_LE_ZONE_ENTERED_HIGH);

/** @brief LE Path Loss Monitoring Threshold Change Report Structure. */
struct bt_conn_le_path_loss_threshold_report {

/** Path Loss zone as documented in Core Spec. Version 5.4 Vol.4, Part E, 7.7.65.32. */
enum bt_conn_le_path_loss_zone zone;

/** Current path loss (dB). */
uint8_t path_loss;
};

/** @brief LE Path Loss Monitoring Parameters Structure as defined in Core Spec. Version 5.4
* Vol.4, Part E, 7.8.119 LE Set Path Loss Reporting Parameters command.
*/
struct bt_conn_le_path_loss_reporting_param {
/** High threshold for the path loss (dB). */
uint8_t high_threshold;
/** Hysteresis value for the high threshold (dB). */
uint8_t high_hysteresis;
/** Low threshold for the path loss (dB). */
uint8_t low_threshold;
/** Hysteresis value for the low threshold (dB). */
uint8_t low_hysteresis;
/** Minimum time in number of connection events to be observed once the
* path loss crosses the threshold before an event is generated.
*/
uint16_t min_time_spent;
};

/** @brief Passkey Keypress Notification type
*
* The numeric values are the same as in the Core specification for Pairing
Expand Down Expand Up @@ -601,6 +652,34 @@ int bt_conn_le_set_tx_power_report_enable(struct bt_conn *conn,
bool local_enable,
bool remote_enable);

/** @brief Set Path Loss Monitoring Parameters.
*
* Change the configuration for path loss threshold change events for a given conn handle.
*
* @note To use this API @kconfig{CONFIG_BT_PATH_LOSS_MONITORING} must be set.
*
* @param conn Connection object.
* @param param Path Loss Monitoring parameters
*
* @return Zero on success or (negative) error code on failure.
*/
int bt_conn_le_set_path_loss_mon_param(struct bt_conn *conn,
const struct bt_conn_le_path_loss_reporting_param *param);

/** @brief Enable or Disable Path Loss Monitoring.
*
* Enable or disable Path Loss Monitoring, which will decide whether Path Loss Threshold events
* are sent from the controller to the host.
*
* @note To use this API @kconfig{CONFIG_BT_PATH_LOSS_MONITORING} must be set.
*
* @param conn Connection Object.
* @param enable Enable/disable path loss reporting.
*
* @return Zero on success or (negative) error code on failure.
*/
int bt_conn_le_set_path_loss_mon_enable(struct bt_conn *conn, bool enable);

/** @brief Update the connection parameters.
*
* If the local device is in the peripheral role then updating the connection
Expand Down Expand Up @@ -1154,6 +1233,20 @@ struct bt_conn_cb {
const struct bt_conn_le_tx_power_report *report);
#endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */

#if defined(CONFIG_BT_PATH_LOSS_MONITORING)
/** @brief LE Path Loss Threshold event.
*
* This callback notifies the application that there has been a path loss threshold
* crossing or reporting the initial path loss threshold zone after using
* @ref bt_conn_le_set_path_loss_mon_enable.
*
* @param conn Connection object.
* @param report Path loss threshold report.
*/
void (*path_loss_threshold_report)(struct bt_conn *conn,
const struct bt_conn_le_path_loss_threshold_report *report);
#endif /* CONFIG_BT_PATH_LOSS_MONITORING */

struct bt_conn_cb *_next;
};

Expand Down
32 changes: 32 additions & 0 deletions include/zephyr/bluetooth/hci_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,26 @@ struct bt_hci_cp_le_set_tx_power_report_enable {
uint8_t remote_enable;
} __packed;

struct bt_hci_cp_le_set_path_loss_reporting_parameters {
uint16_t handle;
uint8_t high_threshold;
uint8_t high_hysteresis;
uint8_t low_threshold;
uint8_t low_hysteresis;
uint16_t min_time_spent;
} __packed;

struct bt_hci_cp_le_set_path_loss_reporting_enable {
uint16_t handle;
uint8_t enable;
} __packed;

#define BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS BT_OP(BT_OGF_LE, 0x0078) /* 0x2078 */

#define BT_HCI_LE_PATH_LOSS_REPORTING_DISABLE 0x00
#define BT_HCI_LE_PATH_LOSS_REPORTING_ENABLE 0x01
#define BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE BT_OP(BT_OGF_LE, 0x0079) /* 0x2079 */

#define BT_HCI_CTL_TO_HOST_FLOW_DISABLE 0x00
#define BT_HCI_CTL_TO_HOST_FLOW_ENABLE 0x01
#define BT_HCI_OP_SET_CTL_TO_HOST_FLOW BT_OP(BT_OGF_BASEBAND, 0x0031) /* 0x0c31 */
Expand Down Expand Up @@ -3020,6 +3040,18 @@ struct bt_hci_evt_le_req_peer_sca_complete {
uint8_t sca;
} __packed;

#define BT_HCI_LE_ZONE_ENTERED_LOW 0x0
#define BT_HCI_LE_ZONE_ENTERED_MIDDLE 0x1
#define BT_HCI_LE_ZONE_ENTERED_HIGH 0x2
#define BT_HCI_LE_PATH_LOSS_UNAVAILABLE 0xFF

#define BT_HCI_EVT_LE_PATH_LOSS_THRESHOLD 0x20
struct bt_hci_evt_le_path_loss_threshold {
uint16_t handle;
uint8_t current_path_loss;
uint8_t zone_entered;
} __packed;

/** Reason for Transmit power reporting.
*/
/* Local Transmit power changed. */
Expand Down
7 changes: 7 additions & 0 deletions subsys/bluetooth/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,13 @@ config BT_TRANSMIT_POWER_CONTROL
Enable support for LE Power Control Request feature that is defined in the
Bluetooth Core specification, Version 5.4 | Vol 6, Part B, Section 4.6.31.

config BT_PATH_LOSS_MONITORING
bool "LE Path Loss Monitoring"
depends on !BT_CTLR || BT_CTLR_LE_PATH_LOSS_MONITORING_SUPPORT
help
Enable support for LE Path Loss Monitoring feature that is defined in the
Bluetooth Core specification, Version 5.4 | Vol 6, Part B, Section 4.6.32.

endif # BT_CONN

rsource "Kconfig.iso"
Expand Down
12 changes: 12 additions & 0 deletions subsys/bluetooth/controller/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ config BT_CTLR_READ_ISO_LINK_QUALITY_SUPPORT
config BT_CTLR_LE_POWER_CONTROL_SUPPORT
bool

config BT_CTLR_LE_PATH_LOSS_MONITORING_SUPPORT
depends on BT_CTLR_LE_POWER_CONTROL_SUPPORT
bool

config BT_CTLR
bool "Bluetooth Controller"
help
Expand Down Expand Up @@ -550,6 +554,14 @@ config BT_CTLR_LE_POWER_CONTROL
Enable support for LE Power Control Request feature that is defined in the
Bluetooth Core specification, Version 5.4 | Vol 6, Part B, Section 4.6.31.

config BT_CTLR_LE_PATH_LOSS_MONITORING
bool "LE Path Loss Monitoring Feature"
depends on BT_CTLR_LE_PATH_LOSS_MONITORING_SUPPORT
default y if BT_PATH_LOSS_MONITORING
help
Enable support for LE Path Loss Monitoring feature that is defined in the
Bluetooth Core specification, Version 5.4 | Vol 6, Part B, Section 4.6.32.

endif # BT_CONN

config BT_CTLR_FILTER_ACCEPT_LIST
Expand Down
59 changes: 59 additions & 0 deletions subsys/bluetooth/host/conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -2884,6 +2884,65 @@ int bt_conn_le_get_tx_power_level(struct bt_conn *conn,
return err;
}

#if defined(CONFIG_BT_PATH_LOSS_MONITORING)
void notify_path_loss_threshold_report(struct bt_conn *conn,
struct bt_conn_le_path_loss_threshold_report report)
{
for (struct bt_conn_cb *cb = callback_list; cb; cb = cb->_next) {
if (cb->path_loss_threshold_report) {
cb->path_loss_threshold_report(conn, &report);
}
}

STRUCT_SECTION_FOREACH(bt_conn_cb, cb)
{
if (cb->path_loss_threshold_report) {
cb->path_loss_threshold_report(conn, &report);
}
}
}

int bt_conn_le_set_path_loss_mon_param(struct bt_conn *conn,
const struct bt_conn_le_path_loss_reporting_param *params)
{
struct bt_hci_cp_le_set_path_loss_reporting_parameters *cp;
struct net_buf *buf;

buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS, sizeof(*cp));
if (!buf) {
return -ENOBUFS;
}

cp = net_buf_add(buf, sizeof(*cp));
cp->handle = sys_cpu_to_le16(conn->handle);
cp->high_threshold = params->high_threshold;
cp->high_hysteresis = params->high_hysteresis;
cp->low_threshold = params->low_threshold;
cp->low_hysteresis = params->low_hysteresis;
cp->min_time_spent = sys_cpu_to_le16(params->min_time_spent);

return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS, buf, NULL);
}

int bt_conn_le_set_path_loss_mon_enable(struct bt_conn *conn, bool reporting_enable)
{
struct bt_hci_cp_le_set_path_loss_reporting_enable *cp;
struct net_buf *buf;

buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE, sizeof(*cp));
if (!buf) {
return -ENOBUFS;
}

cp = net_buf_add(buf, sizeof(*cp));
cp->handle = sys_cpu_to_le16(conn->handle);
cp->enable = reporting_enable ? BT_HCI_LE_PATH_LOSS_REPORTING_ENABLE :
BT_HCI_LE_PATH_LOSS_REPORTING_DISABLE;

return bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE, buf, NULL);
}
#endif /* CONFIG_BT_PATH_LOSS_MONITORING */

int bt_conn_le_param_update(struct bt_conn *conn,
const struct bt_le_conn_param *param)
{
Expand Down
3 changes: 3 additions & 0 deletions subsys/bluetooth/host/conn_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,9 @@ bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param);
void notify_tx_power_report(struct bt_conn *conn,
struct bt_conn_le_tx_power_report report);

void notify_path_loss_threshold_report(struct bt_conn *conn,
struct bt_conn_le_path_loss_threshold_report report);

#if defined(CONFIG_BT_SMP)
/* If role specific LTK is present */
bool bt_conn_ltk_present(const struct bt_conn *conn);
Expand Down
44 changes: 44 additions & 0 deletions subsys/bluetooth/host/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2514,6 +2514,42 @@ void bt_hci_le_transmit_power_report(struct net_buf *buf)
}
#endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */

#if defined(CONFIG_BT_PATH_LOSS_MONITORING)
void bt_hci_le_path_loss_threshold_event(struct net_buf *buf)
{
struct bt_hci_evt_le_path_loss_threshold *evt;
struct bt_conn_le_path_loss_threshold_report report;
struct bt_conn *conn;

evt = net_buf_pull_mem(buf, sizeof(*evt));

if (evt->zone_entered > BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_HIGH) {
LOG_ERR("Invalid zone %u in bt_hci_evt_le_path_loss_threshold",
evt->zone_entered);
return;
}

conn = bt_conn_lookup_handle(sys_le16_to_cpu(evt->handle), BT_CONN_TYPE_LE);
if (!conn) {
LOG_ERR("Unknown conn handle 0x%04X for path loss threshold report",
sys_le16_to_cpu(evt->handle));
return;
}

if (evt->current_path_loss == BT_HCI_LE_PATH_LOSS_UNAVAILABLE) {
report.zone = BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE;
report.path_loss = BT_HCI_LE_PATH_LOSS_UNAVAILABLE;
} else {
report.zone = evt->zone_entered;
report.path_loss = evt->current_path_loss;
}

notify_path_loss_threshold_report(conn, report);

bt_conn_unref(conn);
}
#endif /* CONFIG_BT_PATH_LOSS_MONITORING */

static const struct event_handler vs_events[] = {
#if defined(CONFIG_BT_DF_VS_CL_IQ_REPORT_16_BITS_IQ_SAMPLES)
EVENT_HANDLER(BT_HCI_EVT_VS_LE_CONNECTIONLESS_IQ_REPORT,
Expand Down Expand Up @@ -2663,6 +2699,10 @@ static const struct event_handler meta_events[] = {
EVENT_HANDLER(BT_HCI_EVT_LE_TRANSMIT_POWER_REPORT, bt_hci_le_transmit_power_report,
sizeof(struct bt_hci_evt_le_transmit_power_report)),
#endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */
#if defined(CONFIG_BT_PATH_LOSS_MONITORING)
EVENT_HANDLER(BT_HCI_EVT_LE_PATH_LOSS_THRESHOLD, bt_hci_le_path_loss_threshold_event,
sizeof(struct bt_hci_evt_le_path_loss_threshold)),
#endif /* CONFIG_BT_PATH_LOSS_MONITORING */
#if defined(CONFIG_BT_PER_ADV_SYNC_RSP)
EVENT_HANDLER(BT_HCI_EVT_LE_PER_ADVERTISING_REPORT_V2, bt_hci_le_per_adv_report_v2,
sizeof(struct bt_hci_evt_le_per_advertising_report_v2)),
Expand Down Expand Up @@ -3256,6 +3296,10 @@ static int le_set_event_mask(void)
if (IS_ENABLED(CONFIG_BT_TRANSMIT_POWER_CONTROL)) {
mask |= BT_EVT_MASK_LE_TRANSMIT_POWER_REPORTING;
}

if (IS_ENABLED(CONFIG_BT_PATH_LOSS_MONITORING)) {
mask |= BT_EVT_MASK_LE_PATH_LOSS_THRESHOLD;
}
}

if (IS_ENABLED(CONFIG_BT_SMP) &&
Expand Down
Loading

0 comments on commit 0b327db

Please sign in to comment.