]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Bluetooth: Add quirk for broken READ_VOICE_SETTING
authorPedro Nishiyama <nishiyama.pedro@gmail.com>
Sat, 1 Mar 2025 06:22:58 +0000 (03:22 -0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 20 Apr 2025 08:15:22 +0000 (10:15 +0200)
[ Upstream commit ff26b2dd6568392f60fa67a4e58279938025c3af ]

Some fake controllers cannot be initialized because they return a smaller
report than expected for READ_VOICE_SETTING.

Signed-off-by: Pedro Nishiyama <nishiyama.pedro@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_sync.c

index dd10e02bfc746ebe88f5e83aabe35a87ca76232b..fa6f92915968f58bb720e7f58c4949f5ac5afa3f 100644 (file)
@@ -353,6 +353,14 @@ enum {
         * during the hdev->setup vendor callback.
         */
        HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY,
+
+       /* When this quirk is set, the HCI_OP_READ_VOICE_SETTING command is
+        * skipped. This is required for a subset of the CSR controller clones
+        * which erroneously claim to support it.
+        *
+        * This quirk must be set before hci_register_dev is called.
+        */
+       HCI_QUIRK_BROKEN_READ_VOICE_SETTING,
 };
 
 /* HCI device flags */
index c95f7e6ba2551403a174746cad0519f3e6cc50a8..4245910ffc4a2d731e92269271e338537e810a93 100644 (file)
@@ -1921,6 +1921,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
        ((dev)->commands[20] & 0x10 && \
         !test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks))
 
+#define read_voice_setting_capable(dev) \
+       ((dev)->commands[9] & 0x04 && \
+        !test_bit(HCI_QUIRK_BROKEN_READ_VOICE_SETTING, &(dev)->quirks))
+
 /* Use enhanced synchronous connection if command is supported and its quirk
  * has not been set.
  */
index 7b2b04d6b856309e5bd08640b9051ec8bf81c9a7..bb455e96a715aaecd2d3a48cc45462693c260294 100644 (file)
@@ -3720,6 +3720,9 @@ static int hci_read_local_name_sync(struct hci_dev *hdev)
 /* Read Voice Setting */
 static int hci_read_voice_setting_sync(struct hci_dev *hdev)
 {
+       if (!read_voice_setting_capable(hdev))
+               return 0;
+
        return __hci_cmd_sync_status(hdev, HCI_OP_READ_VOICE_SETTING,
                                     0, NULL, HCI_CMD_TIMEOUT);
 }