Bluetooth: refactor set_exp_feature with a feature table

This patch refactors the set_exp_feature with a feature table
consisting of UUIDs and the corresponding callback functions.
In this way, a new experimental feature setting function can be
simply added with its UUID and callback function.

Signed-off-by: Joseph Hwang <josephsih@chromium.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Joseph Hwang 2021-08-15 20:17:15 +08:00 committed by Marcel Holtmann
parent 76a56bbd81
commit 93fb70bc11

View file

@ -3892,15 +3892,18 @@ static int exp_debug_feature_changed(bool enabled, struct sock *skip)
}
#endif
static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
#define EXP_FEAT(_uuid, _set_func) \
{ \
.uuid = _uuid, \
.set_func = _set_func, \
}
/* The zero key uuid is special. Multiple exp features are set through it. */
static int set_zero_key_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp, u16 data_len)
{
struct mgmt_cp_set_exp_feature *cp = data;
struct mgmt_rp_set_exp_feature rp;
bt_dev_dbg(hdev, "sock %p", sk);
if (!memcmp(cp->uuid, ZERO_KEY, 16)) {
memset(rp.uuid, 0, 16);
rp.flags = cpu_to_le32(0);
@ -3916,8 +3919,7 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
#endif
if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
bool changed = hci_dev_test_flag(hdev,
HCI_ENABLE_LL_PRIVACY);
bool changed = hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
@ -3930,10 +3932,14 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE, 0,
&rp, sizeof(rp));
}
}
#ifdef CONFIG_BT_FEATURE_DEBUG
if (!memcmp(cp->uuid, debug_uuid, 16)) {
static int set_debug_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp, u16 data_len)
{
struct mgmt_rp_set_exp_feature rp;
bool val, changed;
int err;
@ -3972,10 +3978,14 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
exp_debug_feature_changed(val, sk);
return err;
}
}
#endif
if (!memcmp(cp->uuid, rpa_resolution_uuid, 16)) {
static int set_rpa_resolution_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp,
u16 data_len)
{
struct mgmt_rp_set_exp_feature rp;
bool val, changed;
int err;
u32 flags;
@ -4007,16 +4017,14 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
val = !!cp->param[0];
if (val) {
changed = !hci_dev_test_flag(hdev,
HCI_ENABLE_LL_PRIVACY);
changed = !hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY);
hci_dev_clear_flag(hdev, HCI_ADVERTISING);
/* Enable LL privacy + supported settings changed */
flags = BIT(0) | BIT(1);
} else {
changed = hci_dev_test_flag(hdev,
HCI_ENABLE_LL_PRIVACY);
changed = hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
/* Disable LL privacy + supported settings changed */
@ -4036,6 +4044,34 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
exp_ll_privacy_feature_changed(val, hdev, sk);
return err;
}
static const struct mgmt_exp_feature {
const u8 *uuid;
int (*set_func)(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp, u16 data_len);
} exp_features[] = {
EXP_FEAT(ZERO_KEY, set_zero_key_func),
#ifdef CONFIG_BT_FEATURE_DEBUG
EXP_FEAT(debug_uuid, set_debug_func),
#endif
EXP_FEAT(rpa_resolution_uuid, set_rpa_resolution_func),
/* end with a null feature */
EXP_FEAT(NULL, NULL)
};
static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_cp_set_exp_feature *cp = data;
size_t i = 0;
bt_dev_dbg(hdev, "sock %p", sk);
for (i = 0; exp_features[i].uuid; i++) {
if (!memcmp(cp->uuid, exp_features[i].uuid, 16))
return exp_features[i].set_func(sk, hdev, cp, data_len);
}
return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,