]> git.ipfire.org Git - thirdparty/kernel/linux.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)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Tue, 25 Mar 2025 16:43:25 +0000 (12:43 -0400)
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>
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
net/bluetooth/hci_sync.c

index 3ec915738112b73f00d71aada780e5b53977de97..295d97e312e1d260490a1024cfea59b3c8e46b46 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 131ff1f4ebef55c0ec22360dd76994ff1bea17c2..7966db4038ccae363e5dc61be7df6ca988ca868b 100644 (file)
@@ -1925,6 +1925,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 a43749aebf76e83f3541deb346015c5e5a620eda..fd07858387600f9a637ab0b3fa7bbda146171f8f 100644 (file)
@@ -3696,6 +3696,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);
 }