Skip to content

Commit cbbdfa6

Browse files
nsathish41holtmann
authored andcommitted
Bluetooth: Enable controller RPA resolution using Experimental feature
This patch adds support to enable the use of RPA Address resolution using expermental feature mgmt command. Signed-off-by: Sathish Narasimman <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent b2cc233 commit cbbdfa6

File tree

4 files changed

+148
-3
lines changed

4 files changed

+148
-3
lines changed

include/net/bluetooth/hci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ enum {
318318
HCI_FORCE_BREDR_SMP,
319319
HCI_FORCE_STATIC_ADDR,
320320
HCI_LL_RPA_RESOLUTION,
321+
HCI_ENABLE_LL_PRIVACY,
321322
HCI_CMD_PENDING,
322323
HCI_FORCE_NO_MITM,
323324

net/bluetooth/hci_event.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5230,6 +5230,7 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
52305230
le16_to_cpu(ev->supervision_timeout));
52315231

52325232
if (use_ll_privacy(hdev) &&
5233+
hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY) &&
52335234
hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION))
52345235
hci_req_disable_address_resolution(hdev);
52355236
}

net/bluetooth/hci_request.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,8 +678,10 @@ void hci_req_add_le_scan_disable(struct hci_request *req, bool rpa_le_conn)
678678

679679
/* Disable address resolution */
680680
if (use_ll_privacy(hdev) &&
681+
hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY) &&
681682
hci_dev_test_flag(hdev, HCI_LL_RPA_RESOLUTION) && !rpa_le_conn) {
682683
__u8 enable = 0x00;
684+
683685
hci_req_add(req, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE, 1, &enable);
684686
}
685687
}
@@ -870,8 +872,11 @@ static void hci_req_start_scan(struct hci_request *req, u8 type, u16 interval,
870872
return;
871873
}
872874

873-
if (use_ll_privacy(hdev) && addr_resolv) {
875+
if (use_ll_privacy(hdev) &&
876+
hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY) &&
877+
addr_resolv) {
874878
u8 enable = 0x01;
879+
875880
hci_req_add(req, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE, 1, &enable);
876881
}
877882

net/bluetooth/mgmt.c

Lines changed: 140 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -795,10 +795,15 @@ static u32 get_supported_settings(struct hci_dev *hdev)
795795

796796
if (lmp_le_capable(hdev)) {
797797
settings |= MGMT_SETTING_LE;
798-
settings |= MGMT_SETTING_ADVERTISING;
799798
settings |= MGMT_SETTING_SECURE_CONN;
800799
settings |= MGMT_SETTING_PRIVACY;
801800
settings |= MGMT_SETTING_STATIC_ADDRESS;
801+
802+
/* When the experimental feature for LL Privacy support is
803+
* enabled, then advertising is no longer supported.
804+
*/
805+
if (!hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
806+
settings |= MGMT_SETTING_ADVERTISING;
802807
}
803808

804809
if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
@@ -3759,10 +3764,16 @@ static const u8 simult_central_periph_uuid[16] = {
37593764
0x96, 0x46, 0xc0, 0x42, 0xb5, 0x10, 0x1b, 0x67,
37603765
};
37613766

3767+
/* 15c0a148-c273-11ea-b3de-0242ac130004 */
3768+
static const u8 rpa_resolution_uuid[16] = {
3769+
0x04, 0x00, 0x13, 0xac, 0x42, 0x02, 0xde, 0xb3,
3770+
0xea, 0x11, 0x73, 0xc2, 0x48, 0xa1, 0xc0, 0x15,
3771+
};
3772+
37623773
static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
37633774
void *data, u16 data_len)
37643775
{
3765-
char buf[44];
3776+
char buf[62]; /* Enough space for 3 features */
37663777
struct mgmt_rp_read_exp_features_info *rp = (void *)buf;
37673778
u16 idx = 0;
37683779
u32 flags;
@@ -3795,6 +3806,17 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
37953806
idx++;
37963807
}
37973808

3809+
if (hdev && use_ll_privacy(hdev)) {
3810+
if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
3811+
flags = BIT(0) | BIT(1);
3812+
else
3813+
flags = BIT(1);
3814+
3815+
memcpy(rp->features[idx].uuid, rpa_resolution_uuid, 16);
3816+
rp->features[idx].flags = cpu_to_le32(flags);
3817+
idx++;
3818+
}
3819+
37983820
rp->feature_count = cpu_to_le16(idx);
37993821

38003822
/* After reading the experimental features information, enable
@@ -3807,6 +3829,21 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
38073829
0, rp, sizeof(*rp) + (20 * idx));
38083830
}
38093831

3832+
static int exp_ll_privacy_feature_changed(bool enabled, struct hci_dev *hdev,
3833+
struct sock *skip)
3834+
{
3835+
struct mgmt_ev_exp_feature_changed ev;
3836+
3837+
memset(&ev, 0, sizeof(ev));
3838+
memcpy(ev.uuid, rpa_resolution_uuid, 16);
3839+
ev.flags = cpu_to_le32((enabled ? BIT(0) : 0) | BIT(1));
3840+
3841+
return mgmt_limited_event(MGMT_EV_EXP_FEATURE_CHANGED, hdev,
3842+
&ev, sizeof(ev),
3843+
HCI_MGMT_EXP_FEATURE_EVENTS, skip);
3844+
3845+
}
3846+
38103847
#ifdef CONFIG_BT_FEATURE_DEBUG
38113848
static int exp_debug_feature_changed(bool enabled, struct sock *skip)
38123849
{
@@ -3845,6 +3882,16 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
38453882
}
38463883
#endif
38473884

3885+
if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
3886+
bool changed = hci_dev_test_flag(hdev,
3887+
HCI_ENABLE_LL_PRIVACY);
3888+
3889+
hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
3890+
3891+
if (changed)
3892+
exp_ll_privacy_feature_changed(false, hdev, sk);
3893+
}
3894+
38483895
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
38493896

38503897
return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
@@ -3895,6 +3942,69 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
38953942
}
38963943
#endif
38973944

3945+
if (!memcmp(cp->uuid, rpa_resolution_uuid, 16)) {
3946+
bool val, changed;
3947+
int err;
3948+
u32 flags;
3949+
3950+
/* Command requires to use the controller index */
3951+
if (!hdev)
3952+
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
3953+
MGMT_OP_SET_EXP_FEATURE,
3954+
MGMT_STATUS_INVALID_INDEX);
3955+
3956+
/* Changes can only be made when controller is powered down */
3957+
if (hdev_is_powered(hdev))
3958+
return mgmt_cmd_status(sk, hdev->id,
3959+
MGMT_OP_SET_EXP_FEATURE,
3960+
MGMT_STATUS_NOT_POWERED);
3961+
3962+
/* Parameters are limited to a single octet */
3963+
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
3964+
return mgmt_cmd_status(sk, hdev->id,
3965+
MGMT_OP_SET_EXP_FEATURE,
3966+
MGMT_STATUS_INVALID_PARAMS);
3967+
3968+
/* Only boolean on/off is supported */
3969+
if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
3970+
return mgmt_cmd_status(sk, hdev->id,
3971+
MGMT_OP_SET_EXP_FEATURE,
3972+
MGMT_STATUS_INVALID_PARAMS);
3973+
3974+
val = !!cp->param[0];
3975+
3976+
if (val) {
3977+
changed = !hci_dev_test_flag(hdev,
3978+
HCI_ENABLE_LL_PRIVACY);
3979+
hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY);
3980+
hci_dev_clear_flag(hdev, HCI_ADVERTISING);
3981+
3982+
/* Enable LL privacy + supported settings changed */
3983+
flags = BIT(0) | BIT(1);
3984+
} else {
3985+
changed = hci_dev_test_flag(hdev,
3986+
HCI_ENABLE_LL_PRIVACY);
3987+
hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
3988+
3989+
/* Disable LL privacy + supported settings changed */
3990+
flags = BIT(1);
3991+
}
3992+
3993+
memcpy(rp.uuid, rpa_resolution_uuid, 16);
3994+
rp.flags = cpu_to_le32(flags);
3995+
3996+
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
3997+
3998+
err = mgmt_cmd_complete(sk, hdev->id,
3999+
MGMT_OP_SET_EXP_FEATURE, 0,
4000+
&rp, sizeof(rp));
4001+
4002+
if (changed)
4003+
exp_ll_privacy_feature_changed(val, hdev, sk);
4004+
4005+
return err;
4006+
}
4007+
38984008
return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
38994009
MGMT_OP_SET_EXP_FEATURE,
39004010
MGMT_STATUS_NOT_SUPPORTED);
@@ -5040,6 +5150,13 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
50405150
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
50415151
status);
50425152

5153+
/* Enabling the experimental LL Privay support disables support for
5154+
* advertising.
5155+
*/
5156+
if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
5157+
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
5158+
MGMT_STATUS_NOT_SUPPORTED);
5159+
50435160
if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
50445161
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
50455162
MGMT_STATUS_INVALID_PARAMS);
@@ -7112,6 +7229,13 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
71127229
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
71137230
MGMT_STATUS_REJECTED);
71147231

7232+
/* Enabling the experimental LL Privay support disables support for
7233+
* advertising.
7234+
*/
7235+
if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
7236+
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
7237+
MGMT_STATUS_NOT_SUPPORTED);
7238+
71157239
hci_dev_lock(hdev);
71167240

71177241
rp_len = sizeof(*rp) + hdev->adv_instance_cnt;
@@ -7315,6 +7439,13 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev,
73157439
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
73167440
status);
73177441

7442+
/* Enabling the experimental LL Privay support disables support for
7443+
* advertising.
7444+
*/
7445+
if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
7446+
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
7447+
MGMT_STATUS_NOT_SUPPORTED);
7448+
73187449
if (cp->instance < 1 || cp->instance > HCI_MAX_ADV_INSTANCES)
73197450
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
73207451
MGMT_STATUS_INVALID_PARAMS);
@@ -7479,6 +7610,13 @@ static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
74797610

74807611
bt_dev_dbg(hdev, "sock %p", sk);
74817612

7613+
/* Enabling the experimental LL Privay support disables support for
7614+
* advertising.
7615+
*/
7616+
if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
7617+
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
7618+
MGMT_STATUS_NOT_SUPPORTED);
7619+
74827620
hci_dev_lock(hdev);
74837621

74847622
if (cp->instance && !hci_find_adv_instance(hdev, cp->instance)) {

0 commit comments

Comments
 (0)