Bluetooth: Workaround privacy feature issue

This fixes intercompatibility issues with controllers supporting
privacy feature.
Core Spec requires to use network privacy mode as a default when
peer device provides its IRK during bonding when LL Privacy is used,
which is the case for Zephyr. We've seen devices including PTS
which exchanges it's IRK but is not aware about network privacy
mode. This results in Zephyr not able do be reconnect to such bonded
devices.
This workaround sets device privacy mode to be able to reconnect
to such devices.

Fixes #4989
Fixes #5486

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This commit is contained in:
Mariusz Skamra 2018-03-01 12:02:12 +01:00 committed by Carles Cufí
commit 777f9c8cd0

View file

@ -2295,6 +2295,32 @@ static void role_change(struct net_buf *buf)
#endif /* CONFIG_BT_BREDR */
#if defined(CONFIG_BT_SMP)
static int le_set_privacy_mode(const bt_addr_le_t *addr, u8_t mode)
{
struct bt_hci_cp_le_set_privacy_mode cp;
struct net_buf *buf;
int err;
BT_DBG("addr %s mode 0x%02x", bt_addr_le_str(addr), mode);
bt_addr_le_copy(&cp.id_addr, addr);
cp.mode = mode;
buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PRIVACY_MODE, sizeof(cp));
if (!buf) {
return -ENOBUFS;
}
net_buf_add_mem(buf, &cp, sizeof(cp));
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_PRIVACY_MODE, buf, NULL);
if (err) {
return err;
}
return 0;
}
static int addr_res_enable(u8_t enable)
{
struct net_buf *buf;
@ -2400,6 +2426,24 @@ int bt_id_add(struct bt_keys *keys)
bt_dev.le.rl_entries++;
/*
* According to Core Spec. 5.0 Vol 1, Part A 5.4.5 Privacy Feature
*
* By default, network privacy mode is used when private addresses are
* resolved and generated by the Controller, so advertising packets from
* peer devices that contain private addresses will only be accepted.
* By changing to the device privacy mode device is only concerned about
* its privacy and will accept advertising packets from peer devices
* that contain their identity address as well as ones that contain
* a private address, even if the peer device has distributed its IRK in
* the past.
*/
err = le_set_privacy_mode(&keys->addr, BT_HCI_LE_PRIVACY_MODE_DEVICE);
if (err) {
BT_ERR("Failed to set privacy mode");
goto done;
}
done:
addr_res_enable(BT_HCI_ADDR_RES_ENABLE);