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:
committed by
Marcel Holtmann
parent
76a56bbd81
commit
93fb70bc11
@ -3892,15 +3892,18 @@ static int exp_debug_feature_changed(bool enabled, struct sock *skip)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
|
#define EXP_FEAT(_uuid, _set_func) \
|
||||||
void *data, u16 data_len)
|
{ \
|
||||||
|
.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;
|
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);
|
memset(rp.uuid, 0, 16);
|
||||||
rp.flags = cpu_to_le32(0);
|
rp.flags = cpu_to_le32(0);
|
||||||
|
|
||||||
@ -3916,8 +3919,7 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
|
if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
|
||||||
bool changed = hci_dev_test_flag(hdev,
|
bool changed = hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
|
||||||
HCI_ENABLE_LL_PRIVACY);
|
|
||||||
|
|
||||||
hci_dev_clear_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,
|
return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
|
||||||
MGMT_OP_SET_EXP_FEATURE, 0,
|
MGMT_OP_SET_EXP_FEATURE, 0,
|
||||||
&rp, sizeof(rp));
|
&rp, sizeof(rp));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_BT_FEATURE_DEBUG
|
#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;
|
bool val, changed;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
@ -3972,10 +3978,14 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
|
|||||||
exp_debug_feature_changed(val, sk);
|
exp_debug_feature_changed(val, sk);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
bool val, changed;
|
||||||
int err;
|
int err;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
@ -4007,16 +4017,14 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
|
|||||||
val = !!cp->param[0];
|
val = !!cp->param[0];
|
||||||
|
|
||||||
if (val) {
|
if (val) {
|
||||||
changed = !hci_dev_test_flag(hdev,
|
changed = !hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
|
||||||
HCI_ENABLE_LL_PRIVACY);
|
|
||||||
hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY);
|
hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY);
|
||||||
hci_dev_clear_flag(hdev, HCI_ADVERTISING);
|
hci_dev_clear_flag(hdev, HCI_ADVERTISING);
|
||||||
|
|
||||||
/* Enable LL privacy + supported settings changed */
|
/* Enable LL privacy + supported settings changed */
|
||||||
flags = BIT(0) | BIT(1);
|
flags = BIT(0) | BIT(1);
|
||||||
} else {
|
} else {
|
||||||
changed = hci_dev_test_flag(hdev,
|
changed = hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
|
||||||
HCI_ENABLE_LL_PRIVACY);
|
|
||||||
hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
|
hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
|
||||||
|
|
||||||
/* Disable LL privacy + supported settings changed */
|
/* 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);
|
exp_ll_privacy_feature_changed(val, hdev, sk);
|
||||||
|
|
||||||
return err;
|
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,
|
return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
|
||||||
|
Reference in New Issue
Block a user