diff mbox series

[RFC,BlueZ] bap: check adapter support before enabling BAP

Message ID 20230127205205.20235-1-pav@iki.fi
State New
Headers show
Series [RFC,BlueZ] bap: check adapter support before enabling BAP | expand

Commit Message

Pauli Virtanen Jan. 27, 2023, 8:52 p.m. UTC
Hi,

When the BT adapter does not have the "Connected Isochronous Stream - Central"
feature, establishing ISO connections fails at a late stage.  Namely, we get
EOPNOTSUPP in connect() due to cis_central_capable(hdev) being false.  However,
at that point BlueZ and the rest of the userspace like sound servers have
already set up the BAP stuff, and think they are trying to do something that
should succeed under normal conditions.

It appears the information about what features the adapter actually has should
be available to BlueZ earlier, and BlueZ should provide accurate information
about the adapter capabilities to the rest of the userspace.

For LE Audio in particular this is sort of important, because the adapter
support is not currently there, and only fairly new adapter models have these
features. There's also a few other bits (Core Sec 4.6, table 4.6) that BlueZ
might need to know later on, once support for more LE Audio parts is added.

At the moment the ISO sockets are under the experimental feature flag, so I'm
not sure if this is something that is to be added right now.

Below is a quick hack, which just exposes these bits to the mgmt settings a la
WBS and handles them in BlueZ.  But would this be the right place to put them
in the first place? Other ideas?  Trying to connect() to some random addresses
from userspace just to probe the feature capability probably is not the right
thing.


---
 doc/mgmt-api.txt       |  2 ++
 lib/mgmt.h             |  1 +
 profiles/audio/bap.c   |  5 +++++
 profiles/audio/media.c |  3 +++
 src/adapter.c          | 11 +++++++++++
 src/adapter.h          |  6 ++++++
 tools/btmgmt.c         |  1 +
 7 files changed, 29 insertions(+)

 include/net/bluetooth/mgmt.h | 1 +
 net/bluetooth/mgmt.c         | 6 ++++++
 2 files changed, 7 insertions(+)

Comments

Luiz Augusto von Dentz Feb. 7, 2023, 1:10 a.m. UTC | #1
Hi Pauli,

On Mon, Jan 30, 2023 at 10:58 AM Pauli Virtanen <pav@iki.fi> wrote:
>
> ---
>  src/adapter.c | 16 ++++++++++++++++
>  src/adapter.h |  3 +++
>  2 files changed, 19 insertions(+)
>
> diff --git a/src/adapter.c b/src/adapter.c
> index aadad4016..4f06bce53 100644
> --- a/src/adapter.c
> +++ b/src/adapter.c
> @@ -9033,6 +9033,22 @@ bool btd_adapter_ssp_enabled(struct btd_adapter *adapter)
>         return false;
>  }
>
> +bool btd_adapter_cis_central_capable(struct btd_adapter *adapter)
> +{
> +       if (adapter->current_settings & MGMT_SETTING_CIS_CENTRAL)
> +               return true;
> +
> +       return false;
> +}
> +
> +bool btd_adapter_cis_peripheral_capable(struct btd_adapter *adapter)
> +{
> +       if (adapter->current_settings & MGMT_SETTING_CIS_PERIPHERAL)
> +               return true;
> +
> +       return false;
> +}
> +
>  void btd_adapter_set_oob_handler(struct btd_adapter *adapter,
>                                                 struct oob_handler *handler)
>  {
> diff --git a/src/adapter.h b/src/adapter.h
> index 78eb069ae..3fcee30bc 100644
> --- a/src/adapter.h
> +++ b/src/adapter.h
> @@ -226,6 +226,9 @@ void btd_adapter_gatt_server_stop(struct btd_adapter *adapter);
>
>  bool btd_adapter_ssp_enabled(struct btd_adapter *adapter);
>
> +bool btd_adapter_cis_central_capable(struct btd_adapter *adapter);
> +bool btd_adapter_cis_peripheral_capable(struct btd_adapter *adapter);

Lets just have btd_adapter_capable(struct btd_adapter *adapter, int
flags) to make it simple to check multiple flags if needed.

>  int adapter_connect_list_add(struct btd_adapter *adapter,
>                                         struct btd_device *device);
>  void adapter_connect_list_remove(struct btd_adapter *adapter,
> --
> 2.39.1
>
Luiz Augusto von Dentz Feb. 7, 2023, 1:12 a.m. UTC | #2
Hi Pauli,

On Mon, Jan 30, 2023 at 10:48 AM Pauli Virtanen <pav@iki.fi> wrote:

Let's have the btmon output in the description to make it easier to
visualize how this changes affect it.

> ---
>  monitor/packet.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/monitor/packet.c b/monitor/packet.c
> index 44f1941bd..d9e8abf41 100644
> --- a/monitor/packet.c
> +++ b/monitor/packet.c
> @@ -12649,6 +12649,8 @@ static const struct bitfield_data mgmt_settings_table[] = {
>         { 15, "Static Address"          },
>         { 16, "PHY Configuration"       },
>         { 17, "Wideband Speech"         },
> +       { 18, "CIS Central"             },
> +       { 19, "CIS Peripheral"          },
>         { }
>  };
>
> --
> 2.39.1
>
Luiz Augusto von Dentz Feb. 7, 2023, 1:19 a.m. UTC | #3
Hi Pauli,

On Mon, Jan 30, 2023 at 12:04 PM Pauli Virtanen <pav@iki.fi> wrote:
>
> Hi Luiz,
>
> ma, 2023-01-30 kello 11:39 -0800, Luiz Augusto von Dentz kirjoitti:
> > On Mon, Jan 30, 2023 at 11:06 AM Pauli Virtanen <pav@iki.fi> wrote:
> > >
> > > Support central-only case, where no local endpoints are created, and
> > > nothing is registered in the local GATT database.
> > >
> > > In this case, we keep track of the local PACs ("sinks" and "sources"),
> > > but there are no PACS and ASCS registrations or endpoints.
> >
> > I'm not really following how that would work without local endpoints
> > since the endpoints are the interface which is used to setup the
> > stream with the likes of pipewire/pulseaudio we can't really remove
> > them, what Id would suggest doing is to have a flag indicating if the
> > instance is client only or not, that way bt_bap can identify if it
> > needs to register services or not.
>
> What I tried to say here is that in the central-only (or client in
> other words) mode, no ASEs or PACs are registered in the local GATT DB.
> The local endpoints do still exist in the Media1 API. In shared/bap.c
> they are always associated with the PACs (not ASEs), so the client-only
> mode does not need ASEs. So what is done is to my understanding what
> you write above --- maybe I am missing something?

Make sense.

> I've tested playback on this patchset for pipewire -> pipewire between
> two machines, with the CIS Central flag forced to false on one end, and
> CIS Peripheral false on the other end. Also playback to non-BlueZ
> device works with CIS Peripheral flag disabled.

Alright, make sure it also works with the likes of bluetoothctl -e as
well, since that is likely how the CI will be testing this in the
future.

> >
> > > ---
> > >  src/shared/bap.c | 58 ++++++++++++++++++++++++++----------------------
> > >  src/shared/bap.h |  9 +++++---
> > >  unit/test-bap.c  |  4 +++-
> > >  3 files changed, 40 insertions(+), 31 deletions(-)
> > >
> > > diff --git a/src/shared/bap.c b/src/shared/bap.c
> > > index 22f2e6714..24113bb34 100644
> > > --- a/src/shared/bap.c
> > > +++ b/src/shared/bap.c
> > > @@ -110,11 +110,13 @@ struct bt_ascs {
> > >
> > >  struct bt_bap_db {
> > >         struct gatt_db *db;
> > > -       struct bt_pacs *pacs;
> > > -       struct bt_ascs *ascs;
> > >         struct queue *sinks;
> > >         struct queue *sources;
> > > +
> > > +       /* The following are NULL if central-only (no GATT) */
> > >         struct queue *endpoints;
> > > +       struct bt_pacs *pacs;
> > > +       struct bt_ascs *ascs;
> > >  };
> > >
> > >  struct bt_bap_req {
> > > @@ -565,6 +567,7 @@ static void bap_disconnected(int err, void *user_data)
> > >  static struct bt_bap *bap_get_session(struct bt_att *att, struct gatt_db *db)
> > >  {
> > >         const struct queue_entry *entry;
> > > +       struct bt_bap_db *ldb;
> > >         struct bt_bap *bap;
> > >
> > >         for (entry = queue_get_entries(sessions); entry; entry = entry->next) {
> > > @@ -574,7 +577,8 @@ static struct bt_bap *bap_get_session(struct bt_att *att, struct gatt_db *db)
> > >                         return bap;
> > >         }
> > >
> > > -       bap = bt_bap_new(db, NULL);
> > > +       ldb = bt_bap_get_local_db(db, true);
> > > +       bap = bt_bap_new(ldb, NULL);
> > >         bap->att = att;
> > >
> > >         bt_bap_attach(bap, NULL);
> > > @@ -620,7 +624,7 @@ static struct bt_bap_endpoint *bap_get_endpoint(struct bt_bap_db *db,
> > >  {
> > >         struct bt_bap_endpoint *ep;
> > >
> > > -       if (!db || !attr)
> > > +       if (!db || !attr || !db->endpoints)
> > >                 return NULL;
> > >
> > >         ep = queue_find(db->endpoints, bap_endpoint_match, attr);
> > > @@ -652,7 +656,7 @@ static struct bt_bap_endpoint *bap_get_endpoint_id(struct bt_bap *bap,
> > >         struct gatt_db_attribute *attr = NULL;
> > >         size_t i;
> > >
> > > -       if (!bap || !db)
> > > +       if (!bap || !db || !db->endpoints)
> > >                 return NULL;
> > >
> > >         ep = queue_find(db->endpoints, bap_endpoint_match_id, UINT_TO_PTR(id));
> > > @@ -2170,7 +2174,7 @@ static struct bt_ascs *ascs_new(struct gatt_db *db)
> > >         return ascs;
> > >  }
> > >
> > > -static struct bt_bap_db *bap_db_new(struct gatt_db *db)
> > > +static struct bt_bap_db *bap_db_new(struct gatt_db *db, bool peripheral)
> > >  {
> > >         struct bt_bap_db *bdb;
> > >
> > > @@ -2181,23 +2185,26 @@ static struct bt_bap_db *bap_db_new(struct gatt_db *db)
> > >         bdb->db = gatt_db_ref(db);
> > >         bdb->sinks = queue_new();
> > >         bdb->sources = queue_new();
> > > -       bdb->endpoints = queue_new();
> > >
> > >         if (!bap_db)
> > >                 bap_db = queue_new();
> > >
> > > -       bdb->pacs = pacs_new(db);
> > > -       bdb->pacs->bdb = bdb;
> > > +       if (peripheral) {
> > > +               bdb->endpoints = queue_new();
> > >
> > > -       bdb->ascs = ascs_new(db);
> > > -       bdb->ascs->bdb = bdb;
> > > +               bdb->pacs = pacs_new(db);
> > > +               bdb->pacs->bdb = bdb;
> > > +
> > > +               bdb->ascs = ascs_new(db);
> > > +               bdb->ascs->bdb = bdb;
> > > +       }
> > >
> > >         queue_push_tail(bap_db, bdb);
> > >
> > >         return bdb;
> > >  }
> > >
> > > -static struct bt_bap_db *bap_get_db(struct gatt_db *db)
> > > +struct bt_bap_db *bt_bap_get_local_db(struct gatt_db *db, bool peripheral)
> > >  {
> > >         struct bt_bap_db *bdb;
> > >
> > > @@ -2205,7 +2212,7 @@ static struct bt_bap_db *bap_get_db(struct gatt_db *db)
> > >         if (bdb)
> > >                 return bdb;
> > >
> > > -       return bap_db_new(db);
> > > +       return bap_db_new(db, peripheral);
> > >  }
> > >
> > >  static struct bt_pacs *bap_get_pacs(struct bt_bap *bap)
> > > @@ -2328,6 +2335,9 @@ static void bap_add_sink(struct bt_bap_pac *pac)
> > >
> > >         queue_push_tail(pac->bdb->sinks, pac);
> > >
> > > +       if (!pac->bdb->endpoints)
> > > +               return;
> > > +
> > >         memset(value, 0, sizeof(value));
> > >
> > >         iov.iov_base = value;
> > > @@ -2346,6 +2356,9 @@ static void bap_add_source(struct bt_bap_pac *pac)
> > >
> > >         queue_push_tail(pac->bdb->sources, pac);
> > >
> > > +       if (!pac->bdb->endpoints)
> > > +               return;
> > > +
> > >         memset(value, 0, sizeof(value));
> > >
> > >         iov.iov_base = value;
> > > @@ -2373,21 +2386,16 @@ static void notify_session_pac_added(void *data, void *user_data)
> > >         queue_foreach(bap->pac_cbs, notify_pac_added, user_data);
> > >  }
> > >
> > > -struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
> > > +struct bt_bap_pac *bt_bap_add_vendor_pac(struct bt_bap_db *bdb,
> > >                                         const char *name, uint8_t type,
> > >                                         uint8_t id, uint16_t cid, uint16_t vid,
> > >                                         struct bt_bap_pac_qos *qos,
> > >                                         struct iovec *data,
> > >                                         struct iovec *metadata)
> > >  {
> > > -       struct bt_bap_db *bdb;
> > >         struct bt_bap_pac *pac;
> > >         struct bt_bap_codec codec;
> > >
> > > -       if (!db)
> > > -               return NULL;
> > > -
> > > -       bdb = bap_get_db(db);
> > >         if (!bdb)
> > >                 return NULL;
> > >
> > > @@ -2417,13 +2425,13 @@ struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
> > >         return pac;
> > >  }
> > >
> > > -struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
> > > +struct bt_bap_pac *bt_bap_add_pac(struct bt_bap_db *bdb, const char *name,
> > >                                         uint8_t type, uint8_t id,
> > >                                         struct bt_bap_pac_qos *qos,
> > >                                         struct iovec *data,
> > >                                         struct iovec *metadata)
> > >  {
> > > -       return bt_bap_add_vendor_pac(db, name, type, id, 0x0000, 0x0000, qos,
> > > +       return bt_bap_add_vendor_pac(bdb, name, type, id, 0x0000, 0x0000, qos,
> > >                                                         data, metadata);
> > >  }
> > >
> > > @@ -2635,7 +2643,7 @@ static void bap_attached(void *data, void *user_data)
> > >         cb->attached(bap, cb->user_data);
> > >  }
> > >
> > > -struct bt_bap *bt_bap_new(struct gatt_db *ldb, struct gatt_db *rdb)
> > > +struct bt_bap *bt_bap_new(struct bt_bap_db *ldb, struct gatt_db *rdb)
> > >  {
> > >         struct bt_bap *bap;
> > >         struct bt_bap_db *bdb;
> > > @@ -2643,12 +2651,8 @@ struct bt_bap *bt_bap_new(struct gatt_db *ldb, struct gatt_db *rdb)
> > >         if (!ldb)
> > >                 return NULL;
> > >
> > > -       bdb = bap_get_db(ldb);
> > > -       if (!bdb)
> > > -               return NULL;
> > > -
> > >         bap = new0(struct bt_bap, 1);
> > > -       bap->ldb = bdb;
> > > +       bap->ldb = ldb;
> > >         bap->reqs = queue_new();
> > >         bap->pending = queue_new();
> > >         bap->notify = queue_new();
> > > diff --git a/src/shared/bap.h b/src/shared/bap.h
> > > index 47a15636c..a4e8549a5 100644
> > > --- a/src/shared/bap.h
> > > +++ b/src/shared/bap.h
> > > @@ -34,6 +34,7 @@
> > >  #define BT_BAP_CONFIG_PHY_CODEC                0x03
> > >
> > >  struct bt_bap;
> > > +struct bt_bap_db;
> > >  struct bt_bap_pac;
> > >  struct bt_bap_stream;
> > >
> > > @@ -98,14 +99,14 @@ struct bt_bap_pac_qos {
> > >         uint32_t ppd_max;
> > >  };
> > >
> > > -struct bt_bap_pac *bt_bap_add_vendor_pac(struct gatt_db *db,
> > > +struct bt_bap_pac *bt_bap_add_vendor_pac(struct bt_bap_db *bdb,
> > >                                         const char *name, uint8_t type,
> > >                                         uint8_t id, uint16_t cid, uint16_t vid,
> > >                                         struct bt_bap_pac_qos *qos,
> > >                                         struct iovec *data,
> > >                                         struct iovec *metadata);
> > >
> > > -struct bt_bap_pac *bt_bap_add_pac(struct gatt_db *db, const char *name,
> > > +struct bt_bap_pac *bt_bap_add_pac(struct bt_bap_db *bdb, const char *name,
> > >                                         uint8_t type, uint8_t id,
> > >                                         struct bt_bap_pac_qos *qos,
> > >                                         struct iovec *data,
> > > @@ -135,7 +136,9 @@ unsigned int bt_bap_register(bt_bap_func_t added, bt_bap_func_t removed,
> > >                                                         void *user_data);
> > >  bool bt_bap_unregister(unsigned int id);
> > >
> > > -struct bt_bap *bt_bap_new(struct gatt_db *ldb, struct gatt_db *rdb);
> > > +struct bt_bap_db *bt_bap_get_local_db(struct gatt_db *db, bool peripheral);
> > > +
> > > +struct bt_bap *bt_bap_new(struct bt_bap_db *ldb, struct gatt_db *rdb);
> > >
> > >  bool bt_bap_set_user_data(struct bt_bap *bap, void *user_data);
> > >
> > > diff --git a/unit/test-bap.c b/unit/test-bap.c
> > > index afeefac84..b677f5197 100644
> > > --- a/unit/test-bap.c
> > > +++ b/unit/test-bap.c
> > > @@ -311,6 +311,7 @@ static void test_client(const void *user_data)
> > >  {
> > >         struct test_data *data = (void *)user_data;
> > >         struct io *io;
> > > +       struct bt_bap_db *ldb;
> > >         struct gatt_db *db;
> > >
> > >         io = tester_setup_io(data->iov, data->iovcnt);
> > > @@ -321,7 +322,8 @@ static void test_client(const void *user_data)
> > >         db = gatt_db_new();
> > >         g_assert(db);
> > >
> > > -       data->bap = bt_bap_new(db, bt_gatt_client_get_db(data->client));
> > > +       ldb = bt_bap_get_local_db(db, true);
> > > +       data->bap = bt_bap_new(ldb, bt_gatt_client_get_db(data->client));
> > >         g_assert(data->bap);
> > >
> > >         bt_bap_set_debug(data->bap, print_debug, "bt_bap:", NULL);
> > > --
> > > 2.39.1
> > >
> >
> >
>
> --
> Pauli Virtanen
diff mbox series

Patch

diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index 90d612ed8..11798629a 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -333,6 +333,7 @@  Read Controller Information Command
 		16	PHY Configuration
 		17	Wideband Speech
 		18	Quality Report
+		19	Connected Isochronous Stream Central
 
 	This command generates a Command Complete event on success or
 	a Command Status event on failure.
@@ -2926,6 +2927,7 @@  Read Extended Controller Information Command
 		16	PHY Configuration
 		17	Wideband Speech
 		18	Quality Report
+		19	Connected Isochronous Stream Central
 
 	The EIR_Data field contains information about class of device,
 	local name and other values. Not all of them might be present. For
diff --git a/lib/mgmt.h b/lib/mgmt.h
index 796190cd9..610770491 100644
--- a/lib/mgmt.h
+++ b/lib/mgmt.h
@@ -96,6 +96,7 @@  struct mgmt_rp_read_index_list {
 #define MGMT_SETTING_STATIC_ADDRESS	0x00008000
 #define MGMT_SETTING_PHY_CONFIGURATION	0x00010000
 #define MGMT_SETTING_WIDEBAND_SPEECH	0x00020000
+#define MGMT_SETTING_CIS_CENTRAL	0x00040000
 
 #define MGMT_OP_READ_INFO		0x0004
 struct mgmt_rp_read_info {
diff --git a/profiles/audio/bap.c b/profiles/audio/bap.c
index e5ffb7230..2cd12465a 100644
--- a/profiles/audio/bap.c
+++ b/profiles/audio/bap.c
@@ -1264,6 +1264,11 @@  static int bap_probe(struct btd_service *service)
 		return -ENOTSUP;
 	}
 
+	if (!btd_adapter_has_feature(adapter, ADAPTER_FEAT_CIS_CENTRAL)) {
+		error("BAP requires CIS Central, but unsupported by adapter");
+		return -ENOTSUP;
+	}
+
 	/* Ignore, if we were probed for this device already */
 	if (data) {
 		error("Profile probed twice for the same device!");
diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index fbb350889..873dee33e 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -1259,6 +1259,9 @@  static bool experimental_endpoint_supported(struct btd_adapter *adapter)
 	if (!btd_adapter_has_exp_feature(adapter, EXP_FEAT_ISO_SOCKET))
 		return false;
 
+	if (!btd_adapter_has_feature(adapter, ADAPTER_FEAT_CIS_CENTRAL))
+		return false;
+
 	return g_dbus_get_flags() & G_DBUS_FLAG_ENABLE_EXPERIMENTAL;
 }
 
diff --git a/src/adapter.c b/src/adapter.c
index aadad4016..2e038ace0 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -10717,6 +10717,17 @@  bool btd_has_kernel_features(uint32_t features)
 	return (kernel_features & features) ? true : false;
 }
 
+bool btd_adapter_has_feature(struct btd_adapter *adapter, uint32_t feature)
+{
+	size_t i;
+	uint32_t features = 0;
+
+	if (adapter->supported_settings & MGMT_SETTING_CIS_CENTRAL)
+		features |= ADAPTER_FEAT_CIS_CENTRAL;
+
+	return features & feature;
+}
+
 bool btd_adapter_has_exp_feature(struct btd_adapter *adapter, uint32_t feature)
 {
 	size_t i;
diff --git a/src/adapter.h b/src/adapter.h
index 78eb069ae..6a9a626bc 100644
--- a/src/adapter.h
+++ b/src/adapter.h
@@ -256,6 +256,12 @@  void btd_adapter_for_each_device(struct btd_adapter *adapter,
 
 bool btd_le_connect_before_pairing(void);
 
+enum adapter_features {
+	ADAPTER_FEAT_CIS_CENTRAL	= 1 << 0,
+};
+
+bool btd_adapter_has_feature(struct btd_adapter *adapter, uint32_t feature);
+
 enum experimental_features {
 	EXP_FEAT_DEBUG			= 1 << 0,
 	EXP_FEAT_LE_SIMULT_ROLES	= 1 << 1,
diff --git a/tools/btmgmt.c b/tools/btmgmt.c
index 29f86091f..de614ced1 100644
--- a/tools/btmgmt.c
+++ b/tools/btmgmt.c
@@ -353,6 +353,7 @@  static const char *settings_str[] = {
 				"static-addr",
 				"phy-configuration",
 				"wide-band-speech",
+				"cis-central",
 };
 
 static const char *settings2str(uint32_t settings)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 743f6f59dff8..dc284c5f5cbb 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -109,6 +109,7 @@  struct mgmt_rp_read_index_list {
 #define MGMT_SETTING_STATIC_ADDRESS	0x00008000
 #define MGMT_SETTING_PHY_CONFIGURATION	0x00010000
 #define MGMT_SETTING_WIDEBAND_SPEECH	0x00020000
+#define MGMT_SETTING_CIS_CENTRAL	0x00040000
 
 #define MGMT_OP_READ_INFO		0x0004
 #define MGMT_READ_INFO_SIZE		0
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 0dd30a3beb77..d802faf60f26 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -859,6 +859,9 @@  static u32 get_supported_settings(struct hci_dev *hdev)
 	    hdev->set_bdaddr)
 		settings |= MGMT_SETTING_CONFIGURATION;
 
+	if (cis_central_capable(hdev))
+		settings |= MGMT_SETTING_CIS_CENTRAL;
+
 	settings |= MGMT_SETTING_PHY_CONFIGURATION;
 
 	return settings;
@@ -932,6 +935,9 @@  static u32 get_current_settings(struct hci_dev *hdev)
 	if (hci_dev_test_flag(hdev, HCI_WIDEBAND_SPEECH_ENABLED))
 		settings |= MGMT_SETTING_WIDEBAND_SPEECH;
 
+	if (cis_central_capable(hdev) && iso_enabled())
+		settings |= MGMT_SETTING_CIS_CENTRAL;
+
 	return settings;
 }