Bluetooth: hci_core: Fix using {cis,bis}_capable for current settings
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Mon, 4 Aug 2025 13:54:05 +0000 (09:54 -0400)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 15 Aug 2025 13:44:49 +0000 (09:44 -0400)
{cis,bis}_capable only indicates the controller supports the feature
since it doesn't check that LE is enabled so it shall not be used for
current setting, instead this introduces {cis,bis}_enabled macros that
can be used to indicate that these features are currently enabled.

Fixes: 26afbd826ee3 ("Bluetooth: Add initial implementation of CIS connections")
Fixes: eca0ae4aea66 ("Bluetooth: Add initial implementation of BIS connections")
Fixes: ae7533613133 ("Bluetooth: Check for ISO support in controller")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
include/net/bluetooth/bluetooth.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_sync.c
net/bluetooth/iso.c
net/bluetooth/mgmt.c

index ada5b56a441350399810075254606d3c57196150..e5751f3070b8e34fc0bd8ea7a0d9fe134c29e5f4 100644 (file)
@@ -647,7 +647,7 @@ static inline void sco_exit(void)
 #if IS_ENABLED(CONFIG_BT_LE)
 int iso_init(void);
 int iso_exit(void);
-bool iso_enabled(void);
+bool iso_inited(void);
 #else
 static inline int iso_init(void)
 {
@@ -659,7 +659,7 @@ static inline int iso_exit(void)
        return 0;
 }
 
-static inline bool iso_enabled(void)
+static inline bool iso_inited(void)
 {
        return false;
 }
index 4dc11c66f7b819727b2c77eca19ca8556485f249..bc29f2e2e16f0c23fba57fc3a1cc43f310404485 100644 (file)
@@ -1915,6 +1915,8 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
                                !hci_dev_test_flag(dev, HCI_RPA_EXPIRED))
 #define adv_rpa_valid(adv)     (bacmp(&adv->random_addr, BDADDR_ANY) && \
                                !adv->rpa_expired)
+#define le_enabled(dev)        (lmp_le_capable(dev) && \
+                               hci_dev_test_flag(dev, HCI_LE_ENABLED))
 
 #define scan_1m(dev) (((dev)->le_tx_def_phys & HCI_LE_SET_PHY_1M) || \
                      ((dev)->le_rx_def_phys & HCI_LE_SET_PHY_1M))
@@ -1981,14 +1983,23 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
 
 /* CIS Master/Slave and BIS support */
 #define iso_capable(dev) (cis_capable(dev) || bis_capable(dev))
+#define iso_enabled(dev) (le_enabled(dev) && iso_capable(dev))
 #define cis_capable(dev) \
        (cis_central_capable(dev) || cis_peripheral_capable(dev))
+#define cis_enabled(dev) (le_enabled(dev) && cis_capable(dev))
 #define cis_central_capable(dev) \
        ((dev)->le_features[3] & HCI_LE_CIS_CENTRAL)
+#define cis_central_enabled(dev) \
+       (le_enabled(dev) && cis_central_capable(dev))
 #define cis_peripheral_capable(dev) \
        ((dev)->le_features[3] & HCI_LE_CIS_PERIPHERAL)
+#define cis_peripheral_enabled(dev) \
+       (le_enabled(dev) && cis_peripheral_capable(dev))
 #define bis_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_BROADCASTER)
-#define sync_recv_capable(dev) ((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER)
+#define bis_enabled(dev) (le_enabled(dev) && bis_capable(dev))
+#define sync_recv_capable(dev) \
+       ((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER)
+#define sync_recv_enabled(dev) (le_enabled(dev) && sync_recv_capable(dev))
 
 #define mws_transport_config_capable(dev) (((dev)->commands[30] & 0x08) && \
        (!hci_test_quirk((dev), HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG)))
index 387c128f2ba0a6abf5ffd26fce93e3e9a953b24c..aa7d7a8ec3ee6435e640e5a1d599b8f5a9b3c7f0 100644 (file)
@@ -4531,14 +4531,14 @@ static int hci_le_set_host_feature_sync(struct hci_dev *hdev)
 {
        struct hci_cp_le_set_host_feature cp;
 
-       if (!cis_capable(hdev))
+       if (!iso_capable(hdev))
                return 0;
 
        memset(&cp, 0, sizeof(cp));
 
        /* Connected Isochronous Channels (Host Support) */
        cp.bit_number = 32;
-       cp.bit_value = 1;
+       cp.bit_value = iso_enabled(hdev) ? 0x01 : 0x00;
 
        return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_HOST_FEATURE,
                                     sizeof(cp), &cp, HCI_CMD_TIMEOUT);
index eaffd25570e3b0014764b217bd40c3484d87ce63..5ce823ca3aaf4406ae66d34e1cbfbfe608d5984e 100644 (file)
@@ -2483,11 +2483,11 @@ static const struct net_proto_family iso_sock_family_ops = {
        .create = iso_sock_create,
 };
 
-static bool iso_inited;
+static bool inited;
 
-bool iso_enabled(void)
+bool iso_inited(void)
 {
-       return iso_inited;
+       return inited;
 }
 
 int iso_init(void)
@@ -2496,7 +2496,7 @@ int iso_init(void)
 
        BUILD_BUG_ON(sizeof(struct sockaddr_iso) > sizeof(struct sockaddr));
 
-       if (iso_inited)
+       if (inited)
                return -EALREADY;
 
        err = proto_register(&iso_proto, 0);
@@ -2524,7 +2524,7 @@ int iso_init(void)
                iso_debugfs = debugfs_create_file("iso", 0444, bt_debugfs,
                                                  NULL, &iso_debugfs_fops);
 
-       iso_inited = true;
+       inited = true;
 
        return 0;
 
@@ -2535,7 +2535,7 @@ error:
 
 int iso_exit(void)
 {
-       if (!iso_inited)
+       if (!inited)
                return -EALREADY;
 
        bt_procfs_cleanup(&init_net, "iso");
@@ -2549,7 +2549,7 @@ int iso_exit(void)
 
        proto_unregister(&iso_proto);
 
-       iso_inited = false;
+       inited = false;
 
        return 0;
 }
index 1ce682038b519325c5119af4f3e0c6b1d4ff85c8..c42dffe77daf44863d59684c52d7aae0f1f448a1 100644 (file)
@@ -922,16 +922,16 @@ 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))
+       if (cis_central_enabled(hdev))
                settings |= MGMT_SETTING_CIS_CENTRAL;
 
-       if (cis_peripheral_capable(hdev))
+       if (cis_peripheral_enabled(hdev))
                settings |= MGMT_SETTING_CIS_PERIPHERAL;
 
-       if (bis_capable(hdev))
+       if (bis_enabled(hdev))
                settings |= MGMT_SETTING_ISO_BROADCASTER;
 
-       if (sync_recv_capable(hdev))
+       if (sync_recv_enabled(hdev))
                settings |= MGMT_SETTING_ISO_SYNC_RECEIVER;
 
        if (ll_privacy_capable(hdev))
@@ -4513,7 +4513,7 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
        }
 
        if (IS_ENABLED(CONFIG_BT_LE)) {
-               flags = iso_enabled() ? BIT(0) : 0;
+               flags = iso_inited() ? BIT(0) : 0;
                memcpy(rp->features[idx].uuid, iso_socket_uuid, 16);
                rp->features[idx].flags = cpu_to_le32(flags);
                idx++;