From 70a89876d06fed034b32c0002db267874a9dd28e Mon Sep 17 00:00:00 2001 From: Vinayak Kariappa Chettimada Date: Wed, 26 Jun 2019 18:27:54 +0530 Subject: [PATCH] Bluetooth: controller: Fix missing data length update event Fix missing generation of data length update HCI event when effective tx and rx timings change due to PHY update procedure. Fixes BT LL TS 5.1.0 test: LL/CON/MAS/BV-52-C [Master Receiving Data, LE Coded, CI Change] Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/ll_sw/ctrl.c | 79 ++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index 12ef96dbdca..6a7c7722a8a 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -8405,6 +8405,7 @@ static inline void event_phy_upd_ind_prep(struct connection *conn, } else if (((event_counter - conn->llcp.phy_upd_ind.instant) & 0xFFFF) <= 0x7FFF) { struct radio_pdu_node_rx *node_rx; + u16_t eff_tx_time, eff_rx_time; u8_t old_tx, old_rx; /* procedure request acked */ @@ -8413,11 +8414,52 @@ static inline void event_phy_upd_ind_prep(struct connection *conn, /* apply new phy */ old_tx = conn->phy_tx; old_rx = conn->phy_rx; + eff_tx_time = conn->max_tx_time; + eff_rx_time = conn->max_rx_time; if (conn->llcp.phy_upd_ind.tx) { + u16_t tx_time; + conn->phy_tx = conn->llcp.phy_upd_ind.tx; + + tx_time = RADIO_PKT_TIME(conn->max_tx_octets, + conn->phy_tx); + if (tx_time >= + RADIO_PKT_TIME(PDU_DC_PAYLOAD_SIZE_MIN, 0)) { + eff_tx_time = MIN(tx_time, + conn->default_tx_time); +#if defined(CONFIG_BT_CTLR_PHY_CODED) + eff_tx_time = MAX(eff_tx_time, + RADIO_PKT_TIME(PDU_DC_PAYLOAD_SIZE_MIN, + conn->phy_tx)); +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } else { + eff_tx_time = + RADIO_PKT_TIME(PDU_DC_PAYLOAD_SIZE_MIN, + 0); + } } if (conn->llcp.phy_upd_ind.rx) { + u16_t rx_time; + conn->phy_rx = conn->llcp.phy_upd_ind.rx; + + rx_time = RADIO_PKT_TIME(conn->max_rx_octets, + conn->phy_rx); + if (rx_time >= + RADIO_PKT_TIME(PDU_DC_PAYLOAD_SIZE_MIN, 0)) { + eff_rx_time = MIN(rx_time, + RADIO_PKT_TIME(LL_LENGTH_OCTETS_RX_MAX, + BIT(2))); +#if defined(CONFIG_BT_CTLR_PHY_CODED) + eff_rx_time = MAX(eff_rx_time, + RADIO_PKT_TIME(PDU_DC_PAYLOAD_SIZE_MIN, + conn->phy_rx)); +#endif /* CONFIG_BT_CTLR_PHY_CODED */ + } else { + eff_rx_time = + RADIO_PKT_TIME(PDU_DC_PAYLOAD_SIZE_MIN, + 0); + } } conn->phy_flags = conn->phy_pref_flags; @@ -8427,6 +8469,7 @@ static inline void event_phy_upd_ind_prep(struct connection *conn, return; } + /* Prepare the rx packet structure */ node_rx = packet_rx_reserve_get(2); LL_ASSERT(node_rx); @@ -8438,7 +8481,43 @@ static inline void event_phy_upd_ind_prep(struct connection *conn, upd->tx = conn->phy_tx; upd->rx = conn->phy_rx; + /* enqueue phy update structure into rx queue */ packet_rx_enqueue(); + + /* Update max tx and/or max rx if changed */ + if ((eff_tx_time == conn->max_tx_time) && + (eff_rx_time == conn->max_rx_time)) { + return; + } + conn->max_tx_time = eff_tx_time; + conn->max_rx_time = eff_rx_time; + +#if defined(CONFIG_BT_CTLR_DATA_LENGTH) + /* Prepare the rx packet structure */ + node_rx = packet_rx_reserve_get(2); + LL_ASSERT(node_rx); + node_rx->hdr.handle = conn->handle; + node_rx->hdr.type = NODE_RX_TYPE_DC_PDU; + + /* prepare length rsp structure */ + struct pdu_data *pdu_ctrl_rx = (void *)node_rx->pdu_data; + + pdu_ctrl_rx->ll_id = PDU_DATA_LLID_CTRL; + pdu_ctrl_rx->len = + offsetof(struct pdu_data_llctrl, length_rsp) + + sizeof(struct pdu_data_llctrl_length_rsp); + pdu_ctrl_rx->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_LENGTH_RSP; + + struct pdu_data_llctrl_length_req *lr = + (void *)&pdu_ctrl_rx->llctrl.length_rsp; + lr->max_rx_octets = conn->max_rx_octets; + lr->max_tx_octets = conn->max_tx_octets; + lr->max_rx_time = conn->max_rx_time; + lr->max_tx_time = conn->max_tx_time; + + /* enqueue length rsp structure into rx queue */ + packet_rx_enqueue(); +#endif /* CONFIG_BT_CTLR_DATA_LENGTH */ } } #endif /* CONFIG_BT_CTLR_PHY */