Bluetooth: controller: Fix for CPR with/without Feature Exchange
Fix implementation to support Connection Parameter Request Procedure initiation with and without use of Feature Exchange Procedure being performed in a connection. Fixes LL.TS.5.0.2 conformance tests: LL/CON/MAS/BV-81-C [Initiating Connection Parameter Request - Unsupported Without Feature Exchange] LL/CON/MAS/BV-82-C [Initiating Connection Parameter Request - Unsupported With Feature Exchange] LL/CON/SLA/BV-85-C [Initiating Connection Parameter Request - Unsupported Without Feature Exchange] LL/CON/SLA/BV-86-C [Initiating Connection Parameter Request - Unsupported With Feature Exchange] Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
8fc4c99496
commit
7af9c7108f
3 changed files with 88 additions and 18 deletions
|
@ -1089,13 +1089,10 @@ static void le_conn_update(struct net_buf *buf, struct net_buf **evt)
|
|||
conn_latency = sys_le16_to_cpu(cmd->conn_latency);
|
||||
supervision_timeout = sys_le16_to_cpu(cmd->supervision_timeout);
|
||||
|
||||
/** @todo if peer supports LE Conn Param Req,
|
||||
* use Req cmd (1) instead of Initiate cmd (0).
|
||||
*/
|
||||
status = ll_conn_update(handle, 0, 0, conn_interval_max,
|
||||
conn_latency, supervision_timeout);
|
||||
|
||||
*evt = cmd_status((!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED);
|
||||
*evt = cmd_status(status);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
|
@ -1118,7 +1115,7 @@ static void le_conn_param_req_reply(struct net_buf *buf, struct net_buf **evt)
|
|||
timeout);
|
||||
|
||||
rp = cmd_complete(evt, sizeof(*rp));
|
||||
rp->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
|
||||
rp->status = status;
|
||||
rp->handle = sys_cpu_to_le16(handle);
|
||||
}
|
||||
|
||||
|
@ -1134,7 +1131,7 @@ static void le_conn_param_req_neg_reply(struct net_buf *buf,
|
|||
status = ll_conn_update(handle, 2, cmd->reason, 0, 0, 0);
|
||||
|
||||
rp = cmd_complete(evt, sizeof(*rp));
|
||||
rp->status = (!status) ? 0x00 : BT_HCI_ERR_CMD_DISALLOWED;
|
||||
rp->status = status;
|
||||
rp->handle = sys_cpu_to_le16(handle);
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
|
|
|
@ -2846,6 +2846,68 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *radio_pdu_node_rx,
|
|||
|
||||
case PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP:
|
||||
if (0) {
|
||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
} else if (_radio.conn_curr->llcp_conn_param.ack !=
|
||||
_radio.conn_curr->llcp_conn_param.req) {
|
||||
struct connection *conn = _radio.conn_curr;
|
||||
struct radio_le_conn_update_cmplt *cp;
|
||||
|
||||
/* Mark CPR as unsupported */
|
||||
conn->llcp_conn_param.disabled = 1;
|
||||
|
||||
/* TODO: check for unsupported remote feature reason */
|
||||
if (!conn->role) {
|
||||
LL_ASSERT(conn->llcp_req == conn->llcp_ack);
|
||||
|
||||
conn->llcp_conn_param.state =
|
||||
LLCP_CPR_STATE_UPD;
|
||||
|
||||
conn->llcp.conn_upd.win_size = 1;
|
||||
conn->llcp.conn_upd.win_offset_us = 0;
|
||||
conn->llcp.conn_upd.interval =
|
||||
conn->llcp_conn_param.interval;
|
||||
conn->llcp.conn_upd.latency =
|
||||
conn->llcp_conn_param.latency;
|
||||
conn->llcp.conn_upd.timeout =
|
||||
conn->llcp_conn_param.timeout;
|
||||
/* conn->llcp.conn_upd.instant = 0; */
|
||||
conn->llcp.conn_upd.state = LLCP_CUI_STATE_USE;
|
||||
conn->llcp.conn_upd.is_internal =
|
||||
!conn->llcp_conn_param.cmd;
|
||||
conn->llcp_type = LLCP_CONN_UPD;
|
||||
conn->llcp_ack--;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
LL_ASSERT(_radio.conn_upd == conn);
|
||||
|
||||
/* reset mutex */
|
||||
_radio.conn_upd = NULL;
|
||||
|
||||
/* Procedure complete */
|
||||
conn->llcp_conn_param.ack = conn->llcp_conn_param.req;
|
||||
|
||||
/* skip event generation if not cmd initiated */
|
||||
if (!conn->llcp_conn_param.cmd) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* generate conn upd complete event with error code */
|
||||
radio_pdu_node_rx->hdr.type = NODE_RX_TYPE_CONN_UPDATE;
|
||||
|
||||
/* prepare connection update complete structure */
|
||||
pdu_data_rx = (void *)radio_pdu_node_rx->pdu_data;
|
||||
cp = (void *)&pdu_data_rx->payload;
|
||||
cp->status = BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||
cp->interval = conn->conn_interval;
|
||||
cp->latency = conn->latency;
|
||||
cp->timeout = conn->supervision_reload *
|
||||
conn->conn_interval * 125 / 1000;
|
||||
|
||||
*rx_enqueue = 1;
|
||||
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
} else if (_radio.conn_curr->llcp_length.req !=
|
||||
_radio.conn_curr->llcp_length.ack) {
|
||||
|
@ -8923,9 +8985,10 @@ static u32_t conn_update_req(struct connection *conn)
|
|||
return 0;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
} else if (conn->common.fex_valid &&
|
||||
(conn->llcp_features &
|
||||
BIT(BT_LE_FEAT_BIT_CONN_PARAM_REQ))) {
|
||||
} else if (!conn->llcp_conn_param.disabled &&
|
||||
(!conn->common.fex_valid ||
|
||||
(conn->llcp_features &
|
||||
BIT(BT_LE_FEAT_BIT_CONN_PARAM_REQ)))) {
|
||||
/** Perform slave intiated conn param req */
|
||||
conn->llcp_conn_param.status = 0;
|
||||
conn->llcp_conn_param.interval = conn->conn_interval;
|
||||
|
@ -9838,6 +9901,7 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
|
|||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
conn->llcp_conn_param.req = 0;
|
||||
conn->llcp_conn_param.ack = 0;
|
||||
conn->llcp_conn_param.disabled = 0;
|
||||
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
|
@ -10317,6 +10381,7 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
|
|||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
conn->llcp_conn_param.req = 0;
|
||||
conn->llcp_conn_param.ack = 0;
|
||||
conn->llcp_conn_param.disabled = 0;
|
||||
#endif /* CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
|
||||
|
@ -10376,22 +10441,29 @@ u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval,
|
|||
|
||||
conn = connection_get(handle);
|
||||
if (!conn) {
|
||||
return 1;
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
if (!cmd) {
|
||||
if (conn->common.fex_valid &&
|
||||
(conn->llcp_features &
|
||||
BIT(BT_LE_FEAT_BIT_CONN_PARAM_REQ))) {
|
||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||
if (!conn->llcp_conn_param.disabled &&
|
||||
(!conn->common.fex_valid ||
|
||||
(conn->llcp_features &
|
||||
BIT(BT_LE_FEAT_BIT_CONN_PARAM_REQ)))) {
|
||||
cmd++;
|
||||
} else if (conn->role) {
|
||||
return 1;
|
||||
return BT_HCI_ERR_UNSUPP_REMOTE_FEATURE;
|
||||
}
|
||||
#else /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
if (conn->role) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
#endif /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
}
|
||||
|
||||
if (!cmd) {
|
||||
if (conn->llcp_req != conn->llcp_ack) {
|
||||
return 1;
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
conn->llcp.conn_upd.win_size = 1;
|
||||
|
@ -10414,7 +10486,7 @@ u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval,
|
|||
conn->llcp_conn_param.ack) ||
|
||||
(conn->llcp_conn_param.state !=
|
||||
LLCP_CPR_STATE_APP_WAIT)) {
|
||||
return 1;
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
conn->llcp_conn_param.status = status;
|
||||
|
@ -10423,7 +10495,7 @@ u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval,
|
|||
} else {
|
||||
if (conn->llcp_conn_param.req !=
|
||||
conn->llcp_conn_param.ack) {
|
||||
return 1;
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
conn->llcp_conn_param.status = 0;
|
||||
|
@ -10437,7 +10509,7 @@ u32_t ll_conn_update(u16_t handle, u8_t cmd, u8_t status, u16_t interval,
|
|||
|
||||
#else /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
/* CPR feature not supported */
|
||||
return 1;
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
#endif /* !CONFIG_BT_CTLR_CONN_PARAM_REQ */
|
||||
}
|
||||
|
||||
|
|
|
@ -208,6 +208,7 @@ struct connection {
|
|||
LLCP_CPR_STATE_UPD
|
||||
} state:3 __packed;
|
||||
u8_t cmd:1;
|
||||
u8_t disabled:1;
|
||||
u8_t status;
|
||||
u16_t interval;
|
||||
u16_t latency;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue