Skip to content

Commit f7358ed

Browse files
Andries Kruithofcvinayak
authored andcommitted
Bluetooth: Controller: Initial Frame Space Update support
Initial Frame Space Update support. Signed-off-by: Andries Kruithof <andries.kruithof@nordicsemi.no> Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
1 parent f03c105 commit f7358ed

File tree

16 files changed

+543
-6
lines changed

16 files changed

+543
-6
lines changed

subsys/bluetooth/controller/include/ll_feat.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@
253253
* !CONFIG_BT_CTLR_SYNC_PERIODIC_ADI_SUPPORT
254254
*/
255255

256+
/* FIXME: Conditional Compilation for FSU feature, and handle feature bits > 64 bits */
257+
#define LL_FEAT_BIT_FRAME_SPACE 0U
258+
256259
/* All defined feature bits */
257260
#define LL_FEAT_BIT_MASK 0xFFFFFFFFFFULL
258261

@@ -296,7 +299,9 @@
296299
LL_FEAT_BIT_SYNC_RECEIVER | \
297300
LL_FEAT_BIT_PERIODIC_ADI_SUPPORT | \
298301
LL_FEAT_BIT_SYNC_TRANSFER_RECEIVER | \
299-
LL_FEAT_BIT_SYNC_TRANSFER_SENDER)
302+
LL_FEAT_BIT_SYNC_TRANSFER_SENDER | \
303+
LL_FEAT_BIT_FRAME_SPACE | \
304+
0U)
300305

301306
/* Connected Isochronous Stream (Host Support) bit is controlled by host */
302307
#if defined(CONFIG_BT_CTLR_CONN_ISO)

subsys/bluetooth/controller/ll_sw/lll_conn.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ struct data_pdu_length {
5353
};
5454
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
5555

56+
struct data_pdu_fsu {
57+
uint16_t fsu_min;
58+
uint16_t fsu_max;
59+
uint8_t phys;
60+
uint16_t spacing_type;
61+
};
62+
5663
struct lll_conn {
5764
struct lll_hdr hdr;
5865

@@ -133,6 +140,12 @@ struct lll_conn {
133140
uint8_t update;
134141
} dle;
135142
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
143+
struct {
144+
struct data_pdu_fsu local;
145+
struct data_pdu_fsu perphy[4]; /* store frame-space for each PHY */
146+
struct data_pdu_fsu eff;
147+
uint8_t update;
148+
} fsu;
136149

137150
#if defined(CONFIG_BT_CTLR_PHY)
138151
uint8_t phy_tx:3;

subsys/bluetooth/controller/ll_sw/pdu.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@
286286
#define PHY_FLAGS_S2 0
287287
#define PHY_FLAGS_S8 BIT(0)
288288

289+
#define T_IFS_ACL_CP BIT(0)
290+
#define T_IFS_ACL_PC BIT(1)
291+
#define T_MCES BIT(2)
292+
#define T_IFS_CIS BIT(3)
293+
#define T_MSS_CIS BIT(4)
294+
289295
/* Macros for getting/setting did/sid from pdu_adv_adi */
290296
#define PDU_ADV_ADI_DID_GET(adi) ((adi)->did_sid_packed[0] | \
291297
(((adi)->did_sid_packed[1] & 0x0F) << 8))
@@ -624,6 +630,9 @@ enum pdu_data_llctrl_type {
624630
PDU_DATA_LLCTRL_TYPE_CIS_RSP = 0x20,
625631
PDU_DATA_LLCTRL_TYPE_CIS_IND = 0x21,
626632
PDU_DATA_LLCTRL_TYPE_CIS_TERMINATE_IND = 0x22,
633+
PDU_DATA_LLCTRL_TYPE_FRAME_SPACE_REQ = 0x3B,
634+
PDU_DATA_LLCTRL_TYPE_FRAME_SPACE_RSP = 0x3C,
635+
627636
PDU_DATA_LLCTRL_TYPE_UNUSED = 0xFF
628637
};
629638

@@ -788,6 +797,19 @@ struct pdu_data_llctrl_length_req_rsp_common {
788797
uint16_t max_tx_time;
789798
} __packed;
790799

800+
struct pdu_data_llctrl_fsu_req {
801+
uint16_t fsu_min;
802+
uint16_t fsu_max;
803+
uint8_t phys;
804+
uint16_t spacing_type;
805+
} __packed;
806+
807+
struct pdu_data_llctrl_fsu_rsp {
808+
uint16_t fsu;
809+
uint8_t phys;
810+
uint16_t spacing_type;
811+
} __packed;
812+
791813
struct pdu_data_llctrl_phy_req {
792814
uint8_t tx_phys;
793815
uint8_t rx_phys;
@@ -936,6 +958,8 @@ struct pdu_data_llctrl {
936958
struct pdu_data_llctrl_ping_rsp ping_rsp;
937959
struct pdu_data_llctrl_length_req length_req;
938960
struct pdu_data_llctrl_length_rsp length_rsp;
961+
struct pdu_data_llctrl_fsu_req fsu_req;
962+
struct pdu_data_llctrl_fsu_rsp fsu_rsp;
939963
struct pdu_data_llctrl_phy_req phy_req;
940964
struct pdu_data_llctrl_phy_rsp phy_rsp;
941965
struct pdu_data_llctrl_phy_upd_ind phy_upd_ind;

subsys/bluetooth/controller/ll_sw/ull_central.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
227227
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
228228
ull_dle_init(conn, PHY_1M);
229229
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
230-
230+
ull_fsu_init(conn);
231231
#if defined(CONFIG_BT_CTLR_CONN_RSSI)
232232
conn_lll->rssi_latest = BT_HCI_LE_RSSI_NOT_AVAILABLE;
233233
#if defined(CONFIG_BT_CTLR_CONN_RSSI_EVENT)

subsys/bluetooth/controller/ll_sw/ull_conn.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2380,6 +2380,13 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_
23802380
lll->tifs_tx_us = EVENT_IFS_DEFAULT_US;
23812381
lll->tifs_rx_us = EVENT_IFS_DEFAULT_US;
23822382
lll->tifs_hcto_us = EVENT_IFS_DEFAULT_US;
2383+
for (size_t i = 0; i < 3; i++) {
2384+
conn->lll.fsu.perphy[i].fsu_min = EVENT_IFS_DEFAULT_US;
2385+
conn->lll.fsu.perphy[i].fsu_max = EVENT_IFS_DEFAULT_US;
2386+
conn->lll.fsu.perphy[i].phys = PHY_1M | PHY_2M | PHY_CODED;
2387+
conn->lll.fsu.perphy[i].spacing_type =
2388+
T_IFS_ACL_PC | T_IFS_ACL_CP | T_IFS_CIS;
2389+
}
23832390

23842391
#if defined(CONFIG_BT_CTLR_DATA_LENGTH) && \
23852392
defined(CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE)
@@ -2417,6 +2424,14 @@ void ull_conn_update_parameters(struct ll_conn *conn, uint8_t is_cu_proc, uint8_
24172424
lll->tifs_tx_us = CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US;
24182425
lll->tifs_rx_us = CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US;
24192426
lll->tifs_hcto_us = CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US;
2427+
for (size_t i = 0; i < 3; i++) {
2428+
conn->lll.fsu.perphy[i].fsu_min =
2429+
CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US;
2430+
conn->lll.fsu.perphy[i].fsu_max = EVENT_IFS_US;
2431+
conn->lll.fsu.perphy[i].phys = PHY_1M | PHY_2M | PHY_CODED;
2432+
conn->lll.fsu.perphy[i].spacing_type =
2433+
T_IFS_ACL_PC | T_IFS_ACL_CP | T_IFS_CIS;
2434+
}
24202435
/* Reserve only the processing overhead, on overlap the
24212436
* is_abort_cb mechanism will ensure to continue the event so
24222437
* as to not loose anchor point sync.
@@ -2832,6 +2847,132 @@ void ull_conn_default_tx_time_set(uint16_t tx_time)
28322847
}
28332848
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
28342849

2850+
uint8_t ull_fsu_update_eff(struct ll_conn *conn)
2851+
{
2852+
uint8_t fsu_changed = 0U;
2853+
uint8_t phy_tx;
2854+
uint8_t phy_rx;
2855+
2856+
#if defined(CONFIG_BT_PHY_UPDATE)
2857+
phy_tx = conn->lll.phy_tx;
2858+
phy_rx = conn->lll.phy_rx;
2859+
#else
2860+
phy_tx = PHY_1M;
2861+
phy_rx = PHY_1M;
2862+
#endif /* CONFIG_BT_PHY_UPDATE */
2863+
2864+
fsu_changed = ull_fsu_update_eff_from_local(conn);
2865+
2866+
if (fsu_changed) {
2867+
/* TODO: confirm that we do not need to do something here? */
2868+
}
2869+
2870+
if ((conn->lll.fsu.local.spacing_type & T_IFS_CIS) == T_IFS_CIS) {
2871+
2872+
if (conn->lll.tifs_cis_us == conn->lll.fsu.eff.fsu_min) {
2873+
fsu_changed = 1;
2874+
}
2875+
conn->lll.tifs_cis_us = conn->lll.fsu.eff.fsu_min;
2876+
}
2877+
2878+
if ((conn->lll.fsu.local.spacing_type & T_IFS_ACL_CP) == T_IFS_ACL_CP) {
2879+
if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL) {
2880+
if (conn->lll.fsu.local.phys & phy_tx) {
2881+
if (conn->lll.tifs_tx_us ==
2882+
conn->lll.fsu.eff.fsu_min) {
2883+
fsu_changed = 1;
2884+
}
2885+
conn->lll.tifs_tx_us = conn->lll.fsu.eff.fsu_min;
2886+
}
2887+
} else {
2888+
if (conn->lll.fsu.local.phys & phy_rx) {
2889+
if (conn->lll.tifs_rx_us ==
2890+
conn->lll.fsu.eff.fsu_min) {
2891+
fsu_changed = 1;
2892+
}
2893+
conn->lll.tifs_rx_us = conn->lll.fsu.eff.fsu_min;
2894+
}
2895+
}
2896+
}
2897+
2898+
if ((conn->lll.fsu.local.spacing_type & T_IFS_ACL_PC) == T_IFS_ACL_PC) {
2899+
if (conn->lll.role == BT_HCI_ROLE_PERIPHERAL) {
2900+
if (conn->lll.fsu.local.phys & phy_rx) {
2901+
if (conn->lll.tifs_rx_us ==
2902+
conn->lll.fsu.eff.fsu_min) {
2903+
fsu_changed = 1;
2904+
}
2905+
conn->lll.tifs_rx_us = conn->lll.fsu.eff.fsu_min;
2906+
}
2907+
} else {
2908+
if (conn->lll.fsu.local.phys & phy_tx) {
2909+
if (conn->lll.tifs_tx_us ==
2910+
conn->lll.fsu.eff.fsu_min) {
2911+
fsu_changed = 1;
2912+
}
2913+
conn->lll.tifs_tx_us = conn->lll.fsu.eff.fsu_min;
2914+
}
2915+
}
2916+
}
2917+
if (fsu_changed == 1) {
2918+
conn->lll.fsu.local.phys = 0;
2919+
conn->lll.fsu.local.spacing_type = 0;
2920+
}
2921+
2922+
return fsu_changed;
2923+
}
2924+
2925+
uint8_t ull_fsu_update_eff_from_local(struct ll_conn *conn)
2926+
{
2927+
uint8_t fsu_changed = 0U;
2928+
uint16_t fsu_min, fsu_max;
2929+
2930+
fsu_min = MAX(conn->lll.fsu.local.fsu_min, CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US);
2931+
fsu_max = MAX(conn->lll.fsu.local.fsu_max, CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US);
2932+
2933+
conn->lll.fsu.eff.fsu_min = fsu_min;
2934+
conn->lll.fsu.eff.fsu_max = fsu_max;
2935+
conn->lll.fsu.local.fsu_min = fsu_min;
2936+
conn->lll.fsu.local.fsu_max = fsu_max;
2937+
2938+
return fsu_changed;
2939+
}
2940+
2941+
void ull_fsu_local_tx_update(struct ll_conn *conn, uint16_t fsu_min,
2942+
uint16_t fsu_max, uint8_t phys, uint16_t spacing_type)
2943+
{
2944+
conn->lll.fsu.local.fsu_min = fsu_min;
2945+
if (conn->lll.tifs_rx_us > fsu_max) {
2946+
fsu_max = conn->lll.tifs_rx_us;
2947+
}
2948+
if (conn->lll.tifs_tx_us > fsu_max) {
2949+
fsu_max = conn->lll.tifs_tx_us;
2950+
}
2951+
conn->lll.fsu.local.fsu_max = fsu_max;
2952+
conn->lll.fsu.local.phys = phys;
2953+
conn->lll.fsu.local.spacing_type = spacing_type;
2954+
}
2955+
2956+
uint8_t ull_fsu_init(struct ll_conn *conn)
2957+
{
2958+
conn->lll.tifs_rx_us = EVENT_IFS_US;
2959+
conn->lll.tifs_tx_us = EVENT_IFS_US;
2960+
conn->lll.tifs_cis_us = EVENT_IFS_US;
2961+
conn->lll.fsu.local.fsu_min = CONFIG_BT_CTLR_EVENT_IFS_LOW_LAT_US;
2962+
conn->lll.fsu.local.fsu_max = EVENT_IFS_MAX_US;
2963+
conn->lll.fsu.eff.fsu_min = EVENT_IFS_US;
2964+
conn->lll.fsu.eff.fsu_max = EVENT_IFS_US;
2965+
for (size_t i = 0; i < 3; i++) {
2966+
conn->lll.fsu.perphy[i].fsu_min = EVENT_IFS_US;
2967+
conn->lll.fsu.perphy[i].fsu_max = EVENT_IFS_US;
2968+
conn->lll.fsu.perphy[i].phys = PHY_1M | PHY_2M | PHY_CODED;
2969+
conn->lll.fsu.perphy[i].spacing_type =
2970+
T_IFS_ACL_PC | T_IFS_ACL_CP | T_IFS_CIS;
2971+
}
2972+
2973+
return 0;
2974+
}
2975+
28352976
#if defined(CONFIG_BT_CTLR_SYNC_TRANSFER_SENDER)
28362977
static bool ticker_op_id_match_func(uint8_t ticker_id, uint32_t ticks_slot,
28372978
uint32_t ticks_to_expire, void *op_context)

subsys/bluetooth/controller/ll_sw/ull_conn_internal.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,15 @@ uint8_t ull_dle_update_eff(struct ll_conn *conn);
109109
uint8_t ull_dle_update_eff_tx(struct ll_conn *conn);
110110
uint8_t ull_dle_update_eff_rx(struct ll_conn *conn);
111111

112+
uint8_t ull_fsu_update_eff(struct ll_conn *conn);
113+
uint8_t ull_fsu_update_eff_from_local(struct ll_conn *conn);
114+
uint8_t ull_fsu_init(struct ll_conn *conn);
115+
112116
void ull_dle_local_tx_update(struct ll_conn *conn, uint16_t tx_octets, uint16_t tx_time);
113117

118+
void ull_fsu_local_tx_update(struct ll_conn *conn, uint16_t fsu_min,
119+
uint16_t fsu_max, uint8_t phys, uint16_t spacing_type);
120+
114121
void ull_conn_default_phy_tx_set(uint8_t tx);
115122

116123
void ull_conn_default_phy_rx_set(uint8_t rx);

subsys/bluetooth/controller/ll_sw/ull_llcp.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ static uint8_t MALIGN(4) buffer_mem_remote_ctx[PROC_CTX_BUF_SIZE *
8989
CONFIG_BT_CTLR_LLCP_REMOTE_PROC_CTX_BUF_NUM];
9090
static struct llcp_mem_pool mem_remote_ctx = { .pool = buffer_mem_remote_ctx };
9191

92+
uint8_t ull_cp_fsu(struct ll_conn *conn, uint16_t fsu_min, uint16_t fsu_max,
93+
uint8_t phys, uint16_t spacing_type);
94+
9295
/*
9396
* LLCP Resource Management
9497
*/
@@ -856,6 +859,20 @@ uint8_t ull_cp_cis_create(struct ll_conn *conn, struct ll_conn_iso_stream *cis)
856859
}
857860
#endif /* defined(CONFIG_BT_CTLR_CENTRAL_ISO) */
858861

862+
uint8_t bt_ull_cp_fsu(uint16_t handle, uint16_t fsu_min, uint16_t fsu_max,
863+
uint8_t phys, uint16_t spacing_type)
864+
{
865+
struct ll_conn *conn;
866+
uint8_t err;
867+
868+
conn = ll_connected_get(handle);
869+
if (!conn) {
870+
return BT_HCI_ERR_UNKNOWN_CONN_ID;
871+
}
872+
err = ull_cp_fsu(conn, fsu_min, fsu_max, phys, spacing_type);
873+
return err;
874+
}
875+
859876
#if defined(CONFIG_BT_CENTRAL)
860877
uint8_t ull_cp_chan_map_update(struct ll_conn *conn, const uint8_t chm[5])
861878
{
@@ -926,6 +943,27 @@ uint8_t ull_cp_data_length_update(struct ll_conn *conn, uint16_t max_tx_octets,
926943
}
927944
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
928945

946+
uint8_t ull_cp_fsu(struct ll_conn *conn, uint16_t fsu_min, uint16_t fsu_max,
947+
uint8_t phys, uint16_t spacing_type)
948+
{
949+
struct proc_ctx *ctx;
950+
951+
if (!feature_fsu(conn)) {
952+
return BT_HCI_ERR_SUCCESS;
953+
}
954+
955+
ctx = llcp_create_local_procedure(PROC_FRAME_SPACE);
956+
if (!ctx) {
957+
return BT_HCI_ERR_CMD_DISALLOWED;
958+
}
959+
960+
ull_fsu_local_tx_update(conn, fsu_min, fsu_max, phys, spacing_type);
961+
962+
llcp_lr_enqueue(conn, ctx);
963+
964+
return BT_HCI_ERR_SUCCESS;
965+
}
966+
929967
#if defined(CONFIG_BT_CTLR_SCA_UPDATE)
930968
uint8_t ull_cp_req_peer_sca(struct ll_conn *conn)
931969
{
@@ -1153,6 +1191,15 @@ uint8_t ull_cp_remote_dle_pending(struct ll_conn *conn)
11531191
}
11541192
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
11551193

1194+
uint8_t ull_cp_remote_fsu_pending(struct ll_conn *conn)
1195+
{
1196+
struct proc_ctx *ctx;
1197+
1198+
ctx = llcp_rr_peek(conn);
1199+
1200+
return (ctx && ctx->proc == PROC_FRAME_SPACE);
1201+
}
1202+
11561203
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
11571204
void ull_cp_conn_param_req_reply(struct ll_conn *conn)
11581205
{
@@ -1770,6 +1817,16 @@ static bool pdu_validate_length_rsp(struct pdu_data *pdu)
17701817
return VALIDATE_PDU_LEN(pdu, length_rsp);
17711818
}
17721819

1820+
static bool pdu_validate_fsu_req(struct pdu_data *pdu)
1821+
{
1822+
return VALIDATE_PDU_LEN(pdu, fsu_req);
1823+
}
1824+
1825+
static bool pdu_validate_fsu_rsp(struct pdu_data *pdu)
1826+
{
1827+
return VALIDATE_PDU_LEN(pdu, fsu_rsp);
1828+
}
1829+
17731830
#if defined(CONFIG_BT_CTLR_PHY)
17741831
static bool pdu_validate_phy_req(struct pdu_data *pdu)
17751832
{
@@ -1881,6 +1938,8 @@ static const struct pdu_validate pdu_validate[] = {
18811938
[PDU_DATA_LLCTRL_TYPE_LENGTH_REQ] = { pdu_validate_length_req },
18821939
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
18831940
[PDU_DATA_LLCTRL_TYPE_LENGTH_RSP] = { pdu_validate_length_rsp },
1941+
[PDU_DATA_LLCTRL_TYPE_FRAME_SPACE_REQ] = { pdu_validate_fsu_req },
1942+
[PDU_DATA_LLCTRL_TYPE_FRAME_SPACE_RSP] = { pdu_validate_fsu_rsp },
18841943
#if defined(CONFIG_BT_CTLR_PHY)
18851944
[PDU_DATA_LLCTRL_TYPE_PHY_REQ] = { pdu_validate_phy_req },
18861945
#endif /* CONFIG_BT_CTLR_PHY */

0 commit comments

Comments
 (0)