diff mbox series

[BlueZ,3/8] btio: Add BT_IO_PHY option to set le phy options

Message ID 20210722054951.8291-4-ayush.garg@samsung.com (mailing list archive)
State New, archived
Headers show
Series Support for connection specific LE PHY configuration | expand

Commit Message

Ayush Garg July 22, 2021, 5:49 a.m. UTC
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 mbox series

Patch

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: