Bluetooth: BAP: Move endpoint discovery to new callback

Add a new endpoint callback that is used to report the found
ASEs during BAP discovery, rather than calling
the discovery callback with optional values.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h
index f034c94..8ae5ecc 100644
--- a/include/zephyr/bluetooth/audio/bap.h
+++ b/include/zephyr/bluetooth/audio/bap.h
@@ -1227,6 +1227,19 @@
 			   const struct bt_codec *codec);
 
 	/**
+	 * @brief Remote Audio Stream Endoint (ASE) discovered
+	 *
+	 * Called when an ASE has been discovered as part of the discovery procedure.
+	 *
+	 * @param conn     Connection to the remote unicast server.
+	 * @param dir      The type of remote endpoints and capabilities discovered.
+	 * @param ep       Remote endpoint.
+	 *
+	 * If discovery procedure has complete both @p codec and @p ep are set to NULL.
+	 */
+	void (*endpoint)(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep);
+
+	/**
 	 * @brief BAP discovery callback function.
 	 *
 	 * If discovery procedure has completed @p ep is set to NULL and @p err is 0.
@@ -1235,12 +1248,10 @@
 	 * @param err      Error value. 0 on success, GATT error on positive value or errno on
 	 *                 negative value.
 	 * @param dir      The type of remote endpoints and capabilities discovered.
-	 * @param ep       Remote endpoint.
 	 *
 	 * If discovery procedure has complete both @p codec and @p ep are set to NULL.
 	 */
-	void (*discover)(struct bt_conn *conn, int err, enum bt_audio_dir dir,
-			 struct bt_bap_ep *ep);
+	void (*discover)(struct bt_conn *conn, int err, enum bt_audio_dir dir);
 };
 
 /**
diff --git a/samples/bluetooth/unicast_audio_client/src/main.c b/samples/bluetooth/unicast_audio_client/src/main.c
index 949eb12..543b5c2 100644
--- a/samples/bluetooth/unicast_audio_client/src/main.c
+++ b/samples/bluetooth/unicast_audio_client/src/main.c
@@ -583,20 +583,13 @@
 	print_codec_capabilities(codec_capabilities);
 }
 
-static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
-			      struct bt_bap_ep *ep)
+static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
 {
 	if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
 		printk("Discovery failed: %d\n", err);
 		return;
 	}
 
-	if (ep != NULL) {
-		add_remote_sink(ep);
-
-		return;
-	}
-
 	if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
 		printk("Discover sinks completed without finding any sink ASEs\n");
 	} else {
@@ -606,20 +599,13 @@
 	k_sem_give(&sem_sinks_discovered);
 }
 
-static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
-				struct bt_bap_ep *ep)
+static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
 {
 	if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
 		printk("Discovery failed: %d\n", err);
 		return;
 	}
 
-	if (ep != NULL) {
-		add_remote_source(ep);
-
-		return;
-	}
-
 	if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) {
 		printk("Discover sinks completed without finding any source ASEs\n");
 	} else {
@@ -716,10 +702,20 @@
 	print_remote_codec(codec, dir);
 }
 
+static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
+{
+	if (dir == BT_AUDIO_DIR_SOURCE) {
+		add_remote_source(ep);
+	} else if (dir == BT_AUDIO_DIR_SINK) {
+		add_remote_sink(ep);
+	}
+}
+
 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
 	.location = unicast_client_location_cb,
 	.available_contexts = available_contexts_cb,
 	.pac_record = pac_record_cb,
+	.endpoint = endpoint_cb,
 };
 
 static int init(void)
diff --git a/subsys/bluetooth/audio/bap_unicast_client.c b/subsys/bluetooth/audio/bap_unicast_client.c
index c3e8a76..f3ca171 100644
--- a/subsys/bluetooth/audio/bap_unicast_client.c
+++ b/subsys/bluetooth/audio/bap_unicast_client.c
@@ -1464,21 +1464,27 @@
 	}
 }
 
-static void discover_cb(struct bt_conn *conn, int err, struct bt_bap_ep *ep)
+static void endpoint_cb(struct bt_conn *conn, struct bt_bap_ep *ep)
+{
+	if (unicast_client_cbs != NULL && unicast_client_cbs->endpoint != NULL) {
+		struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
+		const enum bt_audio_dir dir = client->dir;
+
+		unicast_client_cbs->endpoint(conn, dir, ep);
+	}
+}
+
+static void discover_cb(struct bt_conn *conn, int err)
 {
 	struct unicast_client *client = &uni_cli_insts[bt_conn_index(conn)];
 	const enum bt_audio_dir dir = client->dir;
 
-	if (err != 0 || ep == NULL) {
-		/* Discover complete - Reset discovery values */
-		client->dir = 0U;
-		client->busy = false;
-
-		memset(&client->disc_params, 0, sizeof(client->disc_params));
-	}
+	/* Discover complete - Reset discovery values */
+	client->dir = 0U;
+	client->busy = false;
 
 	if (unicast_client_cbs != NULL && unicast_client_cbs->discover != NULL) {
-		unicast_client_cbs->discover(conn, err, dir, ep);
+		unicast_client_cbs->discover(conn, err, dir);
 	}
 }
 
@@ -1488,7 +1494,7 @@
 
 	LOG_DBG("conn %p err %u", conn, err);
 
-	discover_cb(conn, err, NULL);
+	discover_cb(conn, err);
 }
 
 static void unicast_client_ep_set_cp(struct bt_conn *conn, uint16_t handle)
@@ -1533,12 +1539,12 @@
 		if (err != 0) {
 			LOG_DBG("Failed to subscribe: %d", err);
 
-			discover_cb(conn, BT_ATT_ERR_UNLIKELY, NULL);
+			discover_cb(conn, BT_ATT_ERR_UNLIKELY);
 
 			return;
 		}
 	} else { /* already subscribed */
-		discover_cb(conn, 0, NULL);
+		discover_cb(conn, 0);
 	}
 }
 
@@ -2850,7 +2856,7 @@
 	if (!attr) {
 		LOG_ERR("Unable to find ASE Control Point");
 
-		discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL);
+		discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
 		return BT_GATT_ITER_STOP;
 	}
 
@@ -2941,19 +2947,19 @@
 	unicast_client_ep_set_status(ep, buf);
 	unicast_client_ep_subscribe(conn, ep);
 
-	discover_cb(conn, 0, ep);
+	endpoint_cb(conn, ep);
 
 	err = unicast_client_ase_discover(conn, handle);
 	if (err != 0) {
 		LOG_DBG("Failed to read ASE: %d", err);
 
-		discover_cb(conn, err, NULL);
+		discover_cb(conn, err);
 	}
 
 	return BT_GATT_ITER_STOP;
 
 fail:
-	discover_cb(conn, err, NULL);
+	discover_cb(conn, err);
 	return BT_GATT_ITER_STOP;
 }
 
@@ -2971,7 +2977,7 @@
 		if (err != 0) {
 			LOG_ERR("Unable to discover ASE Control Point");
 
-			discover_cb(conn, BT_ATT_ERR_UNLIKELY, NULL);
+			discover_cb(conn, BT_ATT_ERR_UNLIKELY);
 		}
 
 		return BT_GATT_ITER_STOP;
@@ -2998,7 +3004,7 @@
 	if (err != 0) {
 		LOG_DBG("Failed to read PAC records: %d", err);
 
-		discover_cb(conn, err, NULL);
+		discover_cb(conn, err);
 	}
 
 	return BT_GATT_ITER_STOP;
@@ -3045,7 +3051,7 @@
 			err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
 		}
 
-		discover_cb(conn, err, NULL);
+		discover_cb(conn, err);
 
 		return BT_GATT_ITER_STOP;
 	}
@@ -3065,7 +3071,7 @@
 	if (cb_err != 0) {
 		LOG_ERR("Unable to read ASE: %d", cb_err);
 
-		discover_cb(conn, err, NULL);
+		discover_cb(conn, err);
 	}
 
 	return BT_GATT_ITER_STOP;
@@ -3140,7 +3146,7 @@
 		 * the characteristic is mandatory
 		 */
 
-		discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL);
+		discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
 
 		return BT_GATT_ITER_STOP;
 	}
@@ -3176,7 +3182,7 @@
 		/* If the characteristic is not subscribable we terminate the
 		 * discovery as BT_GATT_CHRC_NOTIFY is mandatory
 		 */
-		discover_cb(conn, BT_ATT_ERR_NOT_SUPPORTED, NULL);
+		discover_cb(conn, BT_ATT_ERR_NOT_SUPPORTED);
 
 		return BT_GATT_ITER_STOP;
 	}
@@ -3185,7 +3191,7 @@
 	if (err != 0) {
 		LOG_DBG("Failed to read PACS avail_ctx: %d", err);
 
-		discover_cb(conn, err, NULL);
+		discover_cb(conn, err);
 	}
 
 	return BT_GATT_ITER_STOP;
@@ -3229,7 +3235,7 @@
 			err = BT_ATT_ERR_INVALID_ATTRIBUTE_LEN;
 		}
 
-		discover_cb(conn, err, NULL);
+		discover_cb(conn, err);
 
 		return BT_GATT_ITER_STOP;
 	}
@@ -3248,7 +3254,7 @@
 	if (cb_err != 0) {
 		LOG_ERR("Unable to read available contexts: %d", cb_err);
 
-		discover_cb(conn, cb_err, NULL);
+		discover_cb(conn, cb_err);
 	}
 
 	return BT_GATT_ITER_STOP;
@@ -3335,7 +3341,7 @@
 		if (err != 0) {
 			LOG_ERR("Unable to read available contexts: %d", err);
 
-			discover_cb(conn, err, NULL);
+			discover_cb(conn, err);
 		}
 
 		return BT_GATT_ITER_STOP;
@@ -3374,7 +3380,7 @@
 	if (err != 0) {
 		LOG_DBG("Failed to read PACS location: %d", err);
 
-		discover_cb(conn, err, NULL);
+		discover_cb(conn, err);
 	}
 
 	return BT_GATT_ITER_STOP;
@@ -3430,7 +3436,7 @@
 	if (cb_err != 0) {
 		LOG_ERR("Unable to read PACS location: %d", cb_err);
 
-		discover_cb(conn, cb_err, NULL);
+		discover_cb(conn, cb_err);
 	}
 
 	return BT_GATT_ITER_STOP;
@@ -3448,7 +3454,7 @@
 	if (attr == NULL) {
 		LOG_ERR("Unable to find %s PAC context", bt_audio_dir_str(client->dir));
 
-		discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL);
+		discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
 
 		return BT_GATT_ITER_STOP;
 	}
@@ -3471,7 +3477,7 @@
 	if (err != 0) {
 		LOG_DBG("Failed to read PAC records: %d", err);
 
-		discover_cb(conn, err, NULL);
+		discover_cb(conn, err);
 	}
 
 	return BT_GATT_ITER_STOP;
@@ -3627,7 +3633,7 @@
 	return BT_GATT_ITER_STOP;
 
 fail:
-	discover_cb(conn, cb_err, NULL);
+	discover_cb(conn, cb_err);
 	return BT_GATT_ITER_STOP;
 }
 
@@ -3643,7 +3649,7 @@
 	if (attr == NULL) {
 		LOG_ERR("Unable to find %s PAC", bt_audio_dir_str(client->dir));
 
-		discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND, NULL);
+		discover_cb(conn, BT_ATT_ERR_ATTRIBUTE_NOT_FOUND);
 
 		return BT_GATT_ITER_STOP;
 	}
@@ -3669,7 +3675,7 @@
 	if (err != 0) {
 		LOG_DBG("Failed to read PAC records: %d", err);
 
-		discover_cb(conn, err, NULL);
+		discover_cb(conn, err);
 	}
 
 	return BT_GATT_ITER_STOP;
diff --git a/subsys/bluetooth/audio/shell/bap.c b/subsys/bluetooth/audio/shell/bap.c
index 70d49a8..8d35167 100644
--- a/subsys/bluetooth/audio/shell/bap.c
+++ b/subsys/bluetooth/audio/shell/bap.c
@@ -752,47 +752,28 @@
 	print_remote_codec(conn, codec, dir);
 }
 
-static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir, struct bt_bap_ep *ep)
+static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
 {
-
-	if (ep) {
 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
-		if (dir == BT_AUDIO_DIR_SINK) {
-			add_sink(conn, ep);
-		}
+	if (dir == BT_AUDIO_DIR_SINK) {
+		add_sink(conn, ep);
+	}
 #endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
 
 #if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
-		if (dir == BT_AUDIO_DIR_SOURCE) {
-			add_source(conn, ep);
-		}
-#endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0*/
-
-		return;
+	if (dir == BT_AUDIO_DIR_SOURCE) {
+		add_source(conn, ep);
 	}
+#endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0*/
+}
 
+static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
+{
 	shell_print(ctx_shell, "Discover complete: err %d", err);
 }
 
-static void discover_all(struct bt_conn *conn, int err, enum bt_audio_dir dir, struct bt_bap_ep *ep)
+static void discover_all(struct bt_conn *conn, int err, enum bt_audio_dir dir)
 {
-
-	if (ep) {
-#if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0
-		if (dir == BT_AUDIO_DIR_SINK) {
-			add_sink(conn, ep);
-		}
-#endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT > 0 */
-
-#if CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0
-		if (dir == BT_AUDIO_DIR_SOURCE) {
-			add_source(conn, ep);
-		}
-#endif /* CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0*/
-
-		return;
-	}
-
 	/* Sinks discovery complete, now discover sources */
 	if (dir == BT_AUDIO_DIR_SINK) {
 		dir = BT_AUDIO_DIR_SOURCE;
@@ -801,7 +782,7 @@
 		err = bt_bap_unicast_client_discover(default_conn, dir);
 		if (err) {
 			shell_error(ctx_shell, "bt_bap_unicast_client_discover err %d", err);
-			discover_cb(conn, err, dir, NULL);
+			discover_cb(conn, err, dir);
 		}
 	}
 }
@@ -888,6 +869,7 @@
 	.metadata = metadata_cb,
 	.release = release_cb,
 	.pac_record = pac_record_cb,
+	.endpoint = endpoint_cb,
 };
 
 static int cmd_discover(const struct shell *sh, size_t argc, char *argv[])
diff --git a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c
index ba6dbd0..fb89cb1 100644
--- a/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c
+++ b/tests/bsim/bluetooth/audio/src/bap_unicast_client_test.c
@@ -31,6 +31,7 @@
 CREATE_FLAG(flag_sink_discovered);
 CREATE_FLAG(flag_source_discovered);
 CREATE_FLAG(flag_codec_found);
+CREATE_FLAG(flag_endpoint_found);
 CREATE_FLAG(flag_stream_codec_configured);
 static atomic_t flag_stream_qos_configured;
 CREATE_FLAG(flag_stream_enabled);
@@ -232,64 +233,28 @@
 	print_codec(codec);
 }
 
-static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
-			      struct bt_bap_ep *ep)
+static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
 {
-	static bool endpoint_found;
-
 	if (err != 0) {
 		FAIL("Discovery failed: %d\n", err);
 		return;
 	}
 
-	if (ep != NULL) {
-		if (dir == BT_AUDIO_DIR_SINK) {
-			add_remote_sink(ep);
-			endpoint_found = true;
-		} else {
-			FAIL("Invalid param dir: %u\n", dir);
-		}
+	printk("Discover complete\n");
 
-		return;
-	}
-
-	printk("Sinks discover complete\n");
-
-	if (endpoint_found) {
-		SET_FLAG(flag_sink_discovered);
-	} else {
-		FAIL("Did not discover endpoint and codec\n");
-	}
+	SET_FLAG(flag_sink_discovered);
 }
 
-static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
-				struct bt_bap_ep *ep)
+static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
 {
-	static bool endpoint_found;
-
 	if (err != 0) {
 		FAIL("Discovery failed: %d\n", err);
 		return;
 	}
 
-	if (ep != NULL) {
-		if (dir == BT_AUDIO_DIR_SOURCE) {
-			add_remote_source(ep);
-			endpoint_found = true;
-		} else {
-			FAIL("Invalid param dir: %u\n", dir);
-		}
-
-		return;
-	}
-
 	printk("Sources discover complete\n");
 
-	if (endpoint_found) {
-		SET_FLAG(flag_source_discovered);
-	} else {
-		FAIL("Did not discover endpoint and codec\n");
-	}
+	SET_FLAG(flag_source_discovered);
 }
 
 static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, const struct bt_codec *codec)
@@ -298,6 +263,17 @@
 	SET_FLAG(flag_codec_found);
 }
 
+static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
+{
+	if (dir == BT_AUDIO_DIR_SINK) {
+		add_remote_sink(ep);
+	} else {
+		add_remote_source(ep);
+	}
+
+	SET_FLAG(flag_endpoint_found);
+}
+
 static struct bt_bap_unicast_client_cb unicast_client_cbs = {
 	.location = unicast_client_location_cb,
 	.available_contexts = available_contexts_cb,
@@ -310,6 +286,7 @@
 	.metadata = metadata_cb,
 	.release = release_cb,
 	.pac_record = pac_record_cb,
+	.endpoint = endpoint_cb,
 };
 
 static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
@@ -372,6 +349,7 @@
 
 	UNSET_FLAG(flag_codec_found);
 	UNSET_FLAG(flag_sink_discovered);
+	UNSET_FLAG(flag_endpoint_found);
 
 	err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SINK);
 	if (err != 0) {
@@ -382,6 +360,7 @@
 	memset(g_sinks, 0, sizeof(g_sinks));
 
 	WAIT_FOR_FLAG(flag_codec_found);
+	WAIT_FOR_FLAG(flag_endpoint_found);
 	WAIT_FOR_FLAG(flag_sink_discovered);
 }
 
diff --git a/tests/bsim/bluetooth/audio/src/cap_initiator_test.c b/tests/bsim/bluetooth/audio/src/cap_initiator_test.c
index b4f4368..67c7f41 100644
--- a/tests/bsim/bluetooth/audio/src/cap_initiator_test.c
+++ b/tests/bsim/bluetooth/audio/src/cap_initiator_test.c
@@ -53,6 +53,7 @@
 
 CREATE_FLAG(flag_discovered);
 CREATE_FLAG(flag_codec_found);
+CREATE_FLAG(flag_endpoint_found);
 CREATE_FLAG(flag_started);
 CREATE_FLAG(flag_updated);
 CREATE_FLAG(flag_stopped);
@@ -269,39 +270,32 @@
 	SET_FLAG(flag_codec_found);
 }
 
-static void discover_sink_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir,
-			     struct bt_bap_ep *ep)
+static void discover_sink_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir)
 {
-	static bool endpoint_found;
-
 	if (err != 0) {
 		FAIL("Discovery failed: %d\n", err);
 		return;
 	}
 
-	if (ep != NULL) {
-		if (dir == BT_AUDIO_DIR_SINK) {
-			add_remote_sink(ep);
-			endpoint_found = true;
-		} else {
-			FAIL("Invalid param dir: %u\n", dir);
-		}
-
-		return;
-	}
-
 	printk("Sink discover complete\n");
 
-	if (endpoint_found) {
-		SET_FLAG(flag_sink_discovered);
+	SET_FLAG(flag_sink_discovered);
+}
+
+static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep)
+{
+	if (dir == BT_AUDIO_DIR_SINK) {
+		add_remote_sink(ep);
+		SET_FLAG(flag_endpoint_found);
 	} else {
-		FAIL("Did not discover endpoint and codec\n");
+		FAIL("Invalid param dir: %u\n", dir);
 	}
 }
 
 static const struct bt_bap_unicast_client_cb unicast_client_cbs = {
 	.discover = discover_sink_cb,
 	.pac_record = pac_record_cb,
+	.endpoint = endpoint_cb,
 };
 
 static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
@@ -377,6 +371,7 @@
 
 	UNSET_FLAG(flag_sink_discovered);
 	UNSET_FLAG(flag_codec_found);
+	UNSET_FLAG(flag_endpoint_found);
 
 	err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SINK);
 	if (err != 0) {
@@ -387,6 +382,7 @@
 	memset(unicast_sink_eps, 0, sizeof(unicast_sink_eps));
 
 	WAIT_FOR_FLAG(flag_sink_discovered);
+	WAIT_FOR_FLAG(flag_endpoint_found);
 	WAIT_FOR_FLAG(flag_codec_found);
 }