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,
|
static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle,
|
||||||
struct net_buf *buf)
|
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;
|
struct radio_le_conn_cmplt *radio_cc;
|
||||||
|
|
||||||
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
radio_cc = (struct radio_le_conn_cmplt *) (pdu_data->payload.lldata);
|
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) {
|
if (!radio_cc->status) {
|
||||||
conn_count++;
|
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,
|
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;
|
FILTER_IDX_NONE;
|
||||||
#else
|
#else
|
||||||
u8_t rl_idx = FILTER_IDX_NONE;
|
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_pkt_scratch_get();
|
||||||
_pdu_adv = (struct pdu_adv *)&_radio.advertiser.adv_data.data
|
_pdu_adv = (struct pdu_adv *)&_radio.advertiser.adv_data.data
|
||||||
[_radio.advertiser.adv_data.first][0];
|
[_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;
|
(struct radio_le_conn_cmplt *)&pdu_data->payload;
|
||||||
radio_le_conn_cmplt->status = 0x00;
|
radio_le_conn_cmplt->status = 0x00;
|
||||||
radio_le_conn_cmplt->role = 0x01;
|
radio_le_conn_cmplt->role = 0x01;
|
||||||
radio_le_conn_cmplt->peer_addr_type = pdu_adv->tx_addr;
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||||
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;
|
radio_le_conn_cmplt->own_addr_type = pdu_adv->rx_addr;
|
||||||
memcpy(&radio_le_conn_cmplt->own_addr[0],
|
memcpy(&radio_le_conn_cmplt->own_addr[0],
|
||||||
&pdu_adv->payload.connect_ind.adv_addr[0], BDADDR_SIZE);
|
&pdu_adv->payload.connect_ind.adv_addr[0], BDADDR_SIZE);
|
||||||
radio_le_conn_cmplt->peer_irk_index = irkmatch_id;
|
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->interval =
|
radio_le_conn_cmplt->interval =
|
||||||
pdu_adv->payload.connect_ind.lldata.interval;
|
pdu_adv->payload.connect_ind.lldata.interval;
|
||||||
radio_le_conn_cmplt->latency =
|
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,
|
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;
|
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;
|
(struct radio_le_conn_cmplt *)&pdu_data->payload;
|
||||||
radio_le_conn_cmplt->status = 0x00;
|
radio_le_conn_cmplt->status = 0x00;
|
||||||
radio_le_conn_cmplt->role = 0x00;
|
radio_le_conn_cmplt->role = 0x00;
|
||||||
radio_le_conn_cmplt->peer_addr_type = pdu_adv_tx->rx_addr;
|
#if defined(CONFIG_BLUETOOTH_CONTROLLER_PRIVACY)
|
||||||
memcpy(&radio_le_conn_cmplt->peer_addr[0],
|
|
||||||
&pdu_adv_tx->payload.connect_ind.adv_addr[0],
|
|
||||||
BDADDR_SIZE);
|
|
||||||
radio_le_conn_cmplt->own_addr_type = pdu_adv_tx->tx_addr;
|
radio_le_conn_cmplt->own_addr_type = pdu_adv_tx->tx_addr;
|
||||||
memcpy(&radio_le_conn_cmplt->own_addr[0],
|
memcpy(&radio_le_conn_cmplt->own_addr[0],
|
||||||
&pdu_adv_tx->payload.connect_ind.init_addr[0],
|
&pdu_adv_tx->payload.connect_ind.init_addr[0],
|
||||||
BDADDR_SIZE);
|
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->interval = _radio.scanner.conn_interval;
|
||||||
radio_le_conn_cmplt->latency = _radio.scanner. conn_latency;
|
radio_le_conn_cmplt->latency = _radio.scanner. conn_latency;
|
||||||
radio_le_conn_cmplt->timeout = _radio.scanner.conn_timeout;
|
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
|
#endif
|
||||||
if (crc_ok &&
|
if (crc_ok &&
|
||||||
isr_rx_scan_check(irkmatch_ok, devmatch_ok, rl_idx)) {
|
isr_rx_scan_check(irkmatch_ok, devmatch_ok, rl_idx)) {
|
||||||
err = isr_rx_scan(devmatch_ok, devmatch_id, irkmatch_id,
|
err = isr_rx_scan(devmatch_ok, devmatch_id, irkmatch_ok,
|
||||||
rl_idx, rssi_ready);
|
irkmatch_id, rl_idx, rssi_ready);
|
||||||
} else {
|
} else {
|
||||||
err = 1;
|
err = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,9 +271,11 @@ struct radio_le_conn_cmplt {
|
||||||
u8_t role;
|
u8_t role;
|
||||||
u8_t peer_addr_type;
|
u8_t peer_addr_type;
|
||||||
u8_t peer_addr[BDADDR_SIZE];
|
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_type;
|
||||||
u8_t own_addr[BDADDR_SIZE];
|
u8_t own_addr[BDADDR_SIZE];
|
||||||
u8_t peer_irk_index;
|
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
|
||||||
u16_t interval;
|
u16_t interval;
|
||||||
u16_t latency;
|
u16_t latency;
|
||||||
u16_t timeout;
|
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;
|
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)
|
bool ctrl_rl_addr_allowed(u8_t id_addr_type, u8_t *id_addr, u8_t *rl_idx)
|
||||||
{
|
{
|
||||||
int i, j;
|
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_irks_get(u8_t *count);
|
||||||
u8_t ctrl_rl_idx(bool whitelist, u8_t devmatch_id);
|
u8_t ctrl_rl_idx(bool whitelist, u8_t devmatch_id);
|
||||||
u8_t ctrl_rl_irk_idx(u8_t irkmatch_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_irk_whitelisted(u8_t rl_idx);
|
||||||
|
|
||||||
bool ctrl_rl_enabled(void);
|
bool ctrl_rl_enabled(void);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue