Bluetooth: controller: LE Enhanced Connection Complete
Implement the LE Enhanced Connection Complete HCI event, but include it only when controller-based privacy is enabled, since it is only relevant with it. Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
parent
dce2f95e95
commit
b2a76be25b
5 changed files with 129 additions and 29 deletions
|
@ -1820,31 +1820,73 @@ static void le_scan_req_received(struct pdu_data *pdu_data, u8_t *b,
|
|||
static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_evt_le_conn_complete *sep;
|
||||
struct bt_hci_evt_le_conn_complete *lecc;
|
||||
struct radio_le_conn_cmplt *radio_cc;
|
||||
|
||||
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
|
||||
!(le_event_mask & BT_EVT_MASK_LE_CONN_COMPLETE)) {
|
||||
(!(le_event_mask & BT_EVT_MASK_LE_CONN_COMPLETE) &&
|
||||
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||
!(le_event_mask & BT_EVT_MASK_LE_ENH_CONN_COMPLETE))) {
|
||||
#else
|
||||
1)) {
|
||||
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
|
||||
return;
|
||||
}
|
||||
|
||||
radio_cc = (struct radio_le_conn_cmplt *) (pdu_data->payload.lldata);
|
||||
|
||||
sep = meta_evt(buf, BT_HCI_EVT_LE_CONN_COMPLETE, sizeof(*sep));
|
||||
|
||||
sep->status = radio_cc->status;
|
||||
sep->handle = sys_cpu_to_le16(handle);
|
||||
sep->role = radio_cc->role;
|
||||
sep->peer_addr.type = radio_cc->peer_addr_type;
|
||||
memcpy(&sep->peer_addr.a.val[0], &radio_cc->peer_addr[0], BDADDR_SIZE);
|
||||
sep->interval = sys_cpu_to_le16(radio_cc->interval);
|
||||
sep->latency = sys_cpu_to_le16(radio_cc->latency);
|
||||
sep->supv_timeout = sys_cpu_to_le16(radio_cc->timeout);
|
||||
sep->clock_accuracy = radio_cc->mca;
|
||||
|
||||
if (!radio_cc->status) {
|
||||
conn_count++;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||
if (le_event_mask & BT_EVT_MASK_LE_ENH_CONN_COMPLETE) {
|
||||
struct bt_hci_evt_le_enh_conn_complete *leecc;
|
||||
|
||||
leecc = meta_evt(buf, BT_HCI_EVT_LE_ENH_CONN_COMPLETE,
|
||||
sizeof(*leecc));
|
||||
|
||||
leecc->status = radio_cc->status;
|
||||
leecc->handle = sys_cpu_to_le16(handle);
|
||||
leecc->role = radio_cc->role;
|
||||
|
||||
leecc->peer_addr.type = radio_cc->peer_addr_type;
|
||||
memcpy(&leecc->peer_addr.a.val[0], &radio_cc->peer_addr[0],
|
||||
BDADDR_SIZE);
|
||||
|
||||
/* Note: this could be an RPA set as the random address by
|
||||
* the Host instead of generated by the controller. That said,
|
||||
* this should make no difference. */
|
||||
if ((radio_cc->own_addr_type) &&
|
||||
((radio_cc->own_addr[5] & 0xc0) == 0x40)) {
|
||||
memcpy(&leecc->local_rpa.val[0], &radio_cc->own_addr[0],
|
||||
BDADDR_SIZE);
|
||||
} else {
|
||||
memset(&leecc->local_rpa.val[0], 0x0, BDADDR_SIZE);
|
||||
}
|
||||
|
||||
memcpy(&leecc->peer_rpa.val[0], &radio_cc->peer_rpa[0],
|
||||
BDADDR_SIZE);
|
||||
|
||||
leecc->interval = sys_cpu_to_le16(radio_cc->interval);
|
||||
leecc->latency = sys_cpu_to_le16(radio_cc->latency);
|
||||
leecc->supv_timeout = sys_cpu_to_le16(radio_cc->timeout);
|
||||
leecc->clock_accuracy = radio_cc->mca;
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
|
||||
|
||||
lecc = meta_evt(buf, BT_HCI_EVT_LE_CONN_COMPLETE, sizeof(*lecc));
|
||||
|
||||
lecc->status = radio_cc->status;
|
||||
lecc->handle = sys_cpu_to_le16(handle);
|
||||
lecc->role = radio_cc->role;
|
||||
lecc->peer_addr.type = radio_cc->peer_addr_type;
|
||||
memcpy(&lecc->peer_addr.a.val[0], &radio_cc->peer_addr[0], BDADDR_SIZE);
|
||||
lecc->interval = sys_cpu_to_le16(radio_cc->interval);
|
||||
lecc->latency = sys_cpu_to_le16(radio_cc->latency);
|
||||
lecc->supv_timeout = sys_cpu_to_le16(radio_cc->timeout);
|
||||
lecc->clock_accuracy = radio_cc->mca;
|
||||
}
|
||||
|
||||
static void disconn_complete(struct pdu_data *pdu_data, u16_t handle,
|
||||
|
|
|
@ -810,7 +810,8 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
|
|||
FILTER_IDX_NONE;
|
||||
#else
|
||||
u8_t rl_idx = FILTER_IDX_NONE;
|
||||
#endif
|
||||
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
|
||||
|
||||
pdu_adv = (struct pdu_adv *)radio_pkt_scratch_get();
|
||||
_pdu_adv = (struct pdu_adv *)&_radio.advertiser.adv_data.data
|
||||
[_radio.advertiser.adv_data.first][0];
|
||||
|
@ -924,14 +925,35 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
|
|||
(struct radio_le_conn_cmplt *)&pdu_data->payload;
|
||||
radio_le_conn_cmplt->status = 0x00;
|
||||
radio_le_conn_cmplt->role = 0x01;
|
||||
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||
radio_le_conn_cmplt->own_addr_type = pdu_adv->rx_addr;
|
||||
memcpy(&radio_le_conn_cmplt->own_addr[0],
|
||||
&pdu_adv->payload.connect_ind.adv_addr[0], BDADDR_SIZE);
|
||||
if (rl_idx != FILTER_IDX_NONE) {
|
||||
/* TODO: store rl_idx instead if safe */
|
||||
/* Store identity address */
|
||||
ctrl_id_addr_get(rl_idx,
|
||||
&radio_le_conn_cmplt->peer_addr_type,
|
||||
&radio_le_conn_cmplt->peer_addr[0]);
|
||||
/* Mark it as identity address from RPA (0x02, 0x03) */
|
||||
radio_le_conn_cmplt->peer_addr_type += 2;
|
||||
|
||||
/* Store peer RPA */
|
||||
memcpy(&radio_le_conn_cmplt->peer_rpa[0],
|
||||
&pdu_adv->payload.connect_ind.init_addr[0],
|
||||
BDADDR_SIZE);
|
||||
} else {
|
||||
memset(&radio_le_conn_cmplt->peer_rpa[0], 0x0,
|
||||
BDADDR_SIZE);
|
||||
#else
|
||||
if (1) {
|
||||
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
|
||||
radio_le_conn_cmplt->peer_addr_type = pdu_adv->tx_addr;
|
||||
memcpy(&radio_le_conn_cmplt->peer_addr[0],
|
||||
&pdu_adv->payload.connect_ind.init_addr[0],
|
||||
BDADDR_SIZE);
|
||||
radio_le_conn_cmplt->own_addr_type = pdu_adv->rx_addr;
|
||||
memcpy(&radio_le_conn_cmplt->own_addr[0],
|
||||
&pdu_adv->payload.connect_ind.adv_addr[0], BDADDR_SIZE);
|
||||
radio_le_conn_cmplt->peer_irk_index = irkmatch_id;
|
||||
}
|
||||
|
||||
radio_le_conn_cmplt->interval =
|
||||
pdu_adv->payload.connect_ind.lldata.interval;
|
||||
radio_le_conn_cmplt->latency =
|
||||
|
@ -1171,7 +1193,8 @@ static inline bool isr_scan_init_check(struct pdu_adv *pdu, u8_t rl_idx)
|
|||
}
|
||||
|
||||
static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
||||
u8_t irkmatch_id, u8_t rl_idx, u8_t rssi_ready)
|
||||
u8_t irkmatch_ok, u8_t irkmatch_id, u8_t rl_idx,
|
||||
u8_t rssi_ready)
|
||||
{
|
||||
struct pdu_adv *pdu_adv_rx;
|
||||
|
||||
|
@ -1317,15 +1340,38 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
|||
(struct radio_le_conn_cmplt *)&pdu_data->payload;
|
||||
radio_le_conn_cmplt->status = 0x00;
|
||||
radio_le_conn_cmplt->role = 0x00;
|
||||
radio_le_conn_cmplt->peer_addr_type = pdu_adv_tx->rx_addr;
|
||||
memcpy(&radio_le_conn_cmplt->peer_addr[0],
|
||||
&pdu_adv_tx->payload.connect_ind.adv_addr[0],
|
||||
BDADDR_SIZE);
|
||||
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||
radio_le_conn_cmplt->own_addr_type = pdu_adv_tx->tx_addr;
|
||||
memcpy(&radio_le_conn_cmplt->own_addr[0],
|
||||
&pdu_adv_tx->payload.connect_ind.init_addr[0],
|
||||
BDADDR_SIZE);
|
||||
radio_le_conn_cmplt->peer_irk_index = irkmatch_id;
|
||||
|
||||
if (irkmatch_ok && rl_idx != FILTER_IDX_NONE) {
|
||||
/* TODO: store rl_idx instead if safe */
|
||||
/* Store identity address */
|
||||
ctrl_id_addr_get(rl_idx,
|
||||
&radio_le_conn_cmplt->peer_addr_type,
|
||||
&radio_le_conn_cmplt->peer_addr[0]);
|
||||
/* Mark it as identity address from RPA (0x02, 0x03) */
|
||||
radio_le_conn_cmplt->peer_addr_type += 2;
|
||||
|
||||
/* Store peer RPA */
|
||||
memcpy(&radio_le_conn_cmplt->peer_rpa[0],
|
||||
&pdu_adv_tx->payload.connect_ind.adv_addr[0],
|
||||
BDADDR_SIZE);
|
||||
} else {
|
||||
memset(&radio_le_conn_cmplt->peer_rpa[0], 0x0,
|
||||
BDADDR_SIZE);
|
||||
#else
|
||||
if (1) {
|
||||
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
|
||||
radio_le_conn_cmplt->peer_addr_type =
|
||||
pdu_adv_tx->rx_addr;
|
||||
memcpy(&radio_le_conn_cmplt->peer_addr[0],
|
||||
&pdu_adv_tx->payload.connect_ind.adv_addr[0],
|
||||
BDADDR_SIZE);
|
||||
}
|
||||
|
||||
radio_le_conn_cmplt->interval = _radio.scanner.conn_interval;
|
||||
radio_le_conn_cmplt->latency = _radio.scanner. conn_latency;
|
||||
radio_le_conn_cmplt->timeout = _radio.scanner.conn_timeout;
|
||||
|
@ -3104,8 +3150,8 @@ static inline void isr_radio_state_rx(u8_t trx_done, u8_t crc_ok,
|
|||
#endif
|
||||
if (crc_ok &&
|
||||
isr_rx_scan_check(irkmatch_ok, devmatch_ok, rl_idx)) {
|
||||
err = isr_rx_scan(devmatch_ok, devmatch_id, irkmatch_id,
|
||||
rl_idx, rssi_ready);
|
||||
err = isr_rx_scan(devmatch_ok, devmatch_id, irkmatch_ok,
|
||||
irkmatch_id, rl_idx, rssi_ready);
|
||||
} else {
|
||||
err = 1;
|
||||
}
|
||||
|
|
|
@ -271,9 +271,11 @@ struct radio_le_conn_cmplt {
|
|||
u8_t role;
|
||||
u8_t peer_addr_type;
|
||||
u8_t peer_addr[BDADDR_SIZE];
|
||||
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||
u8_t peer_rpa[BDADDR_SIZE];
|
||||
u8_t own_addr_type;
|
||||
u8_t own_addr[BDADDR_SIZE];
|
||||
u8_t peer_irk_index;
|
||||
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
|
||||
u16_t interval;
|
||||
u16_t latency;
|
||||
u16_t timeout;
|
||||
|
|
|
@ -447,6 +447,15 @@ bool ctrl_rl_idx_allowed(u8_t irkmatch_ok, u8_t rl_idx)
|
|||
return !rl[rl_idx].pirk || rl[rl_idx].dev;
|
||||
}
|
||||
|
||||
void ctrl_id_addr_get(u8_t rl_idx, u8_t *id_addr_type, u8_t *id_addr)
|
||||
{
|
||||
LL_ASSERT(rl_idx < CONFIG_BLUETOOTH_CONTROLLER_RL_SIZE);
|
||||
LL_ASSERT(rl[rl_idx].taken);
|
||||
|
||||
*id_addr_type = rl[rl_idx].id_addr_type;
|
||||
memcpy(id_addr, rl[rl_idx].id_addr.val, BDADDR_SIZE);
|
||||
}
|
||||
|
||||
bool ctrl_rl_addr_allowed(u8_t id_addr_type, u8_t *id_addr, u8_t *rl_idx)
|
||||
{
|
||||
int i, j;
|
||||
|
|
|
@ -23,6 +23,7 @@ bt_addr_t *ctrl_lrpa_get(u8_t rl_idx);
|
|||
u8_t *ctrl_irks_get(u8_t *count);
|
||||
u8_t ctrl_rl_idx(bool whitelist, u8_t devmatch_id);
|
||||
u8_t ctrl_rl_irk_idx(u8_t irkmatch_id);
|
||||
void ctrl_id_addr_get(u8_t rl_idx, u8_t *id_addr_type, u8_t *id_addr);
|
||||
bool ctrl_irk_whitelisted(u8_t rl_idx);
|
||||
|
||||
bool ctrl_rl_enabled(void);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue