Bluetooth: controller: split: Port Enc setup to be queueable
Port the fix for the controller implementation to make start encryption queueable if there is any control procedure in progress. Refer to #15335. Relates to #15335, #15186, #15958 and #14636. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
69fc29de4d
commit
79cb615770
5 changed files with 178 additions and 124 deletions
|
@ -564,11 +564,6 @@ u8_t ll_adv_enable(u8_t enable)
|
|||
conn_lll->nesn = 0;
|
||||
conn_lll->empty = 0;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
conn_lll->enc_rx = 0;
|
||||
conn_lll->enc_tx = 0;
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
conn_lll->max_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
|
||||
conn_lll->max_rx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
|
||||
|
@ -627,7 +622,10 @@ u8_t ll_adv_enable(u8_t enable)
|
|||
conn->llcp_terminate.node_rx.hdr.link = link;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
conn->pause_tx = conn->pause_rx = conn->refresh = 0;
|
||||
conn_lll->enc_rx = conn_lll->enc_tx = 0U;
|
||||
conn->llcp_enc.req = conn->llcp_enc.ack = 0U;
|
||||
conn->llcp_enc.pause_tx = conn->llcp_enc.pause_rx = 0U;
|
||||
conn->llcp_enc.refresh = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
|
|
|
@ -57,6 +57,7 @@ static inline void event_ch_map_prep(struct ll_conn *conn,
|
|||
static void terminate_ind_rx_enqueue(struct ll_conn *conn, u8_t reason);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
static bool is_enc_req_pause_tx(struct ll_conn *conn);
|
||||
static inline void event_enc_prep(struct ll_conn *conn);
|
||||
static int enc_rsp_send(struct ll_conn *conn);
|
||||
static int start_enc_rsp_send(struct ll_conn *conn,
|
||||
|
@ -674,7 +675,7 @@ int ull_conn_rx(memq_link_t *link, struct node_rx_pdu **rx)
|
|||
case PDU_DATA_LLID_DATA_CONTINUE:
|
||||
case PDU_DATA_LLID_DATA_START:
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
if (conn->pause_rx) {
|
||||
if (conn->llcp_enc.pause_rx) {
|
||||
conn->llcp_terminate.reason_peer =
|
||||
BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;
|
||||
|
||||
|
@ -687,7 +688,7 @@ int ull_conn_rx(memq_link_t *link, struct node_rx_pdu **rx)
|
|||
case PDU_DATA_LLID_RESV:
|
||||
default:
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
if (conn->pause_rx) {
|
||||
if (conn->llcp_enc.pause_rx) {
|
||||
conn->llcp_terminate.reason_peer =
|
||||
BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;
|
||||
}
|
||||
|
@ -715,7 +716,7 @@ int ull_conn_llcp(struct ll_conn *conn, u32_t ticks_at_expire, u16_t lazy)
|
|||
*/
|
||||
if ((conn->llcp_ack == conn->llcp_req) &&
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
!conn->pause_rx) {
|
||||
!conn->llcp_enc.pause_rx) {
|
||||
#else /* !CONFIG_BT_CTLR_LE_ENC */
|
||||
1) {
|
||||
#endif /* !CONFIG_BT_CTLR_LE_ENC */
|
||||
|
@ -736,6 +737,13 @@ int ull_conn_llcp(struct ll_conn *conn, u32_t ticks_at_expire, u16_t lazy)
|
|||
ticks_at_expire);
|
||||
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
/* check if procedure is requested */
|
||||
} else if (conn->llcp_length.ack != conn->llcp_length.req) {
|
||||
/* handle DLU state machine */
|
||||
event_len_prep(conn);
|
||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
/* check if PHY Req procedure is requested */
|
||||
} else if (conn->llcp_phy.ack != conn->llcp_phy.req) {
|
||||
|
@ -819,14 +827,6 @@ int ull_conn_llcp(struct ll_conn *conn, u32_t ticks_at_expire, u16_t lazy)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
/* check if procedure is requested */
|
||||
if (conn->llcp_length.ack != conn->llcp_length.req) {
|
||||
/* handle DLU state machine */
|
||||
event_len_prep(conn);
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||
|
||||
/* Terminate Procedure Request */
|
||||
if (conn->llcp_terminate.ack != conn->llcp_terminate.req) {
|
||||
struct node_tx *tx;
|
||||
|
@ -891,7 +891,7 @@ void ull_conn_done(struct node_rx_event_done *done)
|
|||
switch (done->extra.mic_state) {
|
||||
case LLL_CONN_MIC_NONE:
|
||||
#if defined(CONFIG_BT_CTLR_LE_PING)
|
||||
if (lll->enc_rx || conn->pause_rx) {
|
||||
if (lll->enc_rx || conn->llcp_enc.pause_rx) {
|
||||
u16_t appto_reload_new;
|
||||
|
||||
/* check for change in apto */
|
||||
|
@ -1190,42 +1190,43 @@ void ull_conn_tx_demux(u8_t count)
|
|||
|
||||
void ull_conn_tx_lll_enqueue(struct ll_conn *conn, u8_t count)
|
||||
{
|
||||
struct node_tx *tx;
|
||||
bool pause_tx = false;
|
||||
|
||||
tx = conn->tx_head;
|
||||
while (tx &&
|
||||
while (conn->tx_head &&
|
||||
((
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
!conn->pause_tx &&
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
!conn->llcp_length.pause_tx &&
|
||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
!conn->llcp_phy.pause_tx &&
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
1) || (tx == conn->tx_ctrl)) && count--) {
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
!conn->llcp_enc.pause_tx &&
|
||||
!(pause_tx = is_enc_req_pause_tx(conn)) &&
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
1) ||
|
||||
(!pause_tx && (conn->tx_head == conn->tx_ctrl))) && count--) {
|
||||
struct node_tx *tx_lll;
|
||||
memq_link_t *link;
|
||||
|
||||
tx_lll = tx;
|
||||
tx_lll = conn->tx_head;
|
||||
|
||||
if (tx == conn->tx_ctrl) {
|
||||
tx = conn->tx_head = conn->tx_head->next;
|
||||
if (conn->tx_head == conn->tx_ctrl) {
|
||||
conn->tx_head = conn->tx_head->next;
|
||||
if (conn->tx_ctrl == conn->tx_ctrl_last) {
|
||||
conn->tx_ctrl = NULL;
|
||||
conn->tx_ctrl_last = NULL;
|
||||
} else {
|
||||
conn->tx_ctrl = tx;
|
||||
conn->tx_ctrl = conn->tx_head;
|
||||
}
|
||||
|
||||
/* point to self to indicate a control PDU mem alloc */
|
||||
tx_lll->next = tx_lll;
|
||||
} else {
|
||||
if (tx == conn->tx_data) {
|
||||
if (conn->tx_head == conn->tx_data) {
|
||||
conn->tx_data = conn->tx_data->next;
|
||||
}
|
||||
tx = conn->tx_head = conn->tx_head->next;
|
||||
conn->tx_head = conn->tx_head->next;
|
||||
}
|
||||
|
||||
link = mem_acquire(&mem_link_tx.free);
|
||||
|
@ -1510,7 +1511,7 @@ static void ctrl_tx_enqueue(struct ll_conn *conn, struct node_tx *tx)
|
|||
/* data/ctrl packet is in the head */
|
||||
conn->tx_head &&
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
!conn->pause_tx &&
|
||||
!conn->llcp_enc.pause_tx &&
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
!conn->llcp_length.pause_tx &&
|
||||
|
@ -1567,7 +1568,7 @@ static void ctrl_tx_enqueue(struct ll_conn *conn, struct node_tx *tx)
|
|||
static void ctrl_tx_sec_enqueue(struct ll_conn *conn, struct node_tx *tx)
|
||||
{
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
if (conn->pause_tx) {
|
||||
if (conn->llcp_enc.pause_tx) {
|
||||
if (!conn->tx_ctrl) {
|
||||
tx->next = conn->tx_head;
|
||||
conn->tx_head = tx;
|
||||
|
@ -1583,6 +1584,65 @@ static void ctrl_tx_sec_enqueue(struct ll_conn *conn, struct node_tx *tx)
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
static bool is_enc_req_pause_tx(struct ll_conn *conn)
|
||||
{
|
||||
struct pdu_data *pdu_data_tx;
|
||||
|
||||
pdu_data_tx = (void *)conn->tx_head->pdu;
|
||||
if ((pdu_data_tx->ll_id == PDU_DATA_LLID_CTRL) &&
|
||||
(pdu_data_tx->llctrl.opcode == PDU_DATA_LLCTRL_TYPE_ENC_REQ)) {
|
||||
if ((conn->llcp_req != conn->llcp_ack) ||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
(conn->llcp_conn_param.ack != conn->llcp_conn_param.req) ||
|
||||
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
(conn->llcp_length.ack != conn->llcp_length.req) ||
|
||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
(conn->llcp_phy.ack != conn->llcp_phy.req) ||
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
0) {
|
||||
struct node_tx *tx;
|
||||
|
||||
/* if we have control packets enqueued after this PDU
|
||||
* bring it ahead, and move the enc_req to last of
|
||||
* ctrl queue.
|
||||
*/
|
||||
tx = conn->tx_head;
|
||||
if ((tx->next != NULL) &&
|
||||
(tx->next == conn->tx_ctrl)) {
|
||||
conn->tx_head = tx->next;
|
||||
tx->next = conn->tx_ctrl_last->next;
|
||||
conn->tx_ctrl_last->next = tx;
|
||||
conn->tx_data = tx;
|
||||
if (!conn->tx_data_last) {
|
||||
conn->tx_data_last = tx;
|
||||
}
|
||||
|
||||
/* Head now contains a control packet permitted
|
||||
* to be transmitted to peer.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Head contains ENC_REQ packet deferred due to another
|
||||
* control procedure in progress.
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
conn->llcp.encryption.initiate = 1U;
|
||||
|
||||
conn->llcp_type = LLCP_ENCRYPTION;
|
||||
conn->llcp_ack -= 2U;
|
||||
}
|
||||
|
||||
/* Head contains a permitted data or control packet. */
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
||||
static inline void event_conn_upd_init(struct ll_conn *conn,
|
||||
u16_t event_counter,
|
||||
u32_t ticks_at_expire,
|
||||
|
@ -2046,9 +2106,9 @@ static inline void event_enc_prep(struct ll_conn *conn)
|
|||
/* master sends encrypted enc start rsp in control priority */
|
||||
if (!lll->role) {
|
||||
/* calc the Session Key */
|
||||
ecb_encrypt(&conn->llcp.encryption.ltk[0],
|
||||
&conn->llcp.encryption.skd[0],
|
||||
NULL, &lll->ccm_rx.key[0]);
|
||||
ecb_encrypt(&conn->llcp_enc.ltk[0],
|
||||
&conn->llcp.encryption.skd[0], NULL,
|
||||
&lll->ccm_rx.key[0]);
|
||||
|
||||
/* copy the Session Key */
|
||||
memcpy(&lll->ccm_tx.key[0], &lll->ccm_rx.key[0],
|
||||
|
@ -2080,7 +2140,7 @@ static inline void event_enc_prep(struct ll_conn *conn)
|
|||
#if defined(CONFIG_BT_CTLR_FAST_ENC)
|
||||
else {
|
||||
#else /* !CONFIG_BT_CTLR_FAST_ENC */
|
||||
else if (!conn->pause_tx || conn->refresh) {
|
||||
else if (!conn->llcp_enc.pause_tx || conn->llcp_enc.refresh) {
|
||||
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
|
||||
|
||||
/* place the reject ind packet as next in tx queue */
|
||||
|
@ -2106,7 +2166,7 @@ static inline void event_enc_prep(struct ll_conn *conn)
|
|||
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
|
||||
|
||||
/* calc the Session Key */
|
||||
ecb_encrypt(&conn->llcp.encryption.ltk[0],
|
||||
ecb_encrypt(&conn->llcp_enc.ltk[0],
|
||||
&conn->llcp.encryption.skd[0], NULL,
|
||||
&lll->ccm_rx.key[0]);
|
||||
|
||||
|
@ -2120,20 +2180,20 @@ static inline void event_enc_prep(struct ll_conn *conn)
|
|||
sizeof(lll->ccm_tx.iv));
|
||||
|
||||
/* initialise counter */
|
||||
lll->ccm_rx.counter = 0;
|
||||
lll->ccm_tx.counter = 0;
|
||||
lll->ccm_rx.counter = 0U;
|
||||
lll->ccm_tx.counter = 0U;
|
||||
|
||||
/* set direction: slave to master = 0,
|
||||
* master to slave = 1
|
||||
*/
|
||||
lll->ccm_rx.direction = 1;
|
||||
lll->ccm_tx.direction = 0;
|
||||
lll->ccm_rx.direction = 1U;
|
||||
lll->ccm_tx.direction = 0U;
|
||||
|
||||
/* enable receive encryption (transmit turned
|
||||
* on when start enc resp from master is
|
||||
* received)
|
||||
*/
|
||||
lll->enc_rx = 1;
|
||||
lll->enc_rx = 1U;
|
||||
|
||||
/* prepare the start enc req */
|
||||
pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
|
||||
|
@ -2149,8 +2209,8 @@ static inline void event_enc_prep(struct ll_conn *conn)
|
|||
start_enc_rsp_send(conn, pdu_ctrl_tx);
|
||||
|
||||
/* resume data packet rx and tx */
|
||||
conn->pause_rx = 0;
|
||||
conn->pause_tx = 0;
|
||||
conn->llcp_enc.pause_rx = 0U;
|
||||
conn->llcp_enc.pause_tx = 0U;
|
||||
#endif /* !CONFIG_BT_CTLR_FAST_ENC */
|
||||
|
||||
}
|
||||
|
@ -2518,7 +2578,7 @@ static inline void event_conn_param_app_req(struct ll_conn *conn)
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
/* defer until encryption setup is complete */
|
||||
if (conn->pause_tx) {
|
||||
if (conn->llcp_enc.pause_tx) {
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
@ -2762,7 +2822,7 @@ static inline void event_phy_req_prep(struct ll_conn *conn)
|
|||
conn->phy_pref_flags = conn->llcp_phy.flags;
|
||||
|
||||
/* pause data packet tx */
|
||||
conn->llcp_phy.pause_tx = 1;
|
||||
conn->llcp_phy.pause_tx = 1U;
|
||||
|
||||
/* place the phy req packet as next in tx queue */
|
||||
pdu_ctrl_tx = (void *)tx->pdu;
|
||||
|
@ -3116,13 +3176,10 @@ static void enc_req_reused_send(struct ll_conn *conn, struct node_tx **tx)
|
|||
pdu_ctrl_tx->len = offsetof(struct pdu_data_llctrl, enc_req) +
|
||||
sizeof(struct pdu_data_llctrl_enc_req);
|
||||
pdu_ctrl_tx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_ENC_REQ;
|
||||
memcpy(&pdu_ctrl_tx->llctrl.enc_req.rand[0],
|
||||
&conn->llcp.encryption.rand[0],
|
||||
memcpy(&pdu_ctrl_tx->llctrl.enc_req.rand[0], &conn->llcp_enc.rand[0],
|
||||
sizeof(pdu_ctrl_tx->llctrl.enc_req.rand));
|
||||
pdu_ctrl_tx->llctrl.enc_req.ediv[0] =
|
||||
conn->llcp.encryption.ediv[0];
|
||||
pdu_ctrl_tx->llctrl.enc_req.ediv[1] =
|
||||
conn->llcp.encryption.ediv[1];
|
||||
pdu_ctrl_tx->llctrl.enc_req.ediv[0] = conn->llcp_enc.ediv[0];
|
||||
pdu_ctrl_tx->llctrl.enc_req.ediv[1] = conn->llcp_enc.ediv[1];
|
||||
|
||||
/*
|
||||
* Take advantage of the fact that ivm and skdm fields, which both have
|
||||
|
@ -3218,13 +3275,13 @@ static int start_enc_rsp_send(struct ll_conn *conn,
|
|||
static inline bool ctrl_is_unexpected(struct ll_conn *conn, u8_t opcode)
|
||||
{
|
||||
return (!conn->lll.role &&
|
||||
((!conn->refresh &&
|
||||
((!conn->llcp_enc.refresh &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_REQ) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_RSP) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_REJECT_IND) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND)) ||
|
||||
(conn->refresh &&
|
||||
(conn->llcp_enc.refresh &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_ENC_RSP) &&
|
||||
|
@ -3233,13 +3290,13 @@ static inline bool ctrl_is_unexpected(struct ll_conn *conn, u8_t opcode)
|
|||
(opcode != PDU_DATA_LLCTRL_TYPE_REJECT_IND) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND)))) ||
|
||||
(conn->lll.role &&
|
||||
((!conn->refresh &&
|
||||
((!conn->llcp_enc.refresh &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_START_ENC_RSP) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_REJECT_IND) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND)) ||
|
||||
(conn->refresh &&
|
||||
(conn->llcp_enc.refresh &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_TERMINATE_IND) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_RSP) &&
|
||||
(opcode != PDU_DATA_LLCTRL_TYPE_ENC_REQ) &&
|
||||
|
@ -3362,7 +3419,7 @@ static int pause_enc_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx,
|
|||
}
|
||||
|
||||
/* key refresh */
|
||||
conn->refresh = 1U;
|
||||
conn->llcp_enc.refresh = 1U;
|
||||
} else if (!conn->lll.role) {
|
||||
/* acquire tx mem */
|
||||
tx = mem_acquire(&mem_conn_tx_ctrl.free);
|
||||
|
@ -3380,7 +3437,7 @@ static int pause_enc_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx,
|
|||
}
|
||||
|
||||
/* pause data packet rx */
|
||||
conn->pause_rx = 1U;
|
||||
conn->llcp_enc.pause_rx = 1U;
|
||||
|
||||
/* disable receive encryption */
|
||||
conn->lll.enc_rx = 0;
|
||||
|
@ -3683,8 +3740,8 @@ static void reject_ext_ind_recv(struct ll_conn *conn, struct node_rx_pdu *rx,
|
|||
switch (rej_ext_ind->reject_opcode) {
|
||||
case PDU_DATA_LLCTRL_TYPE_ENC_REQ:
|
||||
/* resume data packet rx and tx */
|
||||
conn->pause_rx = 0U;
|
||||
conn->pause_tx = 0U;
|
||||
conn->llcp_enc.pause_rx = 0U;
|
||||
conn->llcp_enc.pause_tx = 0U;
|
||||
|
||||
/* Procedure complete */
|
||||
conn->procedure_expire = 0U;
|
||||
|
@ -4010,7 +4067,7 @@ static int phy_rsp_send(struct ll_conn *conn, struct node_rx_pdu *rx,
|
|||
conn->llcp_phy.rx &= p->tx_phys;
|
||||
|
||||
/* pause data packet tx */
|
||||
conn->llcp_phy.pause_tx = 1;
|
||||
conn->llcp_phy.pause_tx = 1U;
|
||||
|
||||
pdu_ctrl_tx = (void *)tx->pdu;
|
||||
pdu_ctrl_tx->ll_id = PDU_DATA_LLID_CTRL;
|
||||
|
@ -4146,18 +4203,21 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx,
|
|||
&pdu_tx->llctrl.enc_req.ivm[0], 4);
|
||||
|
||||
/* pause data packet tx */
|
||||
conn->pause_tx = 1U;
|
||||
conn->llcp_enc.pause_tx = 1U;
|
||||
|
||||
/* Start Procedure Timeout (this will not replace terminate
|
||||
* procedure which always gets place before any packets
|
||||
* going out, hence safe by design).
|
||||
*/
|
||||
conn->procedure_expire = conn->procedure_reload;
|
||||
|
||||
/* Reset enc req queued state */
|
||||
conn->llcp_enc.ack = conn->llcp_enc.req;
|
||||
break;
|
||||
|
||||
case PDU_DATA_LLCTRL_TYPE_ENC_RSP:
|
||||
/* pause data packet tx */
|
||||
conn->pause_tx = 1U;
|
||||
conn->llcp_enc.pause_tx = 1U;
|
||||
break;
|
||||
|
||||
case PDU_DATA_LLCTRL_TYPE_START_ENC_REQ:
|
||||
|
@ -4169,10 +4229,10 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx,
|
|||
|
||||
case PDU_DATA_LLCTRL_TYPE_PAUSE_ENC_REQ:
|
||||
/* pause data packet tx */
|
||||
conn->pause_tx = 1U;
|
||||
conn->llcp_enc.pause_tx = 1U;
|
||||
|
||||
/* key refresh */
|
||||
conn->refresh = 1U;
|
||||
conn->llcp_enc.refresh = 1U;
|
||||
|
||||
/* Start Procedure Timeout (this will not replace terminate
|
||||
* procedure which always gets place before any packets
|
||||
|
@ -4187,7 +4247,7 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx,
|
|||
enc_req_reused_send(conn, tx);
|
||||
} else {
|
||||
/* pause data packet tx */
|
||||
conn->pause_tx = 1U;
|
||||
conn->llcp_enc.pause_tx = 1U;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -4200,8 +4260,8 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx,
|
|||
|
||||
case PDU_DATA_LLCTRL_TYPE_REJECT_IND:
|
||||
/* resume data packet rx and tx */
|
||||
conn->pause_rx = 0U;
|
||||
conn->pause_tx = 0U;
|
||||
conn->llcp_enc.pause_rx = 0U;
|
||||
conn->llcp_enc.pause_tx = 0U;
|
||||
|
||||
/* Procedure complete */
|
||||
conn->procedure_expire = 0U;
|
||||
|
@ -4242,13 +4302,13 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx,
|
|||
}
|
||||
|
||||
/* resume data packet tx */
|
||||
conn->llcp_phy.pause_tx = 0;
|
||||
conn->llcp_phy.pause_tx = 0U;
|
||||
break;
|
||||
|
||||
case PDU_DATA_LLCTRL_TYPE_PHY_UPD_IND:
|
||||
conn->lll.phy_tx_time = conn->llcp.phy_upd_ind.tx;
|
||||
/* resume data packet tx */
|
||||
conn->llcp_phy.pause_tx = 0;
|
||||
conn->llcp_phy.pause_tx = 0U;
|
||||
break;
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
||||
|
@ -4328,7 +4388,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
/* FIXME: do check in individual case to reduce CPU time */
|
||||
if (conn->pause_rx && ctrl_is_unexpected(conn, opcode)) {
|
||||
if (conn->llcp_enc.pause_rx && ctrl_is_unexpected(conn, opcode)) {
|
||||
conn->llcp_terminate.reason_peer =
|
||||
BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL;
|
||||
|
||||
|
@ -4412,7 +4472,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
&pdu_rx->llctrl.enc_req.ivm[0], 4);
|
||||
|
||||
/* pause rx data packets */
|
||||
conn->pause_rx = 1U;
|
||||
conn->llcp_enc.pause_rx = 1U;
|
||||
|
||||
/* Start Procedure Timeout (TODO: this shall not replace
|
||||
* terminate procedure).
|
||||
|
@ -4434,7 +4494,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
&pdu_rx->llctrl.enc_rsp.ivs[0], 4);
|
||||
|
||||
/* pause rx data packets */
|
||||
conn->pause_rx = 1U;
|
||||
conn->llcp_enc.pause_rx = 1U;
|
||||
|
||||
/* Mark for buffer for release */
|
||||
(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
|
||||
|
@ -4442,10 +4502,9 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
break;
|
||||
|
||||
case PDU_DATA_LLCTRL_TYPE_START_ENC_REQ:
|
||||
LL_ASSERT((conn->llcp_req == conn->llcp_ack) ||
|
||||
(conn->llcp_type == LLCP_ENCRYPTION));
|
||||
|
||||
if (conn->lll.role ||
|
||||
((conn->llcp_req != conn->llcp_ack) &&
|
||||
(conn->llcp_type != LLCP_ENCRYPTION)) ||
|
||||
!pdu_len_cmp(PDU_DATA_LLCTRL_TYPE_START_ENC_REQ,
|
||||
pdu_rx->len)) {
|
||||
goto ull_conn_rx_unknown_rsp_send;
|
||||
|
@ -4471,8 +4530,10 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
|
||||
if (conn->lll.role) {
|
||||
#if !defined(CONFIG_BT_CTLR_FAST_ENC)
|
||||
LL_ASSERT((conn->llcp_req == conn->llcp_ack) ||
|
||||
(conn->llcp_type == LLCP_ENCRYPTION));
|
||||
if ((conn->llcp_req != conn->llcp_ack) &&
|
||||
(conn->llcp_type != LLCP_ENCRYPTION)) {
|
||||
goto ull_conn_rx_unknown_rsp_send;
|
||||
}
|
||||
|
||||
/* start enc rsp to be scheduled in slave prepare */
|
||||
conn->llcp.encryption.initiate = 0U;
|
||||
|
@ -4487,19 +4548,19 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
}
|
||||
|
||||
/* resume data packet rx and tx */
|
||||
conn->pause_rx = 0U;
|
||||
conn->pause_tx = 0U;
|
||||
conn->llcp_enc.pause_rx = 0U;
|
||||
conn->llcp_enc.pause_tx = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_FAST_ENC */
|
||||
|
||||
} else {
|
||||
/* resume data packet rx and tx */
|
||||
conn->pause_rx = 0U;
|
||||
conn->pause_tx = 0U;
|
||||
conn->llcp_enc.pause_rx = 0U;
|
||||
conn->llcp_enc.pause_tx = 0U;
|
||||
}
|
||||
|
||||
/* enqueue the start enc resp (encryption change/refresh) */
|
||||
if (conn->refresh) {
|
||||
conn->refresh = 0U;
|
||||
if (conn->llcp_enc.refresh) {
|
||||
conn->llcp_enc.refresh = 0U;
|
||||
|
||||
/* key refresh event */
|
||||
(*rx)->hdr.type = NODE_RX_TYPE_ENC_REFRESH;
|
||||
|
@ -4579,8 +4640,8 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
}
|
||||
|
||||
/* resume data packet rx and tx */
|
||||
conn->pause_rx = 0U;
|
||||
conn->pause_tx = 0U;
|
||||
conn->llcp_enc.pause_rx = 0U;
|
||||
conn->llcp_enc.pause_tx = 0U;
|
||||
|
||||
/* Procedure complete */
|
||||
conn->procedure_expire = 0U;
|
||||
|
@ -4719,7 +4780,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
/* postpone CP request event if under
|
||||
* encryption setup
|
||||
*/
|
||||
if (conn->pause_tx) {
|
||||
if (conn->llcp_enc.pause_tx) {
|
||||
conn->llcp_conn_param.state =
|
||||
LLCP_CPR_STATE_APP_REQ;
|
||||
|
||||
|
@ -5036,7 +5097,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
|
||||
/* Procedure complete */
|
||||
conn->llcp_phy.ack = conn->llcp_phy.req;
|
||||
conn->llcp_phy.pause_tx = 0;
|
||||
conn->llcp_phy.pause_tx = 0U;
|
||||
|
||||
/* Reset packet timing restrictions */
|
||||
lll->phy_tx_time = lll->phy_tx;
|
||||
|
@ -5171,7 +5232,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
conn->llcp_phy.rx &= p->tx_phys;
|
||||
|
||||
/* pause data packet tx */
|
||||
conn->llcp_phy.pause_tx = 1;
|
||||
conn->llcp_phy.pause_tx = 1U;
|
||||
|
||||
/* Mark for buffer for release */
|
||||
(*rx)->hdr.type = NODE_RX_TYPE_DC_PDU_RELEASE;
|
||||
|
@ -5199,7 +5260,7 @@ static inline int ctrl_rx(memq_link_t *link, struct node_rx_pdu **rx,
|
|||
conn->llcp_phy.rx &= p->tx_phys;
|
||||
|
||||
/* pause data packet tx */
|
||||
conn->llcp_phy.pause_tx = 1;
|
||||
conn->llcp_phy.pause_tx = 1U;
|
||||
|
||||
/* Procedure timeout is stopped */
|
||||
conn->procedure_expire = 0U;
|
||||
|
|
|
@ -87,9 +87,6 @@ struct ll_conn {
|
|||
struct {
|
||||
u8_t initiate;
|
||||
u8_t error_code;
|
||||
u8_t rand[8];
|
||||
u8_t ediv[2];
|
||||
u8_t ltk[16];
|
||||
u8_t skd[16];
|
||||
} encryption;
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
@ -118,6 +115,19 @@ struct ll_conn {
|
|||
} node_rx;
|
||||
} llcp_terminate;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
struct {
|
||||
u8_t req;
|
||||
u8_t ack;
|
||||
u8_t pause_rx:1;
|
||||
u8_t pause_tx:1;
|
||||
u8_t refresh:1;
|
||||
u8_t ediv[2];
|
||||
u8_t rand[8];
|
||||
u8_t ltk[16];
|
||||
} llcp_enc;
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
struct {
|
||||
u8_t req;
|
||||
|
@ -191,12 +201,6 @@ struct ll_conn {
|
|||
u8_t phy_pref_rx:3;
|
||||
#endif /* CONFIG_BT_CTLR_PHY */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
u8_t pause_rx:1;
|
||||
u8_t pause_tx:1;
|
||||
u8_t refresh:1;
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
||||
struct node_tx *tx_head;
|
||||
struct node_tx *tx_ctrl;
|
||||
struct node_tx *tx_ctrl_last;
|
||||
|
|
|
@ -118,11 +118,6 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
|
|||
conn_lll->nesn = 0;
|
||||
conn_lll->empty = 0;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
conn_lll->enc_rx = 0;
|
||||
conn_lll->enc_tx = 0;
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
conn_lll->max_tx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
|
||||
conn_lll->max_rx_octets = PDU_DC_PAYLOAD_SIZE_MIN;
|
||||
|
@ -197,7 +192,10 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
|
|||
conn->llcp_terminate.node_rx.hdr.link = link;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_LE_ENC)
|
||||
conn->pause_tx = conn->pause_rx = conn->refresh = 0U;
|
||||
conn_lll->enc_rx = conn_lll->enc_tx = 0U;
|
||||
conn->llcp_enc.req = conn->llcp_enc.ack = 0U;
|
||||
conn->llcp_enc.pause_tx = conn->llcp_enc.pause_rx = 0U;
|
||||
conn->llcp_enc.refresh = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_LE_ENC */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
|
@ -337,16 +335,14 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk)
|
|||
{
|
||||
struct ll_conn *conn;
|
||||
struct node_tx *tx;
|
||||
u8_t ret;
|
||||
|
||||
conn = ll_connected_get(handle);
|
||||
if (!conn) {
|
||||
return BT_HCI_ERR_UNKNOWN_CONN_ID;
|
||||
}
|
||||
|
||||
ret = ull_conn_llcp_req(conn);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if (conn->llcp_enc.req != conn->llcp_enc.ack) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
tx = ll_tx_mem_acquire();
|
||||
|
@ -355,8 +351,7 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk)
|
|||
|
||||
pdu_data_tx = (void *)tx->pdu;
|
||||
|
||||
memcpy(&conn->llcp.encryption.ltk[0], ltk,
|
||||
sizeof(conn->llcp.encryption.ltk));
|
||||
memcpy(&conn->llcp_enc.ltk[0], ltk, sizeof(conn->llcp_enc.ltk));
|
||||
|
||||
if ((conn->lll.enc_rx == 0) && (conn->lll.enc_tx == 0)) {
|
||||
struct pdu_data_llctrl_enc_req *enc_req;
|
||||
|
@ -375,11 +370,11 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk)
|
|||
bt_rand(enc_req->skdm, sizeof(enc_req->skdm));
|
||||
bt_rand(enc_req->ivm, sizeof(enc_req->ivm));
|
||||
} else if ((conn->lll.enc_rx != 0) && (conn->lll.enc_tx != 0)) {
|
||||
memcpy(&conn->llcp.encryption.rand[0], rand,
|
||||
sizeof(conn->llcp.encryption.rand));
|
||||
memcpy(&conn->llcp_enc.rand[0], rand,
|
||||
sizeof(conn->llcp_enc.rand));
|
||||
|
||||
conn->llcp.encryption.ediv[0] = ediv[0];
|
||||
conn->llcp.encryption.ediv[1] = ediv[1];
|
||||
conn->llcp_enc.ediv[0] = ediv[0];
|
||||
conn->llcp_enc.ediv[1] = ediv[1];
|
||||
|
||||
pdu_data_tx->ll_id = PDU_DATA_LLID_CTRL;
|
||||
pdu_data_tx->len = offsetof(struct pdu_data_llctrl,
|
||||
|
@ -398,10 +393,7 @@ u8_t ll_enc_req_send(u16_t handle, u8_t *rand, u8_t *ediv, u8_t *ltk)
|
|||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
conn->llcp.encryption.initiate = 1U;
|
||||
|
||||
conn->llcp_type = LLCP_ENCRYPTION;
|
||||
conn->llcp_req++;
|
||||
conn->llcp_enc.req++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -393,7 +393,7 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
|
|||
}
|
||||
|
||||
if (error_code) {
|
||||
if (conn->refresh == 0U) {
|
||||
if (conn->llcp_enc.refresh == 0U) {
|
||||
ret = ull_conn_llcp_req(conn);
|
||||
if (ret) {
|
||||
return ret;
|
||||
|
@ -415,14 +415,13 @@ u8_t ll_start_enc_req_send(u16_t handle, u8_t error_code,
|
|||
conn->llcp_terminate.req++;
|
||||
}
|
||||
} else {
|
||||
memcpy(&conn->llcp.encryption.ltk[0], ltk,
|
||||
sizeof(conn->llcp.encryption.ltk));
|
||||
|
||||
ret = ull_conn_llcp_req(conn);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(&conn->llcp_enc.ltk[0], ltk, sizeof(conn->llcp_enc.ltk));
|
||||
|
||||
conn->llcp.encryption.error_code = 0U;
|
||||
conn->llcp.encryption.initiate = 0U;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue