From 7a4b67f9caa6bdc004c910f3a52108744a8cab74 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 12 May 2022 16:40:49 -0700 Subject: [PATCH] device: Fix enabling wake support without RPA Resolution 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 --- src/adapter.c | 34 ++++++++++++++++++++++++++++------ src/adapter.h | 10 ++++++++++ src/device.c | 14 ++++++++++++++ src/device.h | 1 + 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/adapter.c b/src/adapter.c index db2624c60..f7faaa263 100644 --- a/src/adapter.c +++ b/src/adapter.c @@ -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); @@ -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, \ } @@ -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, @@ -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; +} diff --git a/src/adapter.h b/src/adapter.h index 35deb1d11..688ed51c6 100644 --- a/src/adapter.h +++ b/src/adapter.h @@ -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, diff --git a/src/device.c b/src/device.c index a39eb8c64..638bad061 100644 --- a/src/device.c +++ b/src/device.c @@ -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; @@ -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 @@ -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; diff --git a/src/device.h b/src/device.h index 9cdc0e68d..5e8d1c3e1 100644 --- a/src/device.h +++ b/src/device.h @@ -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); -- 2.47.3