Bluetooth: controller: Add handling of CTE request failed
CTE request control procedure may failed due to rejection by peer device or due to receive of LL_CTE_RSP PDU without CTE. These events has to be reported to host by HCI_LE_CTE_Request_Failed. The commit adds missing functionalit. Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
This commit is contained in:
parent
cb29f29cc9
commit
85c4176446
6 changed files with 75 additions and 6 deletions
|
@ -2495,8 +2495,15 @@ struct bt_hci_evt_le_connection_iq_report {
|
||||||
struct bt_hci_le_iq_sample sample[0];
|
struct bt_hci_le_iq_sample sample[0];
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
#define BT_HCI_CTE_REQ_STATUS_RSP_WITHOUT_CTE 0x0
|
||||||
|
|
||||||
#define BT_HCI_EVT_LE_CTE_REQUEST_FAILED 0x17
|
#define BT_HCI_EVT_LE_CTE_REQUEST_FAILED 0x17
|
||||||
struct bt_hci_evt_le_cte_req_failed {
|
struct bt_hci_evt_le_cte_req_failed {
|
||||||
|
/* According to BT 5.3 Core Spec the status field may have following
|
||||||
|
* values:
|
||||||
|
* - BT_HCI_CTE_REQ_STATUS_RSP_WIHOUT_CTE when received LL_CTE_RSP_PDU without CTE.
|
||||||
|
* - Other Controller error code for peer rejected request.
|
||||||
|
*/
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
uint16_t conn_handle;
|
uint16_t conn_handle;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
|
@ -2991,6 +2991,21 @@ static void le_df_set_conn_cte_req_enable(struct net_buf *buf, struct net_buf **
|
||||||
rp->status = status;
|
rp->status = status;
|
||||||
rp->handle = handle_le16;
|
rp->handle = handle_le16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void le_df_cte_req_failed(uint8_t error_code, uint16_t handle, struct net_buf *buf)
|
||||||
|
{
|
||||||
|
struct bt_hci_evt_le_cte_req_failed *sep;
|
||||||
|
|
||||||
|
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
|
||||||
|
!(le_event_mask & BT_EVT_MASK_LE_CTE_REQUEST_FAILED)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sep = meta_evt(buf, BT_HCI_EVT_LE_CTE_REQUEST_FAILED, sizeof(*sep));
|
||||||
|
|
||||||
|
sep->status = error_code;
|
||||||
|
sep->conn_handle = sys_cpu_to_le16(handle);
|
||||||
|
}
|
||||||
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
|
||||||
|
@ -7350,6 +7365,19 @@ static void le_unknown_rsp(struct pdu_data *pdu_data, uint16_t handle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void le_reject_ext_ind(struct pdu_data *pdu, uint16_t handle, struct net_buf *buf)
|
||||||
|
{
|
||||||
|
switch (pdu->llctrl.reject_ext_ind.reject_opcode) {
|
||||||
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
|
||||||
|
case PDU_DATA_LLCTRL_TYPE_CTE_REQ:
|
||||||
|
le_df_cte_req_failed(pdu->llctrl.reject_ext_ind.error_code, handle, buf);
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
||||||
|
default:
|
||||||
|
BT_WARN("reject opcode: 0x%02x", pdu->llctrl.reject_ext_ind.reject_opcode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
#if defined(CONFIG_BT_CTLR_CONN_PARAM_REQ)
|
||||||
static void le_conn_param_req(struct pdu_data *pdu_data, uint16_t handle,
|
static void le_conn_param_req(struct pdu_data *pdu_data, uint16_t handle,
|
||||||
struct net_buf *buf)
|
struct net_buf *buf)
|
||||||
|
@ -7466,10 +7494,20 @@ static void encode_data_ctrl(struct node_rx_pdu *node_rx,
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
|
||||||
|
case PDU_DATA_LLCTRL_TYPE_CTE_REQ:
|
||||||
|
le_df_cte_req_failed(BT_HCI_CTE_REQ_STATUS_RSP_WITHOUT_CTE, handle, buf);
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
||||||
|
|
||||||
case PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP:
|
case PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP:
|
||||||
le_unknown_rsp(pdu_data, handle, buf);
|
le_unknown_rsp(pdu_data, handle, buf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND:
|
||||||
|
le_reject_ext_ind(pdu_data, handle, buf);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LL_ASSERT(0);
|
LL_ASSERT(0);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -424,6 +424,7 @@ struct llcp_struct {
|
||||||
uint16_t req_interval;
|
uint16_t req_interval;
|
||||||
uint16_t req_expire;
|
uint16_t req_expire;
|
||||||
} cte_req;
|
} cte_req;
|
||||||
|
|
||||||
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
||||||
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
|
||||||
struct llcp_df_rsp_cfg {
|
struct llcp_df_rsp_cfg {
|
||||||
|
|
|
@ -210,9 +210,12 @@ static void lp_comm_ntf_length_change(struct ll_conn *conn, struct proc_ctx *ctx
|
||||||
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
|
||||||
static void lp_comm_ntf_cte_req(struct ll_conn *conn, struct proc_ctx *ctx, struct pdu_data *pdu)
|
static void lp_comm_ntf_cte_req(struct ll_conn *conn, struct proc_ctx *ctx, struct pdu_data *pdu)
|
||||||
{
|
{
|
||||||
/* TODO (ppryga): Add handling of rejections in HCI: HCI_LE_CTE_Request_Failed. */
|
|
||||||
switch (ctx->response_opcode) {
|
switch (ctx->response_opcode) {
|
||||||
case PDU_DATA_LLCTRL_TYPE_CTE_RSP:
|
case PDU_DATA_LLCTRL_TYPE_CTE_RSP:
|
||||||
|
/* Notify host that received LL_CTE_RSP does not have CTE */
|
||||||
|
if (!ctx->data.cte_remote_rsp.has_cte) {
|
||||||
|
llcp_ntf_encode_cte_req(pdu);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND:
|
case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND:
|
||||||
llcp_ntf_encode_reject_ext_ind(ctx, pdu);
|
llcp_ntf_encode_reject_ext_ind(ctx, pdu);
|
||||||
|
@ -346,10 +349,12 @@ static void lp_comm_complete(struct ll_conn *conn, struct proc_ctx *ctx, uint8_t
|
||||||
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
|
||||||
case PROC_CTE_REQ:
|
case PROC_CTE_REQ:
|
||||||
if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_CTE_RSP) {
|
if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_CTE_RSP) {
|
||||||
if (conn->llcp.cte_req.req_interval != 0U) {
|
if (ctx->data.cte_remote_rsp.has_cte &&
|
||||||
|
conn->llcp.cte_req.req_interval != 0U) {
|
||||||
conn->llcp.cte_req.req_expire = conn->llcp.cte_req.req_interval;
|
conn->llcp.cte_req.req_expire = conn->llcp.cte_req.req_interval;
|
||||||
} else {
|
} else {
|
||||||
conn->llcp.cte_req.is_enabled = 0U;
|
conn->llcp.cte_req.is_enabled = 0U;
|
||||||
|
lp_comm_ntf(conn, ctx);
|
||||||
}
|
}
|
||||||
ctx->state = LP_COMMON_STATE_IDLE;
|
ctx->state = LP_COMMON_STATE_IDLE;
|
||||||
} else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND &&
|
} else if (ctx->response_opcode == PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND &&
|
||||||
|
@ -556,9 +561,11 @@ static void lp_comm_rx_decode(struct ll_conn *conn, struct proc_ctx *ctx, struct
|
||||||
llcp_pdu_decode_length_rsp(conn, pdu);
|
llcp_pdu_decode_length_rsp(conn, pdu);
|
||||||
break;
|
break;
|
||||||
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
|
||||||
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_REQ)
|
||||||
case PDU_DATA_LLCTRL_TYPE_CTE_RSP:
|
case PDU_DATA_LLCTRL_TYPE_CTE_RSP:
|
||||||
/* CTE Response PDU had no data */
|
llcp_pdu_decode_cte_rsp(ctx, pdu);
|
||||||
break;
|
break;
|
||||||
|
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
||||||
case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND:
|
case PDU_DATA_LLCTRL_TYPE_REJECT_EXT_IND:
|
||||||
llcp_pdu_decode_reject_ext_ind(ctx, pdu);
|
llcp_pdu_decode_reject_ext_ind(ctx, pdu);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -220,6 +220,11 @@ struct proc_ctx {
|
||||||
uint8_t type:2;
|
uint8_t type:2;
|
||||||
uint8_t min_len:5;
|
uint8_t min_len:5;
|
||||||
} cte_req;
|
} cte_req;
|
||||||
|
|
||||||
|
struct llcp_df_cte_remote_rsp {
|
||||||
|
/* Storage for information that received LL_CTE_RSP PDU includes CTE */
|
||||||
|
uint8_t has_cte;
|
||||||
|
} cte_remote_rsp;
|
||||||
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
|
||||||
|
@ -591,7 +596,8 @@ void llcp_ntf_encode_length_change(struct ll_conn *conn,
|
||||||
* Constant Tone Request Procedure Helper
|
* Constant Tone Request Procedure Helper
|
||||||
*/
|
*/
|
||||||
void llcp_pdu_encode_cte_req(struct proc_ctx *ctx, struct pdu_data *pdu);
|
void llcp_pdu_encode_cte_req(struct proc_ctx *ctx, struct pdu_data *pdu);
|
||||||
void llcp_ntf_encode_cte_req(struct ll_conn *conn, struct pdu_data *pdu);
|
void llcp_pdu_decode_cte_rsp(struct proc_ctx *ctx, const struct pdu_data *pdu);
|
||||||
|
void llcp_ntf_encode_cte_req(struct pdu_data *pdu);
|
||||||
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
||||||
|
|
||||||
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
|
#if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RSP)
|
||||||
|
|
|
@ -727,14 +727,24 @@ void llcp_pdu_encode_cte_req(struct proc_ctx *ctx, struct pdu_data *pdu)
|
||||||
p->cte_type_req = ctx->data.cte_req.type;
|
p->cte_type_req = ctx->data.cte_req.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void llcp_ntf_encode_cte_req(struct ll_conn *conn, struct pdu_data *pdu)
|
void llcp_pdu_decode_cte_rsp(struct proc_ctx *ctx, const struct pdu_data *pdu)
|
||||||
|
{
|
||||||
|
if (pdu->cp == 0U || pdu->cte_info.time == 0U) {
|
||||||
|
ctx->data.cte_remote_rsp.has_cte = false;
|
||||||
|
} else {
|
||||||
|
ctx->data.cte_remote_rsp.has_cte = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void llcp_ntf_encode_cte_req(struct pdu_data *pdu)
|
||||||
{
|
{
|
||||||
pdu->ll_id = PDU_DATA_LLID_CTRL;
|
pdu->ll_id = PDU_DATA_LLID_CTRL;
|
||||||
pdu->len =
|
pdu->len =
|
||||||
offsetof(struct pdu_data_llctrl, cte_rsp) + sizeof(struct pdu_data_llctrl_cte_rsp);
|
offsetof(struct pdu_data_llctrl, cte_rsp) + sizeof(struct pdu_data_llctrl_cte_rsp);
|
||||||
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CTE_RSP;
|
pdu->llctrl.opcode = PDU_DATA_LLCTRL_TYPE_CTE_RSP;
|
||||||
|
|
||||||
/* TODO add handling of IQ samples forwarding */
|
/* Received LL_CTE_RSP PDU didn't have CTE */
|
||||||
|
pdu->cp = 0U;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
#endif /* CONFIG_BT_CTLR_DF_CONN_CTE_REQ */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue