diff mbox series

[BlueZ] client/player: Add codec as parameter to endpoint.presets

Message ID 20230512203507.4146233-1-luiz.dentz@gmail.com
State New
Headers show
Series [BlueZ] client/player: Add codec as parameter to endpoint.presets | expand

Commit Message

Luiz Augusto von Dentz May 12, 2023, 8:35 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

This changes endpoint.presets command to take codec as parameter.
---
 client/player.c | 240 +++++++++++++++++++++++++++++++++++-------------
 1 file changed, 175 insertions(+), 65 deletions(-)

Comments

bluez.test.bot@gmail.com May 12, 2023, 10:06 p.m. UTC | #1
This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=747185

---Test result---

Test Summary:
CheckPatch                    PASS      0.69 seconds
GitLint                       PASS      0.34 seconds
BuildEll                      PASS      26.35 seconds
BluezMake                     PASS      756.71 seconds
MakeCheck                     PASS      11.61 seconds
MakeDistcheck                 PASS      152.87 seconds
CheckValgrind                 PASS      245.82 seconds
CheckSmatch                   PASS      329.72 seconds
bluezmakeextell               PASS      99.86 seconds
IncrementalBuild              PASS      637.77 seconds
ScanBuild                     PASS      990.47 seconds



---
Regards,
Linux Bluetooth
diff mbox series

Patch

diff --git a/client/player.c b/client/player.c
index 58e14654ffb0..a9f56fb94b9b 100644
--- a/client/player.c
+++ b/client/player.c
@@ -78,6 +78,7 @@  struct endpoint {
 	uint8_t cis;
 	char *transport;
 	DBusMessage *msg;
+	struct preset *preset;
 };
 
 static DBusConnection *dbus_conn;
@@ -1166,7 +1167,7 @@  struct codec_qos {
 };
 
 struct codec_preset {
-	const char *name;
+	char *name;
 	const struct iovec data;
 	const struct codec_qos qos;
 	uint8_t target_latency;
@@ -1410,9 +1411,10 @@  static struct codec_preset lc3_presets[] = {
 			LC3_10_UNFRAMED(155u, 13u, 100u, 40000u)),
 };
 
-#define PRESET(_uuid, _presets, _default_index) \
+#define PRESET(_uuid, _codec, _presets, _default_index) \
 	{ \
 		.uuid = _uuid, \
+		.codec = _codec, \
 		.custom = { .name = "custom" }, \
 		.default_preset = &_presets[_default_index], \
 		.presets = _presets, \
@@ -1421,46 +1423,142 @@  static struct codec_preset lc3_presets[] = {
 
 static struct preset {
 	const char *uuid;
+	uint8_t codec;
+	uint16_t cid;
+	uint16_t vid;
 	struct codec_preset custom;
 	struct codec_preset *default_preset;
 	struct codec_preset *presets;
 	size_t num_presets;
 } presets[] = {
-	PRESET(A2DP_SOURCE_UUID, sbc_presets, 6),
-	PRESET(A2DP_SINK_UUID, sbc_presets, 6),
-	PRESET(PAC_SINK_UUID, lc3_presets, 3),
-	PRESET(PAC_SOURCE_UUID, lc3_presets, 3),
+	PRESET(A2DP_SOURCE_UUID, A2DP_CODEC_SBC, sbc_presets, 6),
+	PRESET(A2DP_SINK_UUID, A2DP_CODEC_SBC, sbc_presets, 6),
+	PRESET(PAC_SINK_UUID, LC3_ID, lc3_presets, 3),
+	PRESET(PAC_SOURCE_UUID, LC3_ID, lc3_presets, 3),
 };
 
-static struct codec_preset *find_preset(const char *uuid, const char *name)
+static void parse_vendor_codec(const char *codec, uint16_t *vid, uint16_t *cid)
+{
+	char **list;
+	char *endptr = NULL;
+
+	if (!codec)
+		return;
+
+	list = g_strsplit(codec, ":", 2);
+
+	if (vid)
+		*vid = strtol(list[0], &endptr, 0);
+
+	if (cid)
+		*cid = strtol(list[1], &endptr, 0);
+
+	g_strfreev(list);
+}
+
+static struct preset *find_presets(const char *uuid, uint8_t codec,
+					uint16_t vid, uint16_t cid)
 {
 	size_t i;
 
+	if (codec == 0xff) {
+		GList *l;
+
+		for (l = local_endpoints; l; l = g_list_next(l)) {
+			struct endpoint *ep = l->data;
+
+			if (strcasecmp(ep->uuid, uuid) || ep->codec != codec)
+				continue;
+
+			if (ep->codec == 0xff && (ep->vid != vid ||
+							ep->cid != cid))
+				continue;
+
+			return ep->preset;
+		}
+
+		return NULL;
+	}
+
 	for (i = 0; i < ARRAY_SIZE(presets); i++) {
 		struct preset *preset = &presets[i];
 
-		if (!strcasecmp(preset->uuid, uuid)) {
-			size_t j;
+		if (preset->codec != codec)
+			continue;
 
-			if (!name)
-				return preset->default_preset;
-			else if (!strcmp(name, "custom"))
-				return &preset->custom;
-
-			for (j = 0; j < preset->num_presets; j++) {
-				struct codec_preset *p;
-
-				p = &preset->presets[j];
-
-				if (!strcmp(p->name, name))
-					return p;
-			}
-		}
+		if (!strcasecmp(preset->uuid, uuid))
+			return preset;
 	}
 
 	return NULL;
 }
 
+static struct preset *find_vendor_presets(const char *uuid, const char *codec)
+{
+	uint16_t cid;
+	uint16_t vid;
+
+	if (!uuid || !codec)
+		return NULL;
+
+	parse_vendor_codec(codec, &vid, &cid);
+
+	return find_presets(uuid, 0xff, vid, cid);
+}
+
+static struct preset *find_presets_name(const char *uuid, const char *codec)
+{
+	uint8_t id;
+	char *endptr = NULL;
+
+	if (!uuid || !codec)
+		return NULL;
+
+	if (strrchr(codec, ':'))
+		return find_vendor_presets(uuid, codec);
+
+	id = strtol(codec, &endptr, 0);
+
+	return find_presets(uuid, id, 0x0000, 0x0000);
+}
+
+static struct codec_preset *preset_find_name(struct preset *preset,
+						const char *name)
+{
+	size_t i;
+
+	if (!preset)
+		return NULL;
+
+	if (!name)
+		return preset->default_preset;
+	else if (!strcmp(name, "custom"))
+		return &preset->custom;
+
+	for (i = 0; i < preset->num_presets; i++) {
+		struct codec_preset *p;
+
+		p = &preset->presets[i];
+
+		if (!strcmp(p->name, name))
+			return p;
+	}
+
+	return NULL;
+}
+
+static struct codec_preset *find_preset(const char *uuid, const char *codec,
+					const char *name)
+{
+	struct preset *preset;
+
+	preset = find_presets_name(uuid, codec);
+	if (!preset)
+		return NULL;
+
+	return preset_find_name(preset, name);
+}
+
 static DBusMessage *endpoint_select_config_reply(DBusMessage *msg,
 						 uint8_t *data, size_t len)
 {
@@ -1525,7 +1623,7 @@  static void select_config_response(const char *input, void *user_data)
 	uint8_t *data;
 	size_t len;
 
-	p = find_preset(ep->uuid, input);
+	p = preset_find_name(ep->preset, input);
 	if (p) {
 		data = p->data.iov_base;
 		len = p->data.iov_len;
@@ -1580,7 +1678,7 @@  static DBusMessage *endpoint_select_configuration(DBusConnection *conn,
 		return NULL;
 	}
 
-	p = find_preset(ep->uuid, NULL);
+	p = preset_find_name(ep->preset, NULL);
 	if (!p) {
 		reply = g_dbus_create_error(msg, "org.bluez.Error.Rejected",
 								NULL);
@@ -1755,7 +1853,7 @@  static void select_properties_response(const char *input, void *user_data)
 	struct codec_preset *p;
 	DBusMessage *reply;
 
-	p = find_preset(ep->uuid, input);
+	p = preset_find_name(ep->preset, input);
 	if (p) {
 		reply = endpoint_select_properties_reply(ep, ep->msg, p);
 		goto done;
@@ -1797,9 +1895,9 @@  static DBusMessage *endpoint_select_properties(DBusConnection *conn,
 		return NULL;
 	}
 
-	p = find_preset(ep->uuid, NULL);
+	p = preset_find_name(ep->preset, NULL);
 	if (!p)
-		NULL;
+		return NULL;
 
 	reply = endpoint_select_properties_reply(ep, msg, p);
 	if (!reply)
@@ -1903,6 +2001,11 @@  static void endpoint_free(void *data)
 	if (ep->msg)
 		dbus_message_unref(ep->msg);
 
+	if (ep->codec == 0xff) {
+		free(ep->preset->custom.name);
+		free(ep->preset);
+	}
+
 	g_free(ep->path);
 	g_free(ep->uuid);
 	g_free(ep);
@@ -2312,7 +2415,6 @@  static void cmd_register_endpoint(int argc, char *argv[])
 {
 	struct endpoint *ep;
 	char *endptr = NULL;
-	char **list;
 
 	ep = g_new0(struct endpoint, 1);
 	ep->uuid = g_strdup(argv[1]);
@@ -2324,12 +2426,13 @@  static void cmd_register_endpoint(int argc, char *argv[])
 	local_endpoints = g_list_append(local_endpoints, ep);
 
 	if (strrchr(argv[2], ':')) {
-		list = g_strsplit(argv[2], ":", 2);
-
 		ep->codec = 0xff;
-		ep->vid = strtol(list[0], &endptr, 0);
-		endptr = NULL;
-		ep->cid = strtol(list[1], &endptr, 0);
+		parse_vendor_codec(argv[2], &ep->cid, &ep->vid);
+		ep->preset = new0(struct preset, 1);
+		ep->preset->custom.name = strdup("custom");
+		ep->preset->default_preset = &ep->preset->custom;
+	} else {
+		ep->preset = find_presets_name(ep->uuid, argv[2]);
 	}
 
 	if (argc > 3)
@@ -2489,7 +2592,7 @@  static void cmd_config_endpoint(int argc, char *argv[])
 	}
 
 	if (argc > 3) {
-		preset = find_preset(cfg->ep->uuid, argv[3]);
+		preset = preset_find_name(cfg->ep->preset, argv[3]);
 		if (!preset) {
 			bt_shell_printf("Preset %s not found\n", argv[3]);
 			goto fail;
@@ -2835,46 +2938,50 @@  static void custom_frequency(const char *input, void *user_data)
 				custom_duration, user_data);
 }
 
-static void cmd_presets_endpoint(int argc, char *argv[])
+static void print_presets(struct preset *preset)
 {
 	size_t i;
+	struct codec_preset *p;
+
+	p = &preset->custom;
+
+	bt_shell_printf("%s%s\n", p == preset->default_preset ? "*" : "",
+								p->name);
+
+	for (i = 0; i < preset->num_presets; i++) {
+		p = &preset->presets[i];
+		bt_shell_printf("%s%s\n", p == preset->default_preset ?
+						"*" : "", p->name);
+	}
+}
+
+static void cmd_presets_endpoint(int argc, char *argv[])
+{
+	struct preset *preset;
 	struct codec_preset *default_preset = NULL;
 
-	if (argc > 2) {
-		default_preset = find_preset(argv[1], argv[2]);
+	if (argc > 3) {
+		default_preset = find_preset(argv[1], argv[2], argv[3]);
 		if (!default_preset) {
-			bt_shell_printf("Preset %s not found\n", argv[2]);
+			bt_shell_printf("Preset %s not found\n", argv[3]);
 			return bt_shell_noninteractive_quit(EXIT_FAILURE);
 		}
 	}
 
-	for (i = 0; i < ARRAY_SIZE(presets); i++) {
-		struct preset *preset = &presets[i];
-
-		if (!strcasecmp(preset->uuid, argv[1])) {
-			size_t j;
-			struct codec_preset *p;
-
-			if (default_preset) {
-				preset->default_preset = default_preset;
-				break;
-			}
-
-			p = &preset->custom;
-
-			bt_shell_printf("%s%s\n", p == preset->default_preset ?
-						"*" : "", p->name);
-
-			for (j = 0; j < preset->num_presets; j++) {
-				p = &preset->presets[j];
-
-				bt_shell_printf("%s%s\n",
-						p == preset->default_preset ?
-						"*" : "", p->name);
-			}
-		}
+	preset = find_presets_name(argv[1], argv[2]);
+	if (!preset) {
+		bt_shell_printf("No preset found\n");
+		return bt_shell_noninteractive_quit(EXIT_FAILURE);
 	}
 
+	if (default_preset) {
+		preset->default_preset = default_preset;
+		goto done;
+	}
+
+	print_presets(preset);
+
+done:
 	if (default_preset && !strcmp(default_preset->name, "custom")) {
 		bt_shell_prompt_input("Codec", "Enter frequency (Khz):",
 					custom_frequency, default_preset);
@@ -2904,7 +3011,8 @@  static const struct bt_shell_menu endpoint_menu = {
 						cmd_config_endpoint,
 						"Configure Endpoint",
 						endpoint_generator },
-	{ "presets",      "<UUID> [default]", cmd_presets_endpoint,
+	{ "presets",      "<UUID> <codec[:company]> [default]",
+						cmd_presets_endpoint,
 						"List available presets",
 						uuid_generator },
 	{} },
@@ -2938,6 +3046,8 @@  static void register_endpoints(GDBusProxy *proxy)
 			continue;
 
 		ep = endpoint_new(cap);
+		ep->preset = find_presets(ep->uuid, ep->codec, ep->vid,
+								ep->cid);
 		ep->max_transports = UINT8_MAX;
 		ep->auto_accept = true;
 		ep->cig = BT_ISO_QOS_CIG_UNSET;