Commit 93fb70bc authored by Joseph Hwang's avatar Joseph Hwang Committed by Marcel Holtmann
Browse files

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: default avatarJoseph Hwang <josephsih@chromium.org>
Signed-off-by: default avatarLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
parent 76a56bbd
Loading
Loading
Loading
Loading
+142 −106
Original line number Diff line number Diff line
@@ -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);

@@ -3933,7 +3935,11 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
}

#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;

@@ -3975,7 +3981,11 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
}
#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 */
@@ -4038,6 +4046,34 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
	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,
			       MGMT_OP_SET_EXP_FEATURE,
			       MGMT_STATUS_NOT_SUPPORTED);