Bluetooth: controller: Fix master terminate procedure

Fix master terminate procedure so that if slave responded to
the ack from master for the LL_TERMINATE_IND then the master
correctly disconnected.

This fixes TP/CON/MAS/BV-09-C [Master Accepting Termination]
in LL.TS.5.0.0.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
Tested-by: Ulrich Myhre <ulmy@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2017-07-05 12:09:40 +02:00 committed by Johan Hedberg
commit 52ee6622c0
2 changed files with 37 additions and 37 deletions

View file

@ -3011,6 +3011,7 @@ static inline void isr_close_conn(void)
u16_t ticks_drift_minus;
u16_t latency_event;
u16_t elapsed_event;
u8_t reason_peer;
u16_t lazy;
u8_t force;
@ -3019,11 +3020,13 @@ static inline void isr_close_conn(void)
return;
}
/* Remote Initiated terminate happened in this event for Slave */
if ((_radio.role == ROLE_SLAVE) &&
_radio.conn_curr->llcp_terminate.reason_peer) {
terminate_ind_rx_enqueue(_radio.conn_curr,
_radio.conn_curr->llcp_terminate.reason_peer);
/* Master transmitted ack for the received terminate ind or
* Slave received terminate ind.
*/
reason_peer = _radio.conn_curr->llcp_terminate.reason_peer;
if (reason_peer && ((_radio.role == ROLE_SLAVE) ||
_radio.conn_curr->master.terminate_ack)) {
terminate_ind_rx_enqueue(_radio.conn_curr, reason_peer);
connection_release(_radio.conn_curr);
_radio.conn_curr = NULL;
@ -3037,8 +3040,8 @@ static inline void isr_close_conn(void)
elapsed_event = latency_event + 1;
/* calculate drift if anchor point sync-ed */
if ((_radio.packet_counter != 0) && ((!SILENT_CONNECTION) ||
(_radio.packet_counter != 0xFF))) {
if (_radio.packet_counter &&
(!SILENT_CONNECTION || (_radio.packet_counter != 0xFF))) {
if (_radio.role == ROLE_SLAVE) {
u32_t start_to_address_expected_us;
u32_t start_to_address_actual_us;
@ -3092,23 +3095,14 @@ static inline void isr_close_conn(void)
_radio.conn_curr->latency_event =
_radio.conn_curr->latency;
}
} else if (reason_peer) {
_radio.conn_curr->master.terminate_ack = 1;
}
/* Reset connection failed to establish procedure */
_radio.conn_curr->connect_expire = 0;
}
/* Remote Initiated terminate happened in previous event for Master */
else if (_radio.conn_curr->llcp_terminate.reason_peer) {
terminate_ind_rx_enqueue(_radio.conn_curr,
_radio.conn_curr->llcp_terminate.reason_peer);
connection_release(_radio.conn_curr);
_radio.conn_curr = NULL;
return;
}
/* check connection failed to establish */
else if (_radio.conn_curr->connect_expire) {
if (_radio.conn_curr->connect_expire > elapsed_event) {
@ -7504,8 +7498,7 @@ static void terminate_ind_rx_enqueue(struct connection *conn, u8_t reason)
void *link;
/* Prepare the rx packet structure */
radio_pdu_node_rx =
(struct radio_pdu_node_rx *)&conn->llcp_terminate.radio_pdu_node_rx;
radio_pdu_node_rx = (void *)&conn->llcp_terminate.radio_pdu_node_rx;
LL_ASSERT(radio_pdu_node_rx->hdr.onion.link);
radio_pdu_node_rx->hdr.handle = conn->handle;
@ -8765,6 +8758,7 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
conn->role = 0;
conn->connect_expire = 6;
conn->master.terminate_ack = 0;
conn_interval_us =
(u32_t)_radio.scanner.conn_interval * 1250;
conn->supervision_reload =

View file

@ -90,19 +90,25 @@ struct connection {
u16_t apto_expire;
#endif /* CONFIG_BLUETOOTH_CONTROLLER_LE_PING */
struct {
u8_t latency_enabled:1;
u8_t latency_cancel:1;
u8_t sca:3;
u32_t window_widening_periodic_us;
u32_t window_widening_max_us;
u32_t window_widening_prepare_us;
u32_t window_widening_event_us;
u32_t window_size_prepare_us;
u32_t window_size_event_us;
u32_t force;
u32_t ticks_to_offset;
} slave;
union {
struct {
u8_t terminate_ack:1;
} master;
struct {
u8_t latency_enabled:1;
u8_t latency_cancel:1;
u8_t sca:3;
u32_t window_widening_periodic_us;
u32_t window_widening_max_us;
u32_t window_widening_prepare_us;
u32_t window_widening_event_us;
u32_t window_size_prepare_us;
u32_t window_size_event_us;
u32_t force;
u32_t ticks_to_offset;
} slave;
};
u8_t llcp_req;
u8_t llcp_ack;
@ -174,10 +180,10 @@ struct connection {
} llcp_version;
struct {
u8_t req;
u8_t ack;
u8_t reason_own;
u8_t reason_peer;
u8_t req;
u8_t ack;
u8_t reason_own;
u8_t reason_peer;
struct {
struct radio_pdu_node_rx_hdr hdr;
u8_t reason;