Skip to content

Commit

Permalink
device: Fix enabling wake support without RPA Resolution
Browse files Browse the repository at this point in the history
If device uses RPA it shall only enable wakeup if RPA Resolution has
been enabled otherwise it cannot be programmed in the acceptlist which
can cause suspend to fail.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=215768
  • Loading branch information
Vudentz committed May 12, 2022
1 parent 83497bb commit 7a4b67f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 6 deletions.
34 changes: 28 additions & 6 deletions src/adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -4761,6 +4761,9 @@ static void load_devices(struct btd_adapter *adapter)
if (!device)
goto free;

if (irk_info)
device_set_rpa(device, true);

btd_device_set_temporary(device, false);
adapter_add_device(adapter, device);

Expand Down Expand Up @@ -9569,8 +9572,9 @@ static bool set_blocked_keys(struct btd_adapter *adapter)
adapter, NULL);
}

#define EXP_FEAT(_uuid, _func) \
#define EXP_FEAT(_flag, _uuid, _func) \
{ \
.flag = _flag, \
.uuid = _uuid, \
.func = _func, \
}
Expand Down Expand Up @@ -9692,15 +9696,18 @@ static void codec_offload_func(struct btd_adapter *adapter, uint8_t action)
}

static const struct exp_feat {
uint32_t flag;
const struct mgmt_exp_uuid *uuid;
void (*func)(struct btd_adapter *adapter, uint8_t action);
} exp_table[] = {
EXP_FEAT(&debug_uuid, exp_debug_func),
EXP_FEAT(&le_simult_central_peripheral_uuid,
EXP_FEAT(EXP_FEAT_DEBUG, &debug_uuid, exp_debug_func),
EXP_FEAT(EXP_FEAT_LE_SIMULT_ROLES, &le_simult_central_peripheral_uuid,
le_simult_central_peripheral_func),
EXP_FEAT(&quality_report_uuid, quality_report_func),
EXP_FEAT(&rpa_resolution_uuid, rpa_resolution_func),
EXP_FEAT(&codec_offload_uuid, codec_offload_func),
EXP_FEAT(EXP_FEAT_BQR, &quality_report_uuid, quality_report_func),
EXP_FEAT(EXP_FEAT_RPA_RESOLUTION, &rpa_resolution_uuid,
rpa_resolution_func),
EXP_FEAT(EXP_FEAT_CODEC_OFFLOAD, &codec_offload_uuid,
codec_offload_func),
};

static void read_exp_features_complete(uint8_t status, uint16_t length,
Expand Down Expand Up @@ -10451,3 +10458,18 @@ bool btd_has_kernel_features(uint32_t features)
{
return (kernel_features & features) ? true : false;
}

bool btd_adapter_has_exp_feature(struct btd_adapter *adapter, uint32_t feature)
{
size_t i;

for (i = 0; i < ARRAY_SIZE(exp_table); i++) {
const struct exp_feat *feat = &exp_table[i];

if ((feat->flag & feature) && queue_find(adapter->exps, NULL,
feat->uuid->val))
return true;
}

return false;
}
10 changes: 10 additions & 0 deletions src/adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,16 @@ void btd_adapter_for_each_device(struct btd_adapter *adapter,

bool btd_le_connect_before_pairing(void);

enum experimental_features {
EXP_FEAT_DEBUG = 1 << 0,
EXP_FEAT_LE_SIMULT_ROLES = 1 << 1,
EXP_FEAT_BQR = 1 << 2,
EXP_FEAT_RPA_RESOLUTION = 1 << 3,
EXP_FEAT_CODEC_OFFLOAD = 1 << 4,
};

bool btd_adapter_has_exp_feature(struct btd_adapter *adapter, uint32_t feature);

enum kernel_features {
KERNEL_CONN_CONTROL = 1 << 0,
KERNEL_BLOCKED_KEYS_SUPPORTED = 1 << 1,
Expand Down
14 changes: 14 additions & 0 deletions src/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ struct btd_device {
uint8_t conn_bdaddr_type;
bdaddr_t bdaddr;
uint8_t bdaddr_type;
bool rpa;
char *path;
bool bredr;
bool le;
Expand Down Expand Up @@ -1460,6 +1461,12 @@ static bool device_get_wake_support(struct btd_device *device)

void device_set_wake_support(struct btd_device *device, bool wake_support)
{
if (device->rpa && !btd_adapter_has_exp_feature(device->adapter,
EXP_FEAT_RPA_RESOLUTION)) {
warn("Unable to set wake_support without RPA resolution");
return;
}

device->wake_support = wake_support;

/* If wake configuration has not been made yet, set the initial
Expand Down Expand Up @@ -4595,11 +4602,18 @@ void device_set_class(struct btd_device *device, uint32_t class)
DEVICE_INTERFACE, "Icon");
}

void device_set_rpa(struct btd_device *device, bool value)
{
device->rpa = value;
}

void device_update_addr(struct btd_device *device, const bdaddr_t *bdaddr,
uint8_t bdaddr_type)
{
bool auto_connect = device->auto_connect;

device_set_rpa(device, true);

if (!bacmp(bdaddr, &device->bdaddr) &&
bdaddr_type == device->bdaddr_type)
return;
Expand Down
1 change: 1 addition & 0 deletions src/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ bool device_name_known(struct btd_device *device);
bool device_is_name_resolve_allowed(struct btd_device *device);
void device_name_resolve_fail(struct btd_device *device);
void device_set_class(struct btd_device *device, uint32_t class);
void device_set_rpa(struct btd_device *device, bool value);
void device_update_addr(struct btd_device *device, const bdaddr_t *bdaddr,
uint8_t bdaddr_type);
void device_set_bredr_support(struct btd_device *device);
Expand Down

0 comments on commit 7a4b67f

Please sign in to comment.