linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ayush Garg <ayush.garg@samsung.com>
To: linux-bluetooth@vger.kernel.org
Cc: anupam.r@samsung.com, nitin.j@samsung.com
Subject: [PATCH BlueZ 3/7] adapter: Add support for get/set phy configuration property
Date: Thu, 22 Jul 2021 10:56:36 +0530	[thread overview]
Message-ID: <20210722052640.5863-4-ayush.garg@samsung.com> (raw)
In-Reply-To: <20210722052640.5863-1-ayush.garg@samsung.com>

This change introduces a new adapter property(PhyConfiguration)
which will be used to read and set controller's PHY.
This property is based upon MGMT_OP_GET_PHY_CONFIGURATION
and MGMT_OP_SET_PHY_CONFIGURATION operations.

Reviewed-by: Anupam Roy <anupam.r@samsung.com>
---
 src/adapter.c | 282 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 282 insertions(+)

diff --git a/src/adapter.c b/src/adapter.c
index 12e4ff5c0..fd4c654dc 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -285,6 +285,11 @@ struct btd_adapter {
 
 	bool le_simult_roles_supported;
 	bool quality_report_supported;
+
+	uint32_t supported_phys;
+	uint32_t configurable_phys;
+	uint32_t selected_phys;
+	uint32_t pending_phys;
 };
 
 typedef enum {
@@ -3245,6 +3250,237 @@ static gboolean property_get_roles(const GDBusPropertyTable *property,
 	return TRUE;
 }
 
+static struct phys_config {
+	uint32_t flag;
+	const char *name;
+} phys_str[] = {
+	{ MGMT_PHY_BR_1M_1SLOT, "BR1M1SLOT" },
+	{ MGMT_PHY_BR_1M_3SLOT, "BR1M3SLOT" },
+	{ MGMT_PHY_BR_1M_5SLOT, "BR1M5SLOT" },
+	{ MGMT_PHY_EDR_2M_1SLOT, "EDR2M1SLOT" },
+	{ MGMT_PHY_EDR_2M_3SLOT, "EDR2M3SLOT" },
+	{ MGMT_PHY_EDR_2M_5SLOT, "EDR2M5SLOT" },
+	{ MGMT_PHY_EDR_3M_1SLOT, "EDR3M1SLOT" },
+	{ MGMT_PHY_EDR_3M_3SLOT, "EDR3M3SLOT" },
+	{ MGMT_PHY_EDR_3M_5SLOT, "EDR3M5SLOT" },
+	{ MGMT_PHY_LE_1M_TX, "LE1MTX" },
+	{ MGMT_PHY_LE_1M_RX, "LE1MRX" },
+	{ MGMT_PHY_LE_2M_TX, "LE2MTX" },
+	{ MGMT_PHY_LE_2M_RX, "LE2MRX" },
+	{ MGMT_PHY_LE_CODED_TX, "LECODEDTX" },
+	{ MGMT_PHY_LE_CODED_RX, "LECODEDRX" }
+};
+
+static void append_phys_str(DBusMessageIter *array, uint32_t phys)
+{
+	unsigned int i;
+
+	for (i = 0; i < NELEM(phys_str); i++) {
+		if (phys & phys_str[i].flag)
+			dbus_message_iter_append_basic(array, DBUS_TYPE_STRING,
+						&phys_str[i].name);
+	}
+}
+
+static bool parse_phys_str(DBusMessageIter *array, uint32_t *phys)
+{
+	const char *str;
+	unsigned int i;
+
+	*phys = 0;
+
+	do {
+		if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_STRING)
+			return false;
+
+		dbus_message_iter_get_basic(array, &str);
+
+		for (i = 0; i < NELEM(phys_str); i++) {
+			if (!strcmp(str, phys_str[i].name)) {
+				*phys |= phys_str[i].flag;
+				break;
+			}
+		}
+
+		if (i == NELEM(phys_str))
+			return false;
+	} while (dbus_message_iter_next(array));
+
+	return true;
+}
+
+static void set_default_phy_complete(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	struct property_set_data *data = user_data;
+	struct btd_adapter *adapter = data->adapter;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		adapter->pending_phys = 0;
+		btd_error(adapter->dev_id,
+				"Failed to set PHY configuration: %s (0x%02x)",
+						mgmt_errstr(status), status);
+		g_dbus_pending_property_error(data->id, ERROR_INTERFACE ".Failed",
+							mgmt_errstr(status));
+		return;
+	}
+
+	/* The default phys are successfully set. */
+	btd_info(adapter->dev_id, "PHY configuration successfully set");
+
+	adapter->selected_phys = adapter->pending_phys;
+	adapter->pending_phys = 0;
+
+	g_dbus_pending_property_success(data->id);
+
+	g_dbus_emit_property_changed(dbus_conn, adapter->path,
+					ADAPTER_INTERFACE, "PhyConfiguration");
+}
+
+static int set_default_phy(struct btd_adapter *adapter, uint32_t phys,
+			GDBusPendingPropertySet id)
+{
+	struct mgmt_cp_set_phy_confguration cp;
+	struct property_set_data *data;
+	uint32_t unconfigure_phys;
+
+	if (!phys) {
+		btd_error(adapter->dev_id,
+			"Set PHY configuration failed: No supplied phy(s)");
+		return -EINVAL;
+	}
+
+	if (phys & ~(adapter->supported_phys)) {
+		btd_error(adapter->dev_id,
+			"Set PHY configuration failed: supplied phy(s) is not supported");
+		return -EINVAL;
+	}
+
+	if (phys == adapter->selected_phys) {
+		DBG("PHYs are already set [0x%x]", phys);
+		g_dbus_pending_property_success(id);
+		return 0;
+	}
+
+	unconfigure_phys = adapter->supported_phys & ~(adapter->configurable_phys);
+
+	if ((phys & unconfigure_phys) != unconfigure_phys) {
+		btd_error(adapter->dev_id,
+			"Set PHY configuration failed: supplied phy(s) must include PHYs %u",
+			unconfigure_phys);
+		return -EINVAL;
+	}
+
+	if (adapter->pending_phys) {
+		btd_error(adapter->dev_id,
+			"Set PHY configuration failed: Operation in progress");
+		return -EINPROGRESS;
+	}
+
+	adapter->pending_phys = phys;
+
+	cp.selected_phys = cpu_to_le32(phys);
+
+	data = g_try_new0(struct property_set_data, 1);
+	if (!data)
+		goto failed;
+
+	data->adapter = adapter;
+	data->id = id;
+
+	DBG("sending set phy configuration command for index %u", adapter->dev_id);
+
+	if (mgmt_send(adapter->mgmt, MGMT_OP_SET_PHY_CONFIGURATION,
+				adapter->dev_id, sizeof(cp), &cp,
+				set_default_phy_complete, data, g_free) > 0)
+		return 0;
+
+	g_free(data);
+
+failed:
+	btd_error(adapter->dev_id, "Failed to set PHY configuration for index %u",
+							adapter->dev_id);
+	adapter->pending_phys = 0;
+
+	return -EIO;
+}
+
+static gboolean property_get_phy_configuration(
+					const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	DBusMessageIter array;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "s", &array);
+
+	append_phys_str(&array, adapter->selected_phys);
+
+	dbus_message_iter_close_container(iter, &array);
+
+	return TRUE;
+}
+
+static void property_set_phy_configuration(
+				const GDBusPropertyTable *property,
+				DBusMessageIter *iter,
+				GDBusPendingPropertySet id, void *user_data)
+{
+	struct btd_adapter *adapter = user_data;
+	DBusMessageIter array;
+	uint32_t phys;
+	int ret;
+
+	if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) {
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	dbus_message_iter_recurse(iter, &array);
+
+	if (!(adapter->supported_settings & MGMT_SETTING_PHY_CONFIGURATION)) {
+		ret = -ENOTSUP;
+		goto failed;
+	}
+
+	if (!parse_phys_str(&array, &phys)) {
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	ret = set_default_phy(adapter, phys, id);
+
+	/*
+	 * gdbus_pending_property_success event will be sent when success status
+	 * will be received from mgmt.
+	 */
+	if (!ret)
+		return;
+
+failed:
+	switch (-ret) {
+	case EINVAL:
+		g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".InvalidArguments",
+					"Invalid arguments in method call");
+		break;
+	case ENOTSUP:
+		g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".NotSupported",
+					"Operation is not supported");
+		break;
+	case EINPROGRESS:
+		g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".InProgress",
+					"Operation is in progress");
+		break;
+	default:
+		g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed",
+							strerror(-ret));
+		break;
+	}
+}
+
 static DBusMessage *remove_device(DBusConnection *conn,
 					DBusMessage *msg, void *user_data)
 {
@@ -3517,6 +3753,8 @@ static const GDBusPropertyTable adapter_properties[] = {
 	{ "Modalias", "s", property_get_modalias, NULL,
 					property_exists_modalias },
 	{ "Roles", "as", property_get_roles },
+	{ "PhyConfiguration", "as", property_get_phy_configuration,
+					property_set_phy_configuration },
 	{ }
 };
 
@@ -9389,6 +9627,43 @@ static void read_exp_features(struct btd_adapter *adapter)
 	btd_error(adapter->dev_id, "Failed to read exp features info");
 }
 
+static void read_phy_configuration_resp(uint8_t status, uint16_t length,
+					const void *param, void *user_data)
+{
+	const struct mgmt_rp_get_phy_confguration *rp = param;
+	struct btd_adapter *adapter = user_data;
+
+	if (status != MGMT_STATUS_SUCCESS) {
+		btd_error(adapter->dev_id,
+				"Failed to get PHY configuration info: %s (0x%02x)",
+				mgmt_errstr(status), status);
+		return;
+	}
+
+	if (length < sizeof(*rp)) {
+		btd_error(adapter->dev_id, "Response too small");
+		return;
+	}
+
+	adapter->supported_phys = get_le32(&rp->supported_phys);
+	adapter->configurable_phys = get_le32(&rp->configurable_phys);
+	adapter->selected_phys = get_le32(&rp->selected_phys);
+
+	DBG("Supported phys: [0x%x]", adapter->supported_phys);
+	DBG("Configurable phys: [0x%x]", adapter->configurable_phys);
+	DBG("Selected phys: [0x%x]", adapter->selected_phys);
+}
+
+static void read_phy_configuration(struct btd_adapter *adapter)
+{
+	if (mgmt_send(adapter->mgmt, MGMT_OP_GET_PHY_CONFIGURATION,
+			adapter->dev_id, 0, NULL, read_phy_configuration_resp,
+			adapter, NULL) > 0)
+		return;
+
+	btd_error(adapter->dev_id, "Failed to read phy configuration info");
+}
+
 static void read_info_complete(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -9498,6 +9773,13 @@ static void read_info_complete(uint8_t status, uint16_t length,
 			(missing_settings & MGMT_SETTING_FAST_CONNECTABLE))
 		set_mode(adapter, MGMT_OP_SET_FAST_CONNECTABLE, 0x01);
 
+	if (btd_opts.experimental &&
+			btd_has_kernel_features(KERNEL_EXP_FEATURES))
+		read_exp_features(adapter);
+
+	if (adapter->supported_settings & MGMT_SETTING_PHY_CONFIGURATION)
+		read_phy_configuration(adapter);
+
 	err = adapter_register(adapter);
 	if (err < 0) {
 		btd_error(adapter->dev_id, "Unable to register new adapter");
-- 
2.17.1


  parent reply	other threads:[~2021-07-22  5:59 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20210722052737epcas5p1682a7f66d42470c3cdb8dd04160912ab@epcas5p1.samsung.com>
2021-07-22  5:26 ` [PATCH BlueZ 0/7] Support for Adapter's Default PHY Configuration Ayush Garg
     [not found]   ` <CGME20210722052738epcas5p3b6074e49f088159e8282bba3457d56ba@epcas5p3.samsung.com>
2021-07-22  5:26     ` [PATCH BlueZ 1/7] doc/adapter-api: Add SupportedPhyConfiguration property Ayush Garg
2021-07-22  6:45       ` Support for Adapter's Default PHY Configuration bluez.test.bot
2021-07-22 14:46       ` [PATCH BlueZ 1/7] doc/adapter-api: Add SupportedPhyConfiguration property Marcel Holtmann
     [not found]   ` <CGME20210722052739epcas5p4412d38b394f51ab195c77c887f0a0aaf@epcas5p4.samsung.com>
2021-07-22  5:26     ` [PATCH BlueZ 2/7] doc/adapter-api: Add PhyConfiguration property Ayush Garg
2021-07-22 17:20       ` Luiz Augusto von Dentz
     [not found]   ` <CGME20210722052740epcas5p1fce869a24434f376d111e9e5d4b208eb@epcas5p1.samsung.com>
2021-07-22  5:26     ` Ayush Garg [this message]
     [not found]   ` <CGME20210722052741epcas5p2cb3cbad65a301b0ec0cf1780c0920103@epcas5p2.samsung.com>
2021-07-22  5:26     ` [PATCH BlueZ 4/7] adapter: Add support for the get supported phy property Ayush Garg
     [not found]   ` <CGME20210722052742epcas5p1b53db2cd68028170a86f291bd052bf14@epcas5p1.samsung.com>
2021-07-22  5:26     ` [PATCH BlueZ 5/7] adapter: Add support for PHY Configuration Changed event Ayush Garg
     [not found]   ` <CGME20210722052743epcas5p34af6f55c11db2e8909c2730fae7e1cac@epcas5p3.samsung.com>
2021-07-22  5:26     ` [PATCH BlueZ 6/7] client: Add support for get/set PHY configuration in bluetoothctl Ayush Garg
     [not found]   ` <CGME20210722052744epcas5p46996d48d12500c39b4b63dfcecd30d37@epcas5p4.samsung.com>
2021-07-22  5:26     ` [PATCH BlueZ 7/7] adapter: Save PHY Configuration in storage and read it at init Ayush Garg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210722052640.5863-4-ayush.garg@samsung.com \
    --to=ayush.garg@samsung.com \
    --cc=anupam.r@samsung.com \
    --cc=linux-bluetooth@vger.kernel.org \
    --cc=nitin.j@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).