From 6ccfa64b5cb62e8c3f7753b1d75080cbc0c0a6fa Mon Sep 17 00:00:00 2001 From: Carles Cufi Date: Mon, 7 Nov 2016 15:49:43 +0100 Subject: [PATCH] Bluetooth: Controller: Handle LL_UNKNOWN_RSP PDU for remote features When a peer controller does not recognize one of the LL control PDUs received, it will issue an LL_UNKNOWN_RSP PDU to let the peer know that it does not recognize the request. The controller now handles this incoming PDU and completes the procedure by issuing the appropriate HCI event in the case of an LL_FEATURE_REQ and _RSP pair. Jira: ZEP-1220 Change-Id: I7c04a346441f04deee41198daa6309c11ae1b571 Signed-off-by: Carles Cufi --- subsys/bluetooth/controller/hci/hci.c | 38 ++++++++++++++++++++++----- subsys/bluetooth/controller/ll/ctrl.c | 5 ++-- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index ee0548c11ff..34a3a8886ee 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -1081,18 +1081,38 @@ static void encrypt_change(uint8_t err, uint16_t handle, ep->encrypt = !err ? 1 : 0; } -static void le_remote_feat_complete(struct pdu_data *pdu_data, uint16_t handle, - struct net_buf *buf) +static void le_remote_feat_complete(uint8_t status, struct pdu_data *pdu_data, + uint16_t handle, struct net_buf *buf) { struct bt_hci_ev_le_remote_feat_complete *sep; sep = meta_evt(buf, BT_HCI_EV_LE_REMOTE_FEAT_COMPLETE, sizeof(*sep)); - sep->status = 0x00; + sep->status = status; sep->handle = sys_cpu_to_le16(handle); - memcpy(&sep->features[0], - &pdu_data->payload.llctrl.ctrldata.feature_rsp.features[0], - sizeof(sep->features)); + if (!status) { + memcpy(&sep->features[0], + &pdu_data->payload.llctrl.ctrldata.feature_rsp.features[0], + sizeof(sep->features)); + } else { + memset(&sep->features[0], 0x00, sizeof(sep->features)); + } +} + +static void le_unknown_rsp(struct pdu_data *pdu_data, uint16_t handle, + struct net_buf *buf) +{ + + switch (pdu_data->payload.llctrl.ctrldata.unknown_rsp.type) { + case PDU_DATA_LLCTRL_TYPE_SLAVE_FEATURE_REQ: + le_remote_feat_complete(BT_HCI_ERR_UNSUPP_REMOTE_FEATURE, + NULL, handle, buf); + break; + + default: + BT_ASSERT(0); + break; + } } static void remote_version_info(struct pdu_data *pdu_data, uint16_t handle, @@ -1162,7 +1182,7 @@ static void encode_data_ctrl(struct radio_pdu_node_rx *node_rx, break; case PDU_DATA_LLCTRL_TYPE_FEATURE_RSP: - le_remote_feat_complete(pdu_data, handle, buf); + le_remote_feat_complete(0x00, pdu_data, handle, buf); break; case PDU_DATA_LLCTRL_TYPE_VERSION_IND: @@ -1184,6 +1204,10 @@ static void encode_data_ctrl(struct radio_pdu_node_rx *node_rx, le_data_len_change(pdu_data, handle, buf); break; + case PDU_DATA_LLCTRL_TYPE_UNKNOWN_RSP: + le_unknown_rsp(pdu_data, handle, buf); + break; + default: BT_ASSERT(0); return; diff --git a/subsys/bluetooth/controller/ll/ctrl.c b/subsys/bluetooth/controller/ll/ctrl.c index 333605ac3e6..6ee6100760c 100644 --- a/subsys/bluetooth/controller/ll/ctrl.c +++ b/subsys/bluetooth/controller/ll/ctrl.c @@ -1677,9 +1677,8 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *radio_pdu_node_rx, */ *rx_enqueue = 1; } else { - /** @todo check opcode in unknown rsp, and take - * necessary actions - */ + /* enqueue the error and let HCI handle it */ + *rx_enqueue = 1; /* Procedure complete */ _radio.conn_curr->procedure_expire = 0; }