Bluetooth: controller: Handle Privacy Modes

Add handling of the LE Set Privacy Mode HCI Command along with the logic
required to take it into account when populating the hardware filters.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
Carles Cufi 2017-06-25 18:12:37 +02:00 committed by Johan Hedberg
commit 2c1dbd21f4
3 changed files with 50 additions and 2 deletions

View file

@ -415,6 +415,8 @@ static void read_supported_commands(struct net_buf *buf, struct net_buf **evt)
rp->commands[34] |= BIT(3) | BIT(4) | BIT(5) | BIT(6) | BIT(7);
/* LE Read Local RPA, LE Set AR Enable, Set RPA Timeout */
rp->commands[35] |= BIT(0) | BIT(1) | BIT(2);
/* LE Set Privacy Mode */
rp->commands[39] |= BIT(2);
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
#if defined(CONFIG_BLUETOOTH_CONTROLLER_DATA_LENGTH)
@ -1157,6 +1159,18 @@ static void le_set_rpa_timeout(struct net_buf *buf, struct net_buf **evt)
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = 0x00;
}
static void le_set_privacy_mode(struct net_buf *buf, struct net_buf **evt)
{
struct bt_hci_cp_le_set_privacy_mode *cmd = (void *)buf->data;
struct bt_hci_evt_cc_status *ccst;
u32_t status;
status = ll_priv_mode_set(&cmd->id_addr, cmd->mode);
ccst = cmd_complete(evt, sizeof(*ccst));
ccst->status = status;
}
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
@ -1346,6 +1360,9 @@ static int controller_cmd_handle(u16_t ocf, struct net_buf *cmd,
case BT_OCF(BT_HCI_OP_LE_SET_RPA_TIMEOUT):
le_set_rpa_timeout(cmd, evt);
break;
case BT_OCF(BT_HCI_OP_LE_SET_PRIVACY_MODE):
le_set_privacy_mode(cmd, evt);
break;
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */

View file

@ -47,6 +47,7 @@ u32_t ll_rl_prpa_get(bt_addr_le_t *id_addr, bt_addr_t *prpa);
u32_t ll_rl_lrpa_get(bt_addr_le_t *id_addr, bt_addr_t *lrpa);
u32_t ll_rl_enable(u8_t enable);
void ll_rl_timeout_set(u16_t timeout);
u32_t ll_priv_mode_set(bt_addr_le_t *id_addr, u8_t mode);
void ll_irk_clear(void);
u32_t ll_irk_add(u8_t *irk);

View file

@ -50,6 +50,7 @@ static struct rl_dev {
u8_t pirk:1;
u8_t pirk_idx:3;
u8_t lirk:1;
u8_t dev:1;
u8_t id_addr_type:1;
bt_addr_t id_addr;
@ -267,7 +268,7 @@ static void filter_wl_update(void)
for (i = 0; i < WL_SIZE; i++) {
int j = wl_peers[i].rl_idx;
if (!rl_enable || j == IDX_NONE || !rl[j].pirk) {
if (!rl_enable || j == IDX_NONE || !rl[j].pirk || rl[j].dev) {
filter_insert(&wl, i, wl_peers[i].id_addr_type,
wl_peers[i].id_addr.val);
}
@ -281,7 +282,7 @@ static void filter_rl_update(void)
filter_clear(&rl_filter);
for (i = 0; i < CONFIG_BLUETOOTH_CONTROLLER_RL_SIZE; i++) {
if (!rl[i].pirk) {
if (!rl[i].pirk || rl[i].dev) {
filter_insert(&rl_filter, i, rl[i].id_addr_type,
rl[i].id_addr.val);
}
@ -557,6 +558,8 @@ u32_t ll_rl_add(bt_addr_le_t *id_addr, const u8_t pirk[16],
memcpy(rl[i].local_irk, lirk, 16);
}
rl[i].rpas_ready = 0;
/* Default to Network Privacy */
rl[i].dev = 0;
/* Add reference to a whitelist entry */
j = wl_peers_find(id_addr->type, id_addr->a.val);
if (j >= 0) {
@ -667,6 +670,33 @@ void ll_rl_timeout_set(u16_t timeout)
{
rpa_timeout_ms = timeout * 1000;
}
u32_t ll_priv_mode_set(bt_addr_le_t *id_addr, u8_t mode)
{
int i;
if (!rl_access_check(false)) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
/* find the device and mark it as empty */
i = ll_rl_find(id_addr->type, id_addr->a.val);
if (i >= 0) {
switch (mode) {
case BT_HCI_LE_PRIVACY_MODE_NETWORK:
rl[i].dev = 0;
break;
case BT_HCI_LE_PRIVACY_MODE_DEVICE:
rl[i].dev = 1;
break;
default:
return BT_HCI_ERR_INVALID_PARAM;
}
}
return BT_HCI_ERR_UNKNOWN_CONN_ID;
}
#endif /* CONFIG_BLUETOOTH_CONTROLLER_PRIVACY */
void ll_filter_reset(bool init)