linux-bluetooth.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH BlueZ 0/8] Support for connection specific LE PHY configuration
       [not found] <CGME20210722055008epcas5p28da6985b690d3bbc564a5957c1b209f4@epcas5p2.samsung.com>
@ 2021-07-22  5:49 ` Ayush Garg
       [not found]   ` <CGME20210722055009epcas5p25e4997aa7e53cb2a6e3780fdb7301785@epcas5p2.samsung.com>
                     ` (7 more replies)
  0 siblings, 8 replies; 11+ messages in thread
From: Ayush Garg @ 2021-07-22  5:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: anupam.r, nitin.j

Hello Maintainers,

This patch set contains a proposed approach to enable
user to get the PHYs of a particular LE connection
and to set preferred PHYs for the same on BT 5.0 and
above controllers.

It will introduce a new device property "Phy" which
is based on the L2CAP socket option "BT_PHY".

Note: This patch series is dependent on the the previous patch
series "Support for Adapter's Default PHY Configuration" and
should be applied after it.

Ayush Garg (8):
  doc/device-api: Add Phy property
  doc/mgmt-api: Add support for LE PHY Update Complete event
  btio: Add BT_IO_PHY option to set le phy options
  device: Add support for get/set PHY property
  adapter: Add support for LE PHY Update Complete event
  client: Add support for LE get/set device PHY in bluetoothctl
  device: Save device PHY in storage and read it at init
  monitor: Add support for LE PHY Update event

 btio/btio.c        |  25 ++++-
 client/main.c      |  45 ++++++++
 doc/device-api.txt |  22 ++++
 doc/mgmt-api.txt   |  29 ++++++
 lib/bluetooth.h    |   9 ++
 lib/mgmt.h         |   8 ++
 monitor/packet.c   |  14 +++
 src/adapter.c      |  48 +++++++++
 src/adapter.h      |   1 +
 src/device.c       | 248 +++++++++++++++++++++++++++++++++++++++++++++
 src/device.h       |   2 +
 11 files changed, 447 insertions(+), 4 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH BlueZ 1/8] doc/device-api: Add Phy property
       [not found]   ` <CGME20210722055009epcas5p25e4997aa7e53cb2a6e3780fdb7301785@epcas5p2.samsung.com>
@ 2021-07-22  5:49     ` Ayush Garg
  2021-07-22 17:33       ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 11+ messages in thread
From: Ayush Garg @ 2021-07-22  5:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: anupam.r, nitin.j

This will allow to set the LE PHY preferences for
a connected device.

Reviewed-by: Anupam Roy <anupam.r@samsung.com>
---
 doc/device-api.txt | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/doc/device-api.txt b/doc/device-api.txt
index 4e824d2de..d0e108f74 100644
--- a/doc/device-api.txt
+++ b/doc/device-api.txt
@@ -272,3 +272,25 @@ Properties	string Address [readonly]
 			Example:
 				<Transport Discovery> <Organization Flags...>
 				0x26                   0x01         0x01...
+
+		array{string} Phy [readwrite, optional]
+
+			PHY Preferences for a connected device.
+
+			Note: The controller might not be able to make the
+			change because of reasons like peer not supporting
+			the requested PHY or it couldnot schedule due to
+			other activites.
+
+			This is only available for LE capable controllers.
+			It will return Not Supported Otherwise.
+
+			Possible values:
+				"LE1MTX"
+				"LE1MRX"
+				"LE2MTX"
+				"LE2MRX"
+				"LECODEDTX"
+				"LECODEDRX"
+				"LECODEDS2"
+				"LECODEDS8"
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH BlueZ 2/8] doc/mgmt-api: Add support for LE PHY Update Complete event
       [not found]   ` <CGME20210722055010epcas5p45a16ff704c37d108a9df0d6c0a1942a8@epcas5p4.samsung.com>
@ 2021-07-22  5:49     ` Ayush Garg
  2021-07-22 14:45       ` Marcel Holtmann
  0 siblings, 1 reply; 11+ messages in thread
From: Ayush Garg @ 2021-07-22  5:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: anupam.r, nitin.j

Reviewed-by: Anupam Roy <anupam.r@samsung.com>
---
 doc/mgmt-api.txt | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index 5355fedb0..f7379fcd9 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -4910,3 +4910,32 @@ Controller Resume Event
 	Address_Type. Otherwise, Address and Address_Type will both be zero.
 
 	This event will be sent to all management sockets.
+
+
+LE PHY Update Complete Event
+===============================
+
+	Event Code:		0x002f
+	Controller Index:	<controller id>
+	Event Parameters:	Address (6 Octets)
+				Address_Type (1 Octet)
+				Status (1 Octet)
+				PHYs (4 Octets)
+
+	This event indicates that LE PHYs have been changed for this
+	connected device.
+
+	The PHYs parameters are a bitmask with currently the
+	following available bits:
+
+		9	LE 1M TX
+		10	LE 1M RX
+		11	LE 2M TX
+		12	LE 2M RX
+		13	LE Coded TX
+		14	LE Coded RX
+
+	This event will be used in case of autonomous PHY update made
+	by the controller or HCI_LE_SET_PHY command succeeded.
+
+	This event will be sent to all management sockets.
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH BlueZ 3/8] btio: Add BT_IO_PHY option to set le phy options
       [not found]   ` <CGME20210722055011epcas5p15299bfe8f8b8dd58e1354364071608e3@epcas5p1.samsung.com>
@ 2021-07-22  5:49     ` Ayush Garg
  0 siblings, 0 replies; 11+ messages in thread
From: Ayush Garg @ 2021-07-22  5:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: anupam.r, nitin.j

This patch adds support for the BT_IO_PHY socket
option through BtIO. This can be used to set preference
for LE TX & RX PHYs for a particular connection.

Reviewed-by: Anupam Roy <anupam.r@samsung.com>
---
 btio/btio.c | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/btio/btio.c b/btio/btio.c
index 1f1c374bc..6805ac438 100644
--- a/btio/btio.c
+++ b/btio/btio.c
@@ -66,6 +66,7 @@ struct set_opts {
 	int flushable;
 	uint32_t priority;
 	uint16_t voice;
+	uint32_t phy;
 };
 
 struct connect {
@@ -569,6 +570,14 @@ static int set_priority(int sock, uint32_t prio)
 	return 0;
 }
 
+static int l2cap_set_le_phy(int sock, uint32_t phy)
+{
+	if (setsockopt(sock, SOL_BLUETOOTH, BT_PHY, &phy, sizeof(phy)) < 0)
+		return -errno;
+
+	return 0;
+}
+
 static gboolean get_key_size(int sock, int *size, GError **err)
 {
 	struct bt_security sec;
@@ -657,7 +666,7 @@ static gboolean set_le_mode(int sock, uint8_t mode, GError **err)
 static gboolean l2cap_set(int sock, uint8_t src_type, int sec_level,
 				uint16_t imtu, uint16_t omtu, uint8_t mode,
 				int master, int flushable, uint32_t priority,
-				GError **err)
+				uint32_t phy, GError **err)
 {
 	if (imtu || omtu || mode) {
 		gboolean ret = FALSE;
@@ -694,6 +703,11 @@ static gboolean l2cap_set(int sock, uint8_t src_type, int sec_level,
 	if (sec_level && !set_sec_level(sock, BT_IO_L2CAP, sec_level, err))
 		return FALSE;
 
+	if (phy > 0 && l2cap_set_le_phy(sock, phy) < 0) {
+		ERROR_FAILED(err, "l2cap_set_le_phy", errno);
+		return FALSE;
+	}
+
 	return TRUE;
 }
 
@@ -834,6 +848,7 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
 	opts->priority = 0;
 	opts->src_type = BDADDR_BREDR;
 	opts->dst_type = BDADDR_BREDR;
+	opts->phy = 0;
 
 	while (opt != BT_IO_OPT_INVALID) {
 		switch (opt) {
@@ -904,13 +919,15 @@ static gboolean parse_set_opts(struct set_opts *opts, GError **err,
 		case BT_IO_OPT_VOICE:
 			opts->voice = va_arg(args, int);
 			break;
+		case BT_IO_OPT_PHY:
+			opts->phy = va_arg(args, int);
+			break;
 		case BT_IO_OPT_INVALID:
 		case BT_IO_OPT_KEY_SIZE:
 		case BT_IO_OPT_SOURCE_CHANNEL:
 		case BT_IO_OPT_DEST_CHANNEL:
 		case BT_IO_OPT_HANDLE:
 		case BT_IO_OPT_CLASS:
-		case BT_IO_OPT_PHY:
 		default:
 			g_set_error(err, BT_IO_ERROR, EINVAL,
 					"Unknown option %d", opt);
@@ -1579,7 +1596,7 @@ gboolean bt_io_set(GIOChannel *io, GError **err, BtIOOption opt1, ...)
 	case BT_IO_L2CAP:
 		return l2cap_set(sock, opts.src_type, opts.sec_level, opts.imtu,
 					opts.omtu, opts.mode, opts.master,
-					opts.flushable, opts.priority, err);
+					opts.flushable, opts.priority, opts.phy, err);
 	case BT_IO_RFCOMM:
 		return rfcomm_set(sock, opts.sec_level, opts.master, err);
 	case BT_IO_SCO:
@@ -1629,7 +1646,7 @@ static GIOChannel *create_io(gboolean server, struct set_opts *opts,
 		if (!l2cap_set(sock, opts->src_type, opts->sec_level,
 				opts->imtu, opts->omtu, opts->mode,
 				opts->master, opts->flushable, opts->priority,
-				err))
+				opts->phy, err))
 			goto failed;
 		break;
 	case BT_IO_RFCOMM:
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH BlueZ 4/8] device: Add support for get/set PHY property
       [not found]   ` <CGME20210722055012epcas5p1bb92b3e31233da03906c4f562b22b4fc@epcas5p1.samsung.com>
@ 2021-07-22  5:49     ` Ayush Garg
  0 siblings, 0 replies; 11+ messages in thread
From: Ayush Garg @ 2021-07-22  5:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: anupam.r, nitin.j

This change introduces a new device property
which will enable user to get PHYs of the current
LE Connection.
It will also allow to set preferred PHYs for
a particular LE connection.

Reviewed-by: Anupam Roy <anupam.r@samsung.com>
---
 lib/bluetooth.h |   9 ++
 src/adapter.c   |   8 ++
 src/adapter.h   |   1 +
 src/device.c    | 220 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 238 insertions(+)

diff --git a/lib/bluetooth.h b/lib/bluetooth.h
index 9ab033ec4..a6afaa753 100644
--- a/lib/bluetooth.h
+++ b/lib/bluetooth.h
@@ -127,6 +127,15 @@ struct bt_voice {
 #define BT_PHY_LE_2M_RX		0x00001000
 #define BT_PHY_LE_CODED_TX	0x00002000
 #define BT_PHY_LE_CODED_RX	0x00004000
+#define BT_PHY_LE_CODED_S2	0x00008000
+#define BT_PHY_LE_CODED_S8	0x00010000
+
+#define BT_PHY_LE_MASK (BT_PHY_LE_1M_TX | BT_PHY_LE_1M_RX | \
+				BT_PHY_LE_2M_TX | BT_PHY_LE_2M_RX | \
+				BT_PHY_LE_CODED_TX | BT_PHY_LE_CODED_RX)
+
+#define BT_PHY_LE_CODED_MASK (BT_PHY_LE_CODED_TX | \
+				BT_PHY_LE_CODED_RX)
 
 #define BT_MODE			15
 
diff --git a/src/adapter.c b/src/adapter.c
index 3861ade8a..5de92a570 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -6661,6 +6661,14 @@ const char *adapter_get_path(struct btd_adapter *adapter)
 	return adapter->path;
 }
 
+uint32_t adapter_get_supported_phys(struct btd_adapter *adapter)
+{
+	if (!adapter)
+		return 0;
+
+	return adapter->supported_phys;
+}
+
 const bdaddr_t *btd_adapter_get_address(struct btd_adapter *adapter)
 {
 	return &adapter->bdaddr;
diff --git a/src/adapter.h b/src/adapter.h
index 60b5e3bcc..21046ceaa 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -87,6 +87,7 @@ struct btd_device *btd_adapter_find_device_by_path(struct btd_adapter *adapter,
 						   const char *path);
 
 const char *adapter_get_path(struct btd_adapter *adapter);
+uint32_t adapter_get_supported_phys(struct btd_adapter *adapter);
 const bdaddr_t *btd_adapter_get_address(struct btd_adapter *adapter);
 uint8_t btd_adapter_get_address_type(struct btd_adapter *adapter);
 const char *btd_adapter_get_storage_dir(struct btd_adapter *adapter);
diff --git a/src/device.c b/src/device.c
index b29aa195d..6f74989c7 100644
--- a/src/device.c
+++ b/src/device.c
@@ -272,6 +272,9 @@ struct btd_device {
 
 	GIOChannel	*att_io;
 	guint		store_id;
+
+	uint32_t phys;
+	bool pending_phys;
 };
 
 static const uint16_t uuid_list[] = {
@@ -1470,6 +1473,212 @@ static gboolean dev_property_wake_allowed_exist(
 	return device_get_wake_support(device);
 }
 
+static struct phys_config {
+	uint32_t flag;
+	const char *name;
+} phys_str[] = {
+	{ BT_PHY_LE_1M_TX, "LE1MTX" },
+	{ BT_PHY_LE_1M_RX, "LE1MRX" },
+	{ BT_PHY_LE_2M_TX, "LE2MTX" },
+	{ BT_PHY_LE_2M_RX, "LE2MRX" },
+	{ BT_PHY_LE_CODED_TX, "LECODEDTX" },
+	{ BT_PHY_LE_CODED_RX, "LECODEDRX" },
+	{ BT_PHY_LE_CODED_S2, "LECODEDS2" },
+	{ BT_PHY_LE_CODED_S8, "LECODEDS8" }
+};
+
+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 device_set_phy(struct btd_device *device, uint32_t phys)
+{
+	if (!device)
+		return;
+
+	DBG("Device PHYs %u", phys);
+
+	device->phys = phys;
+
+	g_dbus_emit_property_changed(dbus_conn, device->path,
+					DEVICE_INTERFACE, "Phy");
+
+}
+
+static int set_preferred_phy(struct btd_device *device, uint32_t phys)
+{
+	GIOChannel *io;
+	GError *gerr = NULL;
+	uint32_t supported_phys = 0;
+	int ret;
+
+	if (!device || !phys) {
+		error("Invalid arguments in method call");
+		return -EINVAL;
+	}
+
+	if (!device->le) {
+		error("Operation is not supported");
+		return -ENOTSUP;
+	}
+
+	if (!device->le_state.connected || !device->attrib) {
+		error("Device Not Connected");
+		return -ENOTCONN;
+	}
+
+	io = g_attrib_get_channel(device->attrib);
+
+	if (!io) {
+		error("Device Not Connected");
+		return -ENOTCONN;
+	}
+
+	supported_phys = adapter_get_supported_phys(device->adapter) &
+					BT_PHY_LE_MASK;
+
+	if (supported_phys & BT_PHY_LE_CODED_MASK) {
+		supported_phys |= BT_PHY_LE_CODED_S2;
+		supported_phys |= BT_PHY_LE_CODED_S8;
+	}
+
+	if (phys & ~supported_phys) {
+		error("Supplied phy(s) are not supported");
+		return -EINVAL;
+	}
+
+	if (device->pending_phys) {
+		error("Operation already in progress");
+		return -EINPROGRESS;
+	}
+
+	device->pending_phys = true;
+
+	if (device->phys == phys) {
+		device->pending_phys = false;
+		return 0;
+	}
+
+	bt_io_set(io, &gerr, BT_IO_OPT_PHY, phys, BT_IO_OPT_INVALID);
+
+	if (gerr) {
+		error("bt_io_set: %s", gerr->message);
+		device->pending_phys = false;
+		ret = gerr->code;
+		g_error_free(gerr);
+		return ret;
+	}
+
+	return 0;
+}
+
+static gboolean dev_property_get_phy(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *data)
+{
+	struct btd_device *device = data;
+	DBusMessageIter array;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "s", &array);
+
+	append_phys_str(&array, device->phys);
+
+	dbus_message_iter_close_container(iter, &array);
+
+	return TRUE;
+}
+
+static void dev_property_set_phy(const GDBusPropertyTable *property,
+					DBusMessageIter *value,
+					GDBusPendingPropertySet id, void *data)
+{
+	struct btd_device *device = data;
+	DBusMessageIter array;
+	uint32_t phys;
+	int ret;
+
+	if (dbus_message_iter_get_arg_type(value) != DBUS_TYPE_ARRAY) {
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	dbus_message_iter_recurse(value, &array);
+
+	if (!parse_phys_str(&array, &phys)) {
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	ret = set_preferred_phy(device, phys);
+
+	if (ret >= 0) {
+		g_dbus_pending_property_success(id);
+		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 ENOTCONN:
+		g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".NotConnected",
+					"Device Not Connected");
+		break;
+	case EINPROGRESS:
+		g_dbus_pending_property_error(id,
+					ERROR_INTERFACE ".InProgress",
+					"Operation already in progress");
+		break;
+	default:
+		g_dbus_pending_property_error(id, ERROR_INTERFACE ".Failed",
+							strerror(-ret));
+		break;
+	}
+
+}
+
 static bool disconnect_all(gpointer user_data)
 {
 	struct btd_device *device = user_data;
@@ -2950,6 +3159,7 @@ static const GDBusPropertyTable device_properties[] = {
 	{ "WakeAllowed", "b", dev_property_get_wake_allowed,
 				dev_property_set_wake_allowed,
 				dev_property_wake_allowed_exist },
+	{ "Phy", "as", dev_property_get_phy, dev_property_set_phy },
 	{ }
 };
 
@@ -3017,6 +3227,12 @@ void device_remove_connection(struct btd_device *device, uint8_t bdaddr_type)
 	state->connected = false;
 	device->general_connect = FALSE;
 
+	/* Reset PHYs if LE connection is disconnected */
+	if (bdaddr_type != BDADDR_BREDR) {
+		device->pending_phys = false;
+		device_set_phy(device, 0);
+	}
+
 	device_set_svc_refreshed(device, false);
 
 	if (device->disconn_timer > 0) {
@@ -5305,10 +5521,12 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io)
 	struct btd_gatt_database *database;
 	const bdaddr_t *dst;
 	char dstaddr[18];
+	uint32_t phys;
 
 	bt_io_get(io, &gerr, BT_IO_OPT_SEC_LEVEL, &sec_level,
 						BT_IO_OPT_IMTU, &mtu,
 						BT_IO_OPT_CID, &cid,
+						BT_IO_OPT_PHY, &phys,
 						BT_IO_OPT_INVALID);
 
 	if (gerr) {
@@ -5358,6 +5576,8 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io)
 	dev->attrib = attrib;
 	dev->att = g_attrib_get_att(attrib);
 
+	device_set_phy(dev, phys);
+
 	bt_att_ref(dev->att);
 
 	bt_att_set_debug(dev->att, BT_ATT_DEBUG, gatt_debug, NULL, NULL);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH BlueZ 5/8] adapter: Add support for LE PHY Update Complete event
       [not found]   ` <CGME20210722055013epcas5p350d88f402bbe4c55f1f868dbb2decbaf@epcas5p3.samsung.com>
@ 2021-07-22  5:49     ` Ayush Garg
  0 siblings, 0 replies; 11+ messages in thread
From: Ayush Garg @ 2021-07-22  5:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: anupam.r, nitin.j

This change will subscribe the MGMT LE PHY Update
Complete event.
This event will come whenever the particular PHYs changed
either autonomously or as a response of set PHY property.
Upon receiving the event, it will notify the user by emitting
"Phy" property changed event.

Reviewed-by: Anupam Roy <anupam.r@samsung.com>
---
 lib/mgmt.h    |  8 ++++++++
 src/adapter.c | 40 ++++++++++++++++++++++++++++++++++++++++
 src/device.c  |  7 +++++++
 src/device.h  |  2 ++
 4 files changed, 57 insertions(+)

diff --git a/lib/mgmt.h b/lib/mgmt.h
index 0a6349321..4d2acb778 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -1014,6 +1014,13 @@ struct mgmt_ev_controller_resume {
 	uint8_t wake_reason;
 } __packed;
 
+#define MGMT_EV_LE_PHY_UPDATE_COMPLETE	0x002f
+struct mgmt_ev_le_phy_update_complete {
+	struct mgmt_addr_info addr;
+	uint8_t status;
+	uint32_t phys;
+} __packed;
+
 static const char *mgmt_op[] = {
 	"<0x0000>",
 	"Read Version",
@@ -1152,6 +1159,7 @@ static const char *mgmt_ev[] = {
 	"Advertisement Monitor Removed",
 	"Controller Suspend",
 	"Controller Resume",
+	"LE PHY Update Complete",				/* 0x002f */
 };
 
 static const char *mgmt_status[] = {
diff --git a/src/adapter.c b/src/adapter.c
index 5de92a570..f616879fd 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -9740,6 +9740,41 @@ static void phy_configuration_changed_callback(uint16_t index,
 					ADAPTER_INTERFACE, "PhyConfiguration");
 }
 
+static void le_phy_update_complete_callback(uint16_t index,
+					uint16_t length, const void *param,
+					void *user_data)
+{
+	const struct mgmt_ev_le_phy_update_complete *ev = param;
+	struct btd_adapter *adapter = user_data;
+	struct btd_device *device;
+	char addr[18];
+
+	if (length < sizeof(*ev)) {
+		btd_error(adapter->dev_id, "Too small le phy update complete event");
+		return;
+	}
+
+	if (ev->status != MGMT_STATUS_SUCCESS) {
+		btd_error(adapter->dev_id, "Failed to set le phy: %s (0x%02x)",
+						mgmt_errstr(ev->status), ev->status);
+		return;
+	}
+
+	ba2str(&ev->addr.bdaddr, addr);
+
+	DBG("hci%u device %s PHYs updated %u", index, addr, ev->phys);
+
+	device = btd_adapter_get_device(adapter, &ev->addr.bdaddr,
+								ev->addr.type);
+	if (!device) {
+		btd_error(adapter->dev_id,
+				"Unable to get device object for %s", addr);
+		return;
+	}
+
+	device_le_phy_updated(device, ev->phys);
+}
+
 static void read_info_complete(uint8_t status, uint16_t length,
 					const void *param, void *user_data)
 {
@@ -9980,6 +10015,11 @@ static void read_info_complete(uint8_t status, uint16_t length,
 						phy_configuration_changed_callback,
 						adapter, NULL);
 
+	mgmt_register(adapter->mgmt, MGMT_EV_LE_PHY_UPDATE_COMPLETE,
+						adapter->dev_id,
+						le_phy_update_complete_callback,
+						adapter, NULL);
+
 	set_dev_class(adapter);
 
 	set_name(adapter, btd_adapter_get_name(adapter));
diff --git a/src/device.c b/src/device.c
index 6f74989c7..4b11772b8 100644
--- a/src/device.c
+++ b/src/device.c
@@ -5684,6 +5684,13 @@ done:
 	}
 }
 
+void device_le_phy_updated(struct btd_device *dev, uint32_t phy)
+{
+	dev->pending_phys = false;
+
+	device_set_phy(dev, phy);
+}
+
 int device_connect_le(struct btd_device *dev)
 {
 	struct btd_adapter *adapter = dev->adapter;
diff --git a/src/device.h b/src/device.h
index 4ae9abe0d..b3b32b231 100644
--- a/src/device.h
+++ b/src/device.h
@@ -154,6 +154,8 @@ int device_unblock(struct btd_device *device, gboolean silent,
 void btd_device_set_pnpid(struct btd_device *device, uint16_t source,
 			uint16_t vendor, uint16_t product, uint16_t version);
 
+void device_le_phy_updated(struct btd_device *dev, uint32_t phy);
+
 int device_connect_le(struct btd_device *dev);
 
 typedef void (*device_svc_cb_t) (struct btd_device *dev, int err,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH BlueZ 6/8] client: Add support for LE get/set device PHY in bluetoothctl
       [not found]   ` <CGME20210722055015epcas5p4db389aa15f16f1577a74ba5ce446919b@epcas5p4.samsung.com>
@ 2021-07-22  5:49     ` Ayush Garg
  0 siblings, 0 replies; 11+ messages in thread
From: Ayush Garg @ 2021-07-22  5:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: anupam.r, nitin.j

Verification logs based on BT 5.0 controller
==============================================
[S20] phy  45:18:F8:CF:23:7E
	Selected phys: LE1MTX
	Selected phys: LE1MRX
[S20] phy  45:18:F8:CF:23:7E LE2MTX LE2MRX
[S20]
Changing PHY succeeded
Device 45:18:F8:CF:23:7E Phy: LE2MTX
Device 45:18:F8:CF:23:7E Phy: LE2MRX

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

diff --git a/client/main.c b/client/main.c
index ab925769b..e7146ab6f 100644
--- a/client/main.c
+++ b/client/main.c
@@ -1705,6 +1705,7 @@ static void cmd_info(int argc, char *argv[])
 	print_property(proxy, "TxPower");
 	print_property(proxy, "AdvertisingFlags");
 	print_property(proxy, "AdvertisingData");
+	print_property(proxy, "Phy");
 
 	battery_proxy = find_battery_by_path(battery_proxies,
 					g_dbus_proxy_get_path(proxy));
@@ -2071,6 +2072,47 @@ static void cmd_phy_configuration(int argc, char *argv[])
 	g_strfreev(phys);
 }
 
+static void get_phy(GDBusProxy *proxy)
+{
+	print_property_with_label(proxy, "Phy",
+				"Selected phys");
+}
+
+static void cmd_phy(int argc, char *argv[])
+{
+	GDBusProxy *proxy;
+	char **phys = NULL;
+	size_t phys_len = 0;
+
+	if (check_default_ctrl() == FALSE)
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+
+	if (argc < 2 || !strlen(argv[1])) {
+		bt_shell_printf("Device address not given as input\n");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	proxy = find_proxy_by_address(default_ctrl->devices, argv[1]);
+	if (!proxy) {
+		bt_shell_printf("Device %s not available\n", argv[1]);
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
+	}
+
+	if (argc == 2)
+		return get_phy(proxy);
+
+	phys = g_strdupv(&argv[2]);
+	phys_len = g_strv_length(phys);
+
+	g_dbus_proxy_set_property_array(proxy,
+					"Phy", DBUS_TYPE_STRING, phys,
+					phys_len, generic_callback, "PHY",
+					NULL);
+
+	g_strfreev(phys);
+}
+
+
 static void cmd_list_attributes(int argc, char *argv[])
 {
 	GDBusProxy *proxy;
@@ -3072,6 +3114,9 @@ static const struct bt_shell_menu main_menu = {
 				"[EDR2M1SLOT] [EDR2M3SLOT] [EDR2M5SLOT] "
 				"[EDR3M1SLOT] [EDR3M3SLOT] [EDR3M5SLOT]",
 		cmd_phy_configuration,		"Get/Set PHY Configuration" },
+	{ "phy",		"<dev> [LE1MTX] [LE1MRX] [LE2MTX] [LE2MRX] "
+				"[LECODEDTX] [LECODEDRX] [LECODEDS2] [LECODEDS8]",
+		cmd_phy,	"Get/Set LE PHY preferences for a connected device" },
 	{ } },
 };
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH BlueZ 7/8] device: Save device PHY in storage and read it at init
       [not found]   ` <CGME20210722055016epcas5p267b70f0da3b5c1991d29ca47d685ab6d@epcas5p2.samsung.com>
@ 2021-07-22  5:49     ` Ayush Garg
  0 siblings, 0 replies; 11+ messages in thread
From: Ayush Garg @ 2021-07-22  5:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: anupam.r, nitin.j

This change will save the current LE connection PHY in
the storage when LE PHY Updated Event is received.
It will also load and set the last stored LE PHY when
that device is re-connected.

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

diff --git a/src/device.c b/src/device.c
index 4b11772b8..b708fc822 100644
--- a/src/device.c
+++ b/src/device.c
@@ -275,6 +275,7 @@ struct btd_device {
 
 	uint32_t phys;
 	bool pending_phys;
+	uint32_t stored_phys;
 };
 
 static const uint16_t uuid_list[] = {
@@ -448,6 +449,12 @@ static gboolean store_device_info_cb(gpointer user_data)
 		g_key_file_remove_key(key_file, "General", "Services", NULL);
 	}
 
+	if (device->stored_phys)
+		g_key_file_set_integer(key_file, "General", "Phy",
+					device->stored_phys);
+	else
+		g_key_file_remove_key(key_file, "General", "Phy", NULL);
+
 	if (device->vendor_src) {
 		g_key_file_set_integer(key_file, "DeviceID", "Source",
 					device->vendor_src);
@@ -3576,6 +3583,14 @@ next:
 		gerr = NULL;
 	}
 
+	/* Get PHY */
+	device->stored_phys = g_key_file_get_integer(key_file,
+					"General", "Phy", &gerr);
+	if (gerr) {
+		g_error_free(gerr);
+		gerr = NULL;
+	}
+
 	if (store_needed)
 		store_device_info(device);
 }
@@ -5578,6 +5593,9 @@ bool device_attach_att(struct btd_device *dev, GIOChannel *io)
 
 	device_set_phy(dev, phys);
 
+	if (dev->stored_phys)
+		set_preferred_phy(dev, dev->stored_phys);
+
 	bt_att_ref(dev->att);
 
 	bt_att_set_debug(dev->att, BT_ATT_DEBUG, gatt_debug, NULL, NULL);
@@ -5688,6 +5706,9 @@ void device_le_phy_updated(struct btd_device *dev, uint32_t phy)
 {
 	dev->pending_phys = false;
 
+	dev->stored_phys = phy;
+	store_device_info(dev);
+
 	device_set_phy(dev, phy);
 }
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH BlueZ 8/8] monitor: Add support for LE PHY Update event
       [not found]   ` <CGME20210722055017epcas5p4da91b311c34a5fb869148b369338ed07@epcas5p4.samsung.com>
@ 2021-07-22  5:49     ` Ayush Garg
  0 siblings, 0 replies; 11+ messages in thread
From: Ayush Garg @ 2021-07-22  5:49 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: anupam.r, nitin.j

Verification logs:
=========================================
> HCI Event: LE Meta Event (0x3e) plen 6
	  LE PHY Update Complete (0x0c)
		Status: Success (0x00)
		Handle: 0
		TX PHY: LE 2M (0x02)
		RX PHY: LE 2M (0x02)
@ MGMT Event: LE PHY Update Complete (0x002f) plen 12
		LE Address: 45:18:F8:CF:23:7E (Resolvable)
		Status: Success (0x00)
		Updated PHYs: 0x1800
		  LE 2M TX
		  LE 2M RX

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

diff --git a/monitor/packet.c b/monitor/packet.c
index 52d22ab21..eaa3070de 100644
--- a/monitor/packet.c
+++ b/monitor/packet.c
@@ -14304,6 +14304,18 @@ static void mgmt_controller_resume_evt(const void *data, uint16_t size)
 	mgmt_print_address(data, addr_type);
 }
 
+static void mgmt_le_phy_update_complete_evt(const void *data,
+						uint16_t size)
+{
+	uint8_t address_type = get_u8(data + 6);
+	uint8_t status = get_u8(data + 7);
+	uint32_t selected_phys = get_le32(data + 8);
+
+	mgmt_print_address(data, address_type);
+	mgmt_print_status(status);
+	mgmt_print_phys("Updated PHYs", selected_phys);
+}
+
 static const struct mgmt_data mgmt_event_table[] = {
 	{ 0x0001, "Command Complete",
 			mgmt_command_complete_evt, 3, false },
@@ -14393,6 +14405,8 @@ static const struct mgmt_data mgmt_event_table[] = {
 			mgmt_controller_suspend_evt, 1, true },
 	{ 0x002e, "Controller Resumed",
 			mgmt_controller_resume_evt, 8, true },
+	{ 0x002f, "LE PHY Update Complete",
+			mgmt_le_phy_update_complete_evt, 12, true },
 	{ }
 };
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH BlueZ 2/8] doc/mgmt-api: Add support for LE PHY Update Complete event
  2021-07-22  5:49     ` [PATCH BlueZ 2/8] doc/mgmt-api: Add support for LE PHY Update Complete event Ayush Garg
@ 2021-07-22 14:45       ` Marcel Holtmann
  0 siblings, 0 replies; 11+ messages in thread
From: Marcel Holtmann @ 2021-07-22 14:45 UTC (permalink / raw)
  To: Ayush Garg; +Cc: linux-bluetooth, anupam.r, nitin.j

Hi Ayush,

> Reviewed-by: Anupam Roy <anupam.r@samsung.com>
> ---
> doc/mgmt-api.txt | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
> 
> diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
> index 5355fedb0..f7379fcd9 100644
> --- a/doc/mgmt-api.txt
> +++ b/doc/mgmt-api.txt
> @@ -4910,3 +4910,32 @@ Controller Resume Event
> 	Address_Type. Otherwise, Address and Address_Type will both be zero.
> 
> 	This event will be sent to all management sockets.
> +
> +
> +LE PHY Update Complete Event
> +===============================
> +
> +	Event Code:		0x002f
> +	Controller Index:	<controller id>
> +	Event Parameters:	Address (6 Octets)
> +				Address_Type (1 Octet)
> +				Status (1 Octet)
> +				PHYs (4 Octets)
> +
> +	This event indicates that LE PHYs have been changed for this
> +	connected device.
> +
> +	The PHYs parameters are a bitmask with currently the
> +	following available bits:
> +
> +		9	LE 1M TX
> +		10	LE 1M RX
> +		11	LE 2M TX
> +		12	LE 2M RX
> +		13	LE Coded TX
> +		14	LE Coded RX
> +
> +	This event will be used in case of autonomous PHY update made
> +	by the controller or HCI_LE_SET_PHY command succeeded.
> +
> +	This event will be sent to all management sockets.

As mentioned in the code review, I don’t like doing it this way.

Regards

Marcel


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH BlueZ 1/8] doc/device-api: Add Phy property
  2021-07-22  5:49     ` [PATCH BlueZ 1/8] doc/device-api: Add Phy property Ayush Garg
@ 2021-07-22 17:33       ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 11+ messages in thread
From: Luiz Augusto von Dentz @ 2021-07-22 17:33 UTC (permalink / raw)
  To: Ayush Garg; +Cc: linux-bluetooth, Anupam Roy, nitin.j

Hi Ayush,

On Wed, Jul 21, 2021 at 11:03 PM Ayush Garg <ayush.garg@samsung.com> wrote:
>
> This will allow to set the LE PHY preferences for
> a connected device.
>
> Reviewed-by: Anupam Roy <anupam.r@samsung.com>
> ---
>  doc/device-api.txt | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
>
> diff --git a/doc/device-api.txt b/doc/device-api.txt
> index 4e824d2de..d0e108f74 100644
> --- a/doc/device-api.txt
> +++ b/doc/device-api.txt
> @@ -272,3 +272,25 @@ Properties string Address [readonly]
>                         Example:
>                                 <Transport Discovery> <Organization Flags...>
>                                 0x26                   0x01         0x01...
> +
> +               array{string} Phy [readwrite, optional]
> +
> +                       PHY Preferences for a connected device.
> +
> +                       Note: The controller might not be able to make the
> +                       change because of reasons like peer not supporting
> +                       the requested PHY or it couldnot schedule due to
> +                       other activites.
> +
> +                       This is only available for LE capable controllers.
> +                       It will return Not Supported Otherwise.

The property shall be omitted if LE is not enabled, I guess that was
the intent of optional but saying it would return NotSupport means
otherwise.

> +
> +                       Possible values:
> +                               "LE1MTX"
> +                               "LE1MRX"
> +                               "LE2MTX"
> +                               "LE2MRX"
> +                               "LECODEDTX"
> +                               "LECODEDRX"
> +                               "LECODEDS2"
> +                               "LECODEDS8"
> --
> 2.17.1

I guess the intend here would be to have a prefered PHY for LE, but I
wonder if this would really help since different profiles/service may
have different preferences, also by being an array I assume one would
need to the enter in the preferred order which should probably be
stated and again depending on the use case this could be a config
setting in main.conf instead so it is applied globally to all devices
by drivers can overwrite it with their own preferences.

-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2021-07-22 17:33 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20210722055008epcas5p28da6985b690d3bbc564a5957c1b209f4@epcas5p2.samsung.com>
2021-07-22  5:49 ` [PATCH BlueZ 0/8] Support for connection specific LE PHY configuration Ayush Garg
     [not found]   ` <CGME20210722055009epcas5p25e4997aa7e53cb2a6e3780fdb7301785@epcas5p2.samsung.com>
2021-07-22  5:49     ` [PATCH BlueZ 1/8] doc/device-api: Add Phy property Ayush Garg
2021-07-22 17:33       ` Luiz Augusto von Dentz
     [not found]   ` <CGME20210722055010epcas5p45a16ff704c37d108a9df0d6c0a1942a8@epcas5p4.samsung.com>
2021-07-22  5:49     ` [PATCH BlueZ 2/8] doc/mgmt-api: Add support for LE PHY Update Complete event Ayush Garg
2021-07-22 14:45       ` Marcel Holtmann
     [not found]   ` <CGME20210722055011epcas5p15299bfe8f8b8dd58e1354364071608e3@epcas5p1.samsung.com>
2021-07-22  5:49     ` [PATCH BlueZ 3/8] btio: Add BT_IO_PHY option to set le phy options Ayush Garg
     [not found]   ` <CGME20210722055012epcas5p1bb92b3e31233da03906c4f562b22b4fc@epcas5p1.samsung.com>
2021-07-22  5:49     ` [PATCH BlueZ 4/8] device: Add support for get/set PHY property Ayush Garg
     [not found]   ` <CGME20210722055013epcas5p350d88f402bbe4c55f1f868dbb2decbaf@epcas5p3.samsung.com>
2021-07-22  5:49     ` [PATCH BlueZ 5/8] adapter: Add support for LE PHY Update Complete event Ayush Garg
     [not found]   ` <CGME20210722055015epcas5p4db389aa15f16f1577a74ba5ce446919b@epcas5p4.samsung.com>
2021-07-22  5:49     ` [PATCH BlueZ 6/8] client: Add support for LE get/set device PHY in bluetoothctl Ayush Garg
     [not found]   ` <CGME20210722055016epcas5p267b70f0da3b5c1991d29ca47d685ab6d@epcas5p2.samsung.com>
2021-07-22  5:49     ` [PATCH BlueZ 7/8] device: Save device PHY in storage and read it at init Ayush Garg
     [not found]   ` <CGME20210722055017epcas5p4da91b311c34a5fb869148b369338ed07@epcas5p4.samsung.com>
2021-07-22  5:49     ` [PATCH BlueZ 8/8] monitor: Add support for LE PHY Update event Ayush Garg

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).