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 <carles.cufi@nordicsemi.no>
This commit is contained in:
Carles Cufi 2016-11-07 15:49:43 +01:00 committed by Johan Hedberg
commit 6ccfa64b5c
2 changed files with 33 additions and 10 deletions

View file

@ -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;

View file

@ -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;
}