Skip to content

Commit fa947a1

Browse files
Bluetooth: Controller: Adds path loss monitoring functionality
This functionality is implemented in the HCI-facing side of the controller and the ULL. LLL functionality is not implemented in this commit. Furthermore, this removes a dependency for LE Power Control, as the features are related, but not necessarily required. Signed-off-by: Tyler Joseph Huffman <tyhu@demant.com>
1 parent b15404f commit fa947a1

File tree

10 files changed

+208
-8
lines changed

10 files changed

+208
-8
lines changed

include/zephyr/bluetooth/hci_types.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ struct bt_hci_cp_le_set_tx_power_report_enable {
706706
uint8_t remote_enable;
707707
} __packed;
708708

709+
#define BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS BT_OP(BT_OGF_LE, 0x0078) /* 0x2078 */
709710
struct bt_hci_cp_le_set_path_loss_reporting_parameters {
710711
uint16_t handle;
711712
uint8_t high_threshold;
@@ -715,17 +716,28 @@ struct bt_hci_cp_le_set_path_loss_reporting_parameters {
715716
uint16_t min_time_spent;
716717
} __packed;
717718

718-
struct bt_hci_cp_le_set_path_loss_reporting_enable {
719+
struct bt_hci_rp_le_set_path_loss_reporting_parameters {
719720
uint16_t handle;
720-
uint8_t enable;
721+
uint8_t status;
721722
} __packed;
722723

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

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

729+
struct bt_hci_cp_le_set_path_loss_reporting_enable {
730+
uint16_t handle;
731+
uint8_t enable;
732+
} __packed;
733+
734+
struct bt_hci_rp_le_set_path_loss_reporting_enable {
735+
uint16_t handle;
736+
uint8_t status;
737+
} __packed;
738+
739+
#define BT_HCI_OP_LE_SET_DEFAULT_SUBRATE BT_OP(BT_OGF_LE, 0x007D) /* 0x207D */
740+
729741
struct bt_hci_cp_le_set_default_subrate {
730742
uint16_t subrate_min;
731743
uint16_t subrate_max;
@@ -734,6 +746,8 @@ struct bt_hci_cp_le_set_default_subrate {
734746
uint16_t supervision_timeout;
735747
} __packed;
736748

749+
#define BT_HCI_OP_LE_SUBRATE_REQUEST BT_OP(BT_OGF_LE, 0x007E) /* 0x207E */
750+
737751
struct bt_hci_cp_le_subrate_request {
738752
uint16_t handle;
739753
uint16_t subrate_min;
@@ -743,9 +757,6 @@ struct bt_hci_cp_le_subrate_request {
743757
uint16_t supervision_timeout;
744758
} __packed;
745759

746-
#define BT_HCI_OP_LE_SET_DEFAULT_SUBRATE BT_OP(BT_OGF_LE, 0x007D) /* 0x207D */
747-
#define BT_HCI_OP_LE_SUBRATE_REQUEST BT_OP(BT_OGF_LE, 0x007E) /* 0x207E */
748-
749760
#define BT_HCI_CTL_TO_HOST_FLOW_DISABLE 0x00
750761
#define BT_HCI_CTL_TO_HOST_FLOW_ENABLE 0x01
751762
#define BT_HCI_OP_SET_CTL_TO_HOST_FLOW BT_OP(BT_OGF_BASEBAND, 0x0031) /* 0x0c31 */

subsys/bluetooth/controller/Kconfig

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ config BT_CTLR_LE_POWER_CONTROL_SUPPORT
119119
bool
120120

121121
config BT_CTLR_LE_PATH_LOSS_MONITORING_SUPPORT
122-
depends on BT_CTLR_LE_POWER_CONTROL_SUPPORT
123122
bool
124123

125124
config BT_CTLR_SUBRATING_SUPPORT
@@ -661,7 +660,6 @@ config BT_CTLR_LE_PATH_LOSS_MONITORING
661660
bool "LE Path Loss Monitoring Feature"
662661
depends on BT_CTLR_LE_PATH_LOSS_MONITORING_SUPPORT
663662
default y if BT_PATH_LOSS_MONITORING
664-
select BT_CTLR_LE_POWER_CONTROL
665663
help
666664
Enable support for LE Path Loss Monitoring feature that is defined in the
667665
Bluetooth Core specification, Version 5.4 | Vol 6, Part B, Section 4.6.32.

subsys/bluetooth/controller/hci/hci.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2793,6 +2793,55 @@ static void le_set_phy(struct net_buf *buf, struct net_buf **evt)
27932793
*evt = cmd_status(status);
27942794
}
27952795
#endif /* CONFIG_BT_CTLR_PHY */
2796+
2797+
2798+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
2799+
2800+
#define PATH_LOSS_FACTOR_INVALID 0xFF
2801+
static void le_path_loss_set_parameters(struct net_buf *buf, struct net_buf **evt)
2802+
{
2803+
struct bt_hci_cp_le_set_path_loss_reporting_parameters *cmd = (void *)buf->data;
2804+
struct bt_hci_rp_le_set_path_loss_reporting_parameters *rp;
2805+
2806+
uint16_t handle = sys_le16_to_cpu(cmd->handle);
2807+
uint16_t min_time_spent = sys_le16_to_cpu(cmd->min_time_spent);
2808+
2809+
rp = hci_cmd_complete(evt, sizeof(*rp));
2810+
rp->handle = handle;
2811+
2812+
if (cmd->high_threshold + cmd->high_hysteresis > PATH_LOSS_FACTOR_INVALID ||
2813+
cmd->low_threshold < cmd->low_hysteresis ||
2814+
cmd->low_threshold > cmd->high_threshold ||
2815+
cmd->low_threshold + cmd->low_hysteresis > cmd->high_threshold - cmd->high_hysteresis) {
2816+
rp->status = BT_HCI_ERR_INVALID_PARAM;
2817+
return;
2818+
}
2819+
2820+
rp->status = ll_conn_set_path_loss_parameters(handle, cmd->high_threshold,
2821+
cmd->high_hysteresis, cmd->low_threshold,
2822+
cmd->low_hysteresis, min_time_spent);
2823+
}
2824+
2825+
#define PATH_LOSS_ENABLED 0x01
2826+
#define PATH_LOSS_DISABLED 0x00
2827+
static void le_path_loss_enable(struct net_buf *buf, struct net_buf **evt)
2828+
{
2829+
struct bt_hci_cp_le_set_path_loss_reporting_enable *cmd = (void *)buf->data;
2830+
struct bt_hci_rp_le_set_path_loss_reporting_enable *rp;
2831+
2832+
uint16_t handle = sys_le16_to_cpu(cmd->handle);
2833+
2834+
rp = hci_cmd_complete(evt, sizeof(*rp));
2835+
rp->handle = handle;
2836+
2837+
if (cmd->enable != PATH_LOSS_ENABLED &&
2838+
cmd->enable != PATH_LOSS_DISABLED) {
2839+
rp->status = BT_HCI_ERR_INVALID_PARAM;
2840+
}
2841+
2842+
rp->status = ll_conn_set_path_loss_reporting(handle, cmd->enable);
2843+
}
2844+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
27962845
#endif /* CONFIG_BT_CONN */
27972846

27982847
#if defined(CONFIG_BT_CTLR_PRIVACY)
@@ -4767,6 +4816,17 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd,
47674816
le_set_phy(cmd, evt);
47684817
break;
47694818
#endif /* CONFIG_BT_CTLR_PHY */
4819+
4820+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
4821+
case BT_OCF(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS):
4822+
le_path_loss_set_parameters(cmd, evt);
4823+
break;
4824+
4825+
case BT_OCF(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE):
4826+
le_path_loss_enable(cmd, evt);
4827+
break;
4828+
4829+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
47704830
#endif /* CONFIG_BT_CONN */
47714831

47724832
#if defined(CONFIG_BT_CTLR_ADV_EXT)
@@ -8645,6 +8705,28 @@ static void le_req_peer_sca_complete(struct pdu_data *pdu, uint16_t handle,
86458705
sep->sca = scau->sca;
86468706
}
86478707
#endif /* CONFIG_BT_CTLR_SCA_UPDATE */
8708+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
8709+
static void le_path_loss_threshold(struct pdu_data *pdu,
8710+
uint16_t handle,
8711+
struct net_buf *buf)
8712+
{
8713+
struct bt_hci_evt_le_path_loss_threshold *sep;
8714+
struct node_rx_path_loss *pl_pdu;
8715+
8716+
pl_pdu = (void *)pdu;
8717+
8718+
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
8719+
!(le_event_mask & BT_EVT_MASK_LE_PATH_LOSS_THRESHOLD)) {
8720+
return;
8721+
}
8722+
8723+
sep = meta_evt(buf, BT_HCI_EVT_LE_PATH_LOSS_THRESHOLD, sizeof(*sep));
8724+
8725+
sep->handle = sys_cpu_to_le16(handle);
8726+
sep->current_path_loss = pl_pdu->current_path_loss;
8727+
sep->zone_entered = pl_pdu->zone_entered;
8728+
}
8729+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
86488730
#endif /* CONFIG_BT_CONN */
86498731

86508732
#if defined(CONFIG_BT_HCI_MESH_EXT)
@@ -8847,6 +8929,12 @@ static void encode_control(struct node_rx_pdu *node_rx,
88478929
#endif /* CONFIG_BT_CTLR_DF_VS_CONN_IQ_REPORT_16_BITS_IQ_SAMPLES */
88488930
return;
88498931
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
8932+
8933+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
8934+
case NODE_RX_TYPE_PATH_LOSS:
8935+
le_path_loss_threshold(pdu_data, handle, buf);
8936+
return;
8937+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
88508938
#endif /* CONFIG_BT_CONN */
88518939

88528940
#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
@@ -9332,6 +9420,10 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx)
93329420
#endif /* CONFIG_BT_CTLR_PHY */
93339421

93349422
return HCI_CLASS_EVT_CONNECTION;
9423+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
9424+
case NODE_RX_TYPE_PATH_LOSS:
9425+
return HCI_CLASS_EVT_REQUIRED;
9426+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
93359427
#endif /* CONFIG_BT_CONN */
93369428

93379429
#if defined(CONFIG_BT_CTLR_SYNC_ISO) || defined(CONFIG_BT_CTLR_CONN_ISO)

subsys/bluetooth/controller/include/ll.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,3 +343,12 @@ void ll_coex_ticker_id_get(uint8_t * const instance_index,
343343
uint8_t * const ticker_id);
344344
void ll_radio_state_abort(void);
345345
uint32_t ll_radio_state_is_idle(void);
346+
347+
uint8_t ll_conn_set_path_loss_parameters(uint16_t handle,
348+
uint8_t high_threshold,
349+
uint8_t high_hysteresis,
350+
uint8_t low_threshold,
351+
uint8_t low_hysteresis,
352+
uint16_t min_time_spent);
353+
354+
uint8_t ll_conn_set_path_loss_reporting(uint16_t handle, uint8_t enable);

subsys/bluetooth/controller/ll_sw/lll.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ enum node_rx_type {
309309
NODE_RX_TYPE_IQ_SAMPLE_REPORT_ULL_RELEASE,
310310
NODE_RX_TYPE_IQ_SAMPLE_REPORT_LLL_RELEASE,
311311
NODE_RX_TYPE_SYNC_TRANSFER_RECEIVED,
312+
NODE_RX_TYPE_PATH_LOSS,
312313
/* Signals retention (ie non-release) of rx node */
313314
NODE_RX_TYPE_RETAIN,
314315

subsys/bluetooth/controller/ll_sw/lll_conn.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@
1414
#define LLL_CONN_MIC_PASS 1
1515
#define LLL_CONN_MIC_FAIL 2
1616

17+
18+
struct path_loss_params {
19+
uint16_t min_time_spent;
20+
uint8_t enabled;
21+
uint8_t high_threshold;
22+
uint8_t high_hysteresis;
23+
uint8_t low_threshold;
24+
uint8_t low_hysteresis;
25+
} __packed;
26+
27+
struct path_loss_state {
28+
uint16_t conn_handle;
29+
uint16_t min_time_counter;
30+
uint8_t new_zone;
31+
} __packed;
32+
1733
struct lll_tx {
1834
uint16_t handle;
1935
void *node;
@@ -157,6 +173,11 @@ struct lll_conn {
157173
uint8_t rssi_sample_count;
158174
#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
159175
#endif /* CONFIG_BT_CTLR_CONN_RSSI */
176+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
177+
struct path_loss_params pl_params;
178+
struct path_loss_state pl_state;
179+
uint8_t pl_current_zone;
180+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
160181

161182
#if defined(CONFIG_BT_CTLR_CONN_META)
162183
struct lll_conn_meta conn_meta;

subsys/bluetooth/controller/ll_sw/ull.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,6 +1392,7 @@ void ll_rx_dequeue(void)
13921392
#if defined(CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT)
13931393
case NODE_RX_TYPE_DTM_IQ_SAMPLE_REPORT:
13941394
#endif /* CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT */
1395+
case NODE_RX_TYPE_PATH_LOSS:
13951396

13961397
/* Ensure that at least one 'case' statement is present for this
13971398
* code block.
@@ -1582,6 +1583,7 @@ void ll_rx_mem_release(void **node_rx)
15821583
#if defined(CONFIG_BT_CTLR_ISO)
15831584
case NODE_RX_TYPE_ISO_PDU:
15841585
#endif
1586+
case NODE_RX_TYPE_PATH_LOSS:
15851587

15861588
/* Ensure that at least one 'case' statement is present for this
15871589
* code block.
@@ -2965,6 +2967,7 @@ static inline void rx_demux_rx(memq_link_t *link, struct node_rx_hdr *rx)
29652967
#if defined(CONFIG_BT_CTLR_SCAN_INDICATION)
29662968
case NODE_RX_TYPE_SCAN_INDICATION:
29672969
#endif /* CONFIG_BT_CTLR_SCAN_INDICATION */
2970+
case NODE_RX_TYPE_PATH_LOSS:
29682971

29692972
case NODE_RX_TYPE_RELEASE:
29702973
{

subsys/bluetooth/controller/ll_sw/ull_conn.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2910,6 +2910,56 @@ uint8_t ull_conn_lll_phy_active(struct ll_conn *conn, uint8_t phys)
29102910
return 1;
29112911
}
29122912

2913+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
2914+
uint8_t ll_conn_set_path_loss_parameters(uint16_t handle,
2915+
uint8_t high_threshold,
2916+
uint8_t high_hysteresis,
2917+
uint8_t low_threshold,
2918+
uint8_t low_hysteresis,
2919+
uint16_t min_time_spent)
2920+
{
2921+
struct ll_conn *conn;
2922+
2923+
conn = ll_connected_get(handle);
2924+
2925+
if (!conn) {
2926+
return BT_HCI_ERR_UNKNOWN_CONN_ID;
2927+
}
2928+
2929+
conn->lll.pl_params.high_threshold = high_threshold;
2930+
conn->lll.pl_params.high_hysteresis = high_hysteresis;
2931+
conn->lll.pl_params.low_threshold = low_threshold;
2932+
conn->lll.pl_params.low_hysteresis = low_hysteresis;
2933+
conn->lll.pl_params.min_time_spent = min_time_spent;
2934+
2935+
/* Reset the counter and zone after any update from the host */
2936+
conn->lll.pl_state.min_time_counter = 0;
2937+
conn->lll.pl_current_zone = BT_HCI_LE_ZONE_ENTERED_LOW;
2938+
2939+
return BT_HCI_ERR_SUCCESS;
2940+
}
2941+
2942+
uint8_t ll_conn_set_path_loss_reporting(uint16_t handle, uint8_t enable)
2943+
{
2944+
struct ll_conn *conn;
2945+
2946+
conn = ll_connected_get(handle);
2947+
2948+
if (!conn) {
2949+
return BT_HCI_ERR_UNKNOWN_CONN_ID;
2950+
}
2951+
2952+
conn->lll.pl_params.enabled = enable;
2953+
2954+
/* Reset the counter and zone after any update from the host */
2955+
conn->lll.pl_state.min_time_counter = 0;
2956+
conn->lll.pl_current_zone = BT_HCI_LE_ZONE_ENTERED_LOW;
2957+
2958+
return BT_HCI_ERR_SUCCESS;
2959+
2960+
}
2961+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
2962+
29132963
uint8_t ull_is_lll_tx_queue_empty(struct ll_conn *conn)
29142964
{
29152965
return (memq_peek(conn->lll.memq_tx.head, conn->lll.memq_tx.tail, NULL) == NULL);

subsys/bluetooth/controller/ll_sw/ull_conn_internal.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,13 @@ void ull_conn_resume_rx_data(struct ll_conn *conn);
138138
* @brief Check if the lower link layer transmit queue is empty
139139
*/
140140
uint8_t ull_is_lll_tx_queue_empty(struct ll_conn *conn);
141+
142+
/**
143+
* @brief Set path loss parameters
144+
*/
145+
void ull_path_loss_set_parameters(void);
146+
147+
/**
148+
* @brief Enable path loss reporting
149+
*/
150+
void ull_enable_path_loss_reporting(void);

subsys/bluetooth/controller/ll_sw/ull_conn_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,8 @@ struct node_rx_sca {
301301
uint8_t status;
302302
uint8_t sca;
303303
};
304+
305+
struct node_rx_path_loss {
306+
uint8_t current_path_loss;
307+
uint8_t zone_entered;
308+
};

0 commit comments

Comments
 (0)