Skip to content

Commit c781c30

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 c781c30

File tree

10 files changed

+196
-2
lines changed

10 files changed

+196
-2
lines changed

include/zephyr/bluetooth/hci_types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,11 @@ struct bt_hci_cp_le_set_path_loss_reporting_enable {
720720
uint8_t enable;
721721
} __packed;
722722

723+
struct bt_hci_rp_path_loss_reporting {
724+
uint8_t status;
725+
uint16_t handle;
726+
} __packed;
727+
723728
#define BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS BT_OP(BT_OGF_LE, 0x0078) /* 0x2078 */
724729

725730
#define BT_HCI_LE_PATH_LOSS_REPORTING_DISABLE 0x00

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: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2793,6 +2793,50 @@ 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+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
2798+
static void le_path_loss_set_parameters(struct net_buf *buf, struct net_buf **evt)
2799+
{
2800+
struct bt_hci_cp_le_set_path_loss_reporting_parameters *cmd = (void *)buf->data;
2801+
struct bt_hci_rp_path_loss_reporting *rp;
2802+
2803+
uint16_t handle = sys_le16_to_cpu(cmd->handle);
2804+
uint16_t min_time_spent = sys_le16_to_cpu(cmd->min_time_spent);
2805+
2806+
rp = hci_cmd_complete(evt, sizeof(*rp));
2807+
rp->handle = handle;
2808+
2809+
if (cmd->high_threshold + cmd->high_hysteresis > 0xFF ||
2810+
cmd->low_threshold < cmd->low_hysteresis ||
2811+
cmd->low_threshold > cmd->high_threshold ||
2812+
cmd->low_threshold + cmd->low_hysteresis > cmd->high_threshold - cmd->high_hysteresis) {
2813+
rp->status = BT_HCI_ERR_INVALID_PARAM;
2814+
return;
2815+
}
2816+
2817+
rp->status = ll_conn_set_path_loss_parameters(handle, cmd->high_threshold,
2818+
cmd->high_hysteresis, cmd->low_threshold,
2819+
cmd->low_hysteresis, min_time_spent);
2820+
}
2821+
2822+
static void le_path_loss_enable(struct net_buf *buf, struct net_buf **evt)
2823+
{
2824+
struct bt_hci_cp_le_set_path_loss_reporting_enable *cmd = (void *)buf->data;
2825+
struct bt_hci_rp_path_loss_reporting *rp;
2826+
2827+
uint16_t handle = sys_le16_to_cpu(cmd->handle);
2828+
2829+
rp = hci_cmd_complete(evt, sizeof(*rp));
2830+
rp->handle = handle;
2831+
2832+
/* Anything beyond 0x00 or 0x01 is reserved */
2833+
if (cmd->enable > 0x01) {
2834+
rp->status = BT_HCI_ERR_INVALID_PARAM;
2835+
}
2836+
2837+
rp->status = ll_conn_set_path_loss_reporting(handle, cmd->enable);
2838+
}
2839+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
27962840
#endif /* CONFIG_BT_CONN */
27972841

27982842
#if defined(CONFIG_BT_CTLR_PRIVACY)
@@ -4767,6 +4811,17 @@ static int controller_cmd_handle(uint16_t ocf, struct net_buf *cmd,
47674811
le_set_phy(cmd, evt);
47684812
break;
47694813
#endif /* CONFIG_BT_CTLR_PHY */
4814+
4815+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
4816+
case BT_OCF(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS):
4817+
le_path_loss_set_parameters(cmd, evt);
4818+
break;
4819+
4820+
case BT_OCF(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE):
4821+
le_path_loss_enable(cmd, evt);
4822+
break;
4823+
4824+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
47704825
#endif /* CONFIG_BT_CONN */
47714826

47724827
#if defined(CONFIG_BT_CTLR_ADV_EXT)
@@ -8645,6 +8700,28 @@ static void le_req_peer_sca_complete(struct pdu_data *pdu, uint16_t handle,
86458700
sep->sca = scau->sca;
86468701
}
86478702
#endif /* CONFIG_BT_CTLR_SCA_UPDATE */
8703+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
8704+
static void le_path_loss_threshold(struct pdu_data *pdu,
8705+
uint16_t handle,
8706+
struct net_buf *buf)
8707+
{
8708+
struct bt_hci_evt_le_path_loss_threshold *sep;
8709+
struct node_rx_path_loss *pl_pdu;
8710+
8711+
pl_pdu = (void *)pdu_data;
8712+
8713+
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
8714+
!(le_event_mask & BT_EVT_MASK_LE_PATH_LOSS_THRESHOLD)) {
8715+
return;
8716+
}
8717+
8718+
sep = meta_evt(buf, BT_HCI_EVT_LE_PATH_LOSS_THRESHOLD, sizeof(*sep));
8719+
8720+
sep->handle = sys_cpu_to_le16(handle);
8721+
sep->current_path_loss = pl_pdu->current_path_loss;
8722+
sep->zone_entered = pl_pdu->zone_entered;
8723+
}
8724+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
86488725
#endif /* CONFIG_BT_CONN */
86498726

86508727
#if defined(CONFIG_BT_HCI_MESH_EXT)
@@ -8847,6 +8924,12 @@ static void encode_control(struct node_rx_pdu *node_rx,
88478924
#endif /* CONFIG_BT_CTLR_DF_VS_CONN_IQ_REPORT_16_BITS_IQ_SAMPLES */
88488925
return;
88498926
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
8927+
8928+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
8929+
case NODE_RX_TYPE_PATH_LOSS:
8930+
le_path_loss_threshold(pdu_data, handle, buf);
8931+
return;
8932+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
88508933
#endif /* CONFIG_BT_CONN */
88518934

88528935
#if defined(CONFIG_BT_CTLR_ADV_INDICATION)
@@ -9332,6 +9415,10 @@ uint8_t hci_get_class(struct node_rx_pdu *node_rx)
93329415
#endif /* CONFIG_BT_CTLR_PHY */
93339416

93349417
return HCI_CLASS_EVT_CONNECTION;
9418+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
9419+
case NODE_RX_TYPE_PATH_LOSS:
9420+
return HCI_CLASS_EVT_REQUIRED;
9421+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
93359422
#endif /* CONFIG_BT_CONN */
93369423

93379424
#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: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,27 @@
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+
};
26+
27+
struct path_loss_event {
28+
uint8_t curr_path_loss;
29+
uint8_t zone_entered;
30+
};
31+
32+
struct path_loss_state {
33+
uint16_t conn_handle;
34+
uint16_t min_time_counter;
35+
uint8_t new_zone;
36+
};
37+
1738
struct lll_tx {
1839
uint16_t handle;
1940
void *node;
@@ -157,6 +178,11 @@ struct lll_conn {
157178
uint8_t rssi_sample_count;
158179
#endif /* CONFIG_BT_CTLR_CONN_RSSI_EVENT */
159180
#endif /* CONFIG_BT_CTLR_CONN_RSSI */
181+
#if defined(CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING)
182+
struct path_loss_params pl_params;
183+
struct path_loss_state pl_state;
184+
uint8_t pl_current_zone;
185+
#endif /* CONFIG_BT_CTLR_LE_PATH_LOSS_MONITORING */
160186

161187
#if defined(CONFIG_BT_CTLR_CONN_META)
162188
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)