]> 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:17:47 +0000 (10:17 +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 f2f69eb4295e11d32d7a75688b7effef44096406..be2aad0492b0d5dc21ab6137ce7570bc8fba0498 100644 (file)
@@ -354,6 +354,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 ea798f07c5a2d6e90c2dc2581922edeee2de4113..71921367f0f06b6c2082d1f759f68948d36a29b8 100644 (file)
@@ -1931,6 +1931,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);
 }