@@ -165,11 +165,14 @@ static uint8_t force_md_cnt_calc(struct lll_conn *lll_conn, uint32_t tx_rate);
165165 offsetof(struct pdu_data, llctrl) + \
166166 sizeof(struct pdu_data_llctrl))
167167
168+ /* Terminate procedure state values */
169+ #define TERM_REQ 1
170+ #define TERM_ACKED 3
171+
168172static MFIFO_DEFINE (conn_tx , sizeof (struct lll_tx ), CONFIG_BT_CTLR_TX_BUFFERS );
169173static MFIFO_DEFINE (conn_ack , sizeof (struct lll_tx ),
170174 (CONFIG_BT_CTLR_TX_BUFFERS + CONN_TX_CTRL_BUFFERS ));
171175
172-
173176static struct {
174177 void * free ;
175178 uint8_t pool [CONN_TX_BUF_SIZE * CONFIG_BT_CTLR_TX_BUFFERS ];
@@ -458,18 +461,21 @@ uint8_t ll_terminate_ind_send(uint16_t handle, uint8_t reason)
458461{
459462 struct ll_conn * conn ;
460463
461- if (!is_valid_disconnect_reason (reason )) {
462- return BT_HCI_ERR_INVALID_PARAM ;
463- }
464-
465464 conn = ll_connected_get (handle );
466465 if (!conn ) {
467466 return BT_HCI_ERR_UNKNOWN_CONN_ID ;
468467 }
469468
470- conn -> llcp_terminate .reason_own = reason ;
469+ if (conn -> llcp_terminate .req != conn -> llcp_terminate .ack ) {
470+ return BT_HCI_ERR_CMD_DISALLOWED ;
471+ }
471472
472- conn -> llcp_terminate .req ++ ;
473+ if (!is_valid_disconnect_reason (reason )) {
474+ return BT_HCI_ERR_INVALID_PARAM ;
475+ }
476+
477+ conn -> llcp_terminate .reason_own = reason ;
478+ conn -> llcp_terminate .req ++ ; /* (req - ack) == 1, TERM_REQ */
473479
474480 if (IS_ENABLED (CONFIG_BT_PERIPHERAL ) && conn -> lll .role ) {
475481 ull_slave_latency_cancel (conn , handle );
@@ -1109,15 +1115,18 @@ int ull_conn_llcp(struct ll_conn *conn, uint32_t ticks_at_expire, uint16_t lazy)
11091115#endif /* CONFIG_BT_PERIPHERAL && CONFIG_BT_CTLR_LE_ENC */
11101116
11111117 /* Terminate Procedure Request */
1112- if (conn -> llcp_terminate .ack != conn -> llcp_terminate .req ) {
1118+ if (((conn -> llcp_terminate .req - conn -> llcp_terminate .ack ) & 0xFF ) ==
1119+ TERM_REQ ) {
11131120 struct node_tx * tx ;
11141121
11151122 tx = mem_acquire (& mem_conn_tx_ctrl .free );
11161123 if (tx ) {
11171124 struct pdu_data * pdu_tx = (void * )tx -> pdu ;
11181125
1119- /* Terminate Procedure acked */
1120- conn -> llcp_terminate .ack = conn -> llcp_terminate .req ;
1126+ /* Terminate Procedure initiated,
1127+ * make (req - ack) == 2
1128+ */
1129+ conn -> llcp_terminate .ack -- ;
11211130
11221131 /* place the terminate ind packet in tx queue */
11231132 pdu_tx -> ll_id = PDU_DATA_LLID_CTRL ;
@@ -1212,8 +1221,10 @@ void ull_conn_done(struct node_rx_event_done *done)
12121221 }
12131222#endif /* CONFIG_BT_CTLR_LE_ENC */
12141223
1215- /* Master transmitted ack for the received terminate ind or
1216- * Slave received terminate ind or MIC failure
1224+ /* Peripheral received terminate ind or
1225+ * Central received ack for the transmitted terminate ind or
1226+ * Central transmitted ack for the received terminate ind or
1227+ * there has been MIC failure
12171228 */
12181229 reason_final = conn -> llcp_terminate .reason_final ;
12191230 if (reason_final && (
@@ -1223,6 +1234,9 @@ void ull_conn_done(struct node_rx_event_done *done)
12231234 0 ||
12241235#endif /* CONFIG_BT_PERIPHERAL */
12251236#if defined(CONFIG_BT_CENTRAL )
1237+ (((conn -> llcp_terminate .req -
1238+ conn -> llcp_terminate .ack ) & 0xFF ) ==
1239+ TERM_ACKED ) ||
12261240 conn -> master .terminate_ack ||
12271241 (reason_final == BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL )
12281242#else /* CONFIG_BT_CENTRAL */
@@ -5576,6 +5590,11 @@ static inline void ctrl_tx_ack(struct ll_conn *conn, struct node_tx **tx,
55765590 conn -> llcp_terminate .reason_final =
55775591 pdu_tx -> llctrl .terminate_ind .error_code ;
55785592 }
5593+
5594+ /* Make (req - ack) == 3, a state indicating terminate_ind has
5595+ * been ack-ed.
5596+ */
5597+ conn -> llcp_terminate .ack -- ;
55795598 }
55805599 break ;
55815600
0 commit comments