Bluetooth: controller: Fix encryption and procedure with instant
Fix implementation to run local peripheral initiated control procedure with instant in parallel with remote initiated encryption procedure. Relates to #28887. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
d4347339f5
commit
8f537de8c4
3 changed files with 83 additions and 38 deletions
|
@ -897,6 +897,7 @@ uint8_t ll_adv_enable(uint8_t enable)
|
||||||
conn->llcp_enc.req = conn->llcp_enc.ack = 0U;
|
conn->llcp_enc.req = conn->llcp_enc.ack = 0U;
|
||||||
conn->llcp_enc.pause_tx = conn->llcp_enc.pause_rx = 0U;
|
conn->llcp_enc.pause_tx = conn->llcp_enc.pause_rx = 0U;
|
||||||
conn->llcp_enc.refresh = 0U;
|
conn->llcp_enc.refresh = 0U;
|
||||||
|
conn->slave.llcp_type = 0U;
|
||||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||||
|
|
|
@ -863,6 +863,9 @@ int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy)
|
||||||
*/
|
*/
|
||||||
if ((conn->llcp_ack == conn->llcp_req) &&
|
if ((conn->llcp_ack == conn->llcp_req) &&
|
||||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||||
|
#if defined(CONFIG_BT_PERIPHERAL)
|
||||||
|
(!conn->lll.role || (conn->slave.llcp_type == LLCP_NONE)) &&
|
||||||
|
#endif /* CONFIG_BT_PERIPHERAL */
|
||||||
!conn->llcp_enc.pause_rx) {
|
!conn->llcp_enc.pause_rx) {
|
||||||
#else /* !CONFIG_BT_CTLR_LE_ENC */
|
#else /* !CONFIG_BT_CTLR_LE_ENC */
|
||||||
1) {
|
1) {
|
||||||
|
@ -995,10 +998,34 @@ int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
#if defined(CONFIG_BT_PERIPHERAL) && defined(CONFIG_BT_CTLR_LE_ENC)
|
||||||
/* Run any pending procedure stored while encryption was started */
|
/* Run any pending local peripheral role initiated procedure stored when
|
||||||
if (conn->llcp.encryption.pend_llcp_type != LLCP_NONE) {
|
* peer central initiated a encryption procedure
|
||||||
switch (conn->llcp.encryption.pend_llcp_type) {
|
*/
|
||||||
|
if (conn->lll.role && (conn->slave.llcp_type != LLCP_NONE)) {
|
||||||
|
switch (conn->slave.llcp_type) {
|
||||||
|
case LLCP_CONN_UPD:
|
||||||
|
{
|
||||||
|
if (event_conn_upd_prep(conn, lazy,
|
||||||
|
ticks_at_expire) == 0) {
|
||||||
|
return -ECANCELED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LLCP_CHAN_MAP:
|
||||||
|
{
|
||||||
|
struct lll_conn *lll = &conn->lll;
|
||||||
|
uint16_t event_counter;
|
||||||
|
|
||||||
|
/* Calculate current event counter */
|
||||||
|
event_counter = lll->event_counter +
|
||||||
|
lll->latency_prepare + lazy;
|
||||||
|
|
||||||
|
event_ch_map_prep(conn, event_counter);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_PHY)
|
#if defined(CONFIG_BT_CTLR_PHY)
|
||||||
case LLCP_PHY_UPD:
|
case LLCP_PHY_UPD:
|
||||||
{
|
{
|
||||||
|
@ -1019,7 +1046,7 @@ int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
#endif /* CONFIG_BT_PERIPHERAL && CONFIG_BT_CTLR_LE_ENC */
|
||||||
|
|
||||||
/* Terminate Procedure Request */
|
/* Terminate Procedure Request */
|
||||||
if (conn->llcp_terminate.ack != conn->llcp_terminate.req) {
|
if (conn->llcp_terminate.ack != conn->llcp_terminate.req) {
|
||||||
|
@ -2319,9 +2346,21 @@ static inline int event_conn_upd_prep(struct ll_conn *conn, uint16_t lazy,
|
||||||
uint32_t periodic_us;
|
uint32_t periodic_us;
|
||||||
uint16_t latency;
|
uint16_t latency;
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_PERIPHERAL)
|
||||||
|
if (conn->lll.role && (conn->slave.llcp_type != LLCP_NONE)) {
|
||||||
|
/* Local peripheral initiated PHY update completed while
|
||||||
|
* a remote central had initiated encryption procedure
|
||||||
|
*/
|
||||||
|
conn->slave.llcp_type = LLCP_NONE;
|
||||||
|
} else
|
||||||
|
#endif /* CONFIG_BT_PERIPHERAL */
|
||||||
|
{
|
||||||
|
/* procedure request acked */
|
||||||
|
conn->llcp_ack = conn->llcp_req;
|
||||||
|
}
|
||||||
|
|
||||||
/* procedure request acked */
|
/* procedure request acked */
|
||||||
conn->llcp_cu.ack = conn->llcp_cu.req;
|
conn->llcp_cu.ack = conn->llcp_cu.req;
|
||||||
conn->llcp_ack = conn->llcp_req;
|
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||||
if ((conn->llcp_conn_param.req != conn->llcp_conn_param.ack) &&
|
if ((conn->llcp_conn_param.req != conn->llcp_conn_param.ack) &&
|
||||||
|
@ -2591,8 +2630,18 @@ static inline void event_ch_map_prep(struct ll_conn *conn,
|
||||||
<= 0x7FFF) {
|
<= 0x7FFF) {
|
||||||
struct lll_conn *lll = &conn->lll;
|
struct lll_conn *lll = &conn->lll;
|
||||||
|
|
||||||
/* procedure request acked */
|
#if defined(CONFIG_BT_PERIPHERAL)
|
||||||
conn->llcp_ack = conn->llcp_req;
|
if (conn->lll.role && (conn->slave.llcp_type != LLCP_NONE)) {
|
||||||
|
/* Local peripheral initiated PHY update completed while
|
||||||
|
* a remote central had initiated encryption procedure
|
||||||
|
*/
|
||||||
|
conn->slave.llcp_type = LLCP_NONE;
|
||||||
|
} else
|
||||||
|
#endif /* CONFIG_BT_PERIPHERAL */
|
||||||
|
{
|
||||||
|
/* procedure request acked */
|
||||||
|
conn->llcp_ack = conn->llcp_req;
|
||||||
|
}
|
||||||
|
|
||||||
/* copy to active channel map */
|
/* copy to active channel map */
|
||||||
memcpy(&lll->data_chan_map[0],
|
memcpy(&lll->data_chan_map[0],
|
||||||
|
@ -2802,19 +2851,6 @@ static inline void event_enc_prep(struct ll_conn *conn)
|
||||||
/* resume data packet rx and tx */
|
/* resume data packet rx and tx */
|
||||||
conn->llcp_enc.pause_rx = 0U;
|
conn->llcp_enc.pause_rx = 0U;
|
||||||
conn->llcp_enc.pause_tx = 0U;
|
conn->llcp_enc.pause_tx = 0U;
|
||||||
|
|
||||||
/* If the encryption procedure interrupted another procedcure,
|
|
||||||
* continue that procedure
|
|
||||||
*/
|
|
||||||
if (conn->llcp.encryption.pend_llcp_type != LLCP_NONE) {
|
|
||||||
conn->llcp_type = conn->llcp.encryption.pend_llcp_type;
|
|
||||||
conn->llcp.encryption.pend_llcp_type = LLCP_NONE;
|
|
||||||
/* return now to prevent the 'procedure request acked',
|
|
||||||
* below, otherwise the ack/req flow prevents the
|
|
||||||
* interrupted procedure to run.
|
|
||||||
*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
|
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3721,14 +3757,17 @@ static inline void event_phy_upd_ind_prep(struct ll_conn *conn,
|
||||||
struct node_rx_pdu *rx;
|
struct node_rx_pdu *rx;
|
||||||
uint8_t old_tx, old_rx;
|
uint8_t old_tx, old_rx;
|
||||||
|
|
||||||
if (conn->llcp.encryption.pend_llcp_type == LLCP_NONE) {
|
#if defined(CONFIG_BT_PERIPHERAL)
|
||||||
|
if (conn->lll.role && (conn->slave.llcp_type != LLCP_NONE)) {
|
||||||
|
/* Local peripheral initiated PHY update completed while
|
||||||
|
* a remote central had initiated encryption procedure
|
||||||
|
*/
|
||||||
|
conn->slave.llcp_type = LLCP_NONE;
|
||||||
|
} else
|
||||||
|
#endif /* CONFIG_BT_PERIPHERAL */
|
||||||
|
{
|
||||||
/* procedure request acked */
|
/* procedure request acked */
|
||||||
conn->llcp_ack = conn->llcp_req;
|
conn->llcp_ack = conn->llcp_req;
|
||||||
} else {
|
|
||||||
/* PHY Update completed, so clear the
|
|
||||||
* pending procedure
|
|
||||||
*/
|
|
||||||
conn->llcp.encryption.pend_llcp_type = LLCP_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply new phy */
|
/* apply new phy */
|
||||||
|
@ -5510,17 +5549,19 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_PHY)
|
#if defined(CONFIG_BT_CTLR_PHY)
|
||||||
/* LL_ENC_REQ was received while LLCP_PHY_UPD was running */
|
/* LL_ENC_REQ was received while local peripheral initiated
|
||||||
if (conn->llcp_type == LLCP_PHY_UPD &&
|
* procedure is in progress.
|
||||||
conn->llcp_ack != conn->llcp_req) {
|
*/
|
||||||
/* Adjust ack due to decrement below, to prevent
|
if (unlikely(((conn->llcp_req - conn->llcp_ack) & 0x03) ==
|
||||||
* failures
|
0x02)) {
|
||||||
*/
|
/* Adjust ack due to decrement below, to prevent
|
||||||
|
* failures
|
||||||
|
*/
|
||||||
conn->llcp_ack += 2U;
|
conn->llcp_ack += 2U;
|
||||||
/* Remember that LLCP_PHY_UPD was interrupted */
|
|
||||||
conn->llcp.encryption.pend_llcp_type = LLCP_PHY_UPD;
|
/* Store the local peripheral initiated procedure */
|
||||||
} else {
|
LL_ASSERT(conn->slave.llcp_type == LLCP_NONE);
|
||||||
conn->llcp.encryption.pend_llcp_type = LLCP_NONE;
|
conn->slave.llcp_type = conn->llcp_type;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_CTLR_PHY */
|
#endif /* CONFIG_BT_CTLR_PHY */
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,9 @@ struct ll_conn {
|
||||||
#endif /* CONFIG_BT_CTLR_CONN_META */
|
#endif /* CONFIG_BT_CTLR_CONN_META */
|
||||||
uint8_t latency_cancel:1;
|
uint8_t latency_cancel:1;
|
||||||
uint8_t sca:3;
|
uint8_t sca:3;
|
||||||
|
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||||
|
uint8_t llcp_type;
|
||||||
|
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||||
#if defined(CONFIG_BT_CTLR_CONN_RANDOM_FORCE)
|
#if defined(CONFIG_BT_CTLR_CONN_RANDOM_FORCE)
|
||||||
uint32_t force;
|
uint32_t force;
|
||||||
#endif /* CONFIG_BT_CTLR_CONN_RANDOM_FORCE */
|
#endif /* CONFIG_BT_CTLR_CONN_RANDOM_FORCE */
|
||||||
|
@ -94,6 +97,7 @@ struct ll_conn {
|
||||||
|
|
||||||
uint8_t llcp_req;
|
uint8_t llcp_req;
|
||||||
uint8_t llcp_ack;
|
uint8_t llcp_ack;
|
||||||
|
|
||||||
uint8_t llcp_type;
|
uint8_t llcp_type;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -128,7 +132,6 @@ struct ll_conn {
|
||||||
LLCP_ENC_STATE_INIT,
|
LLCP_ENC_STATE_INIT,
|
||||||
LLCP_ENC_STATE_LTK_WAIT,
|
LLCP_ENC_STATE_LTK_WAIT,
|
||||||
} state:2 __packed;
|
} state:2 __packed;
|
||||||
uint8_t pend_llcp_type;
|
|
||||||
uint8_t error_code;
|
uint8_t error_code;
|
||||||
uint8_t skd[16];
|
uint8_t skd[16];
|
||||||
} encryption;
|
} encryption;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue