]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/bluetooth/btusb.c
Bluetooth: btusb: Add routine for applying Intel DDC parameters
[linux.git] / drivers / bluetooth / btusb.c
index e97d036cde701755512da7732402fdf478baf898..3970224b3b09e95caf4280b40f5a35bef1ffebdf 100644 (file)
@@ -2083,6 +2083,12 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
 
        BT_INFO("%s: Found device firmware: %s", hdev->name, fwname);
 
+       /* Save the DDC file name for later use to apply once the firmware
+        * downloading is done.
+        */
+       snprintf(fwname, sizeof(fwname), "intel/ibt-11-%u.ddc",
+                le16_to_cpu(params->dev_revid));
+
        kfree_skb(skb);
 
        if (fw->size < 644) {
@@ -2244,6 +2250,43 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
 
        clear_bit(BTUSB_BOOTLOADER, &data->flags);
 
+       /* Once the device is running in operational mode, it needs to apply
+        * the device configuration (DDC) parameters.
+        *
+        * The device can work without DDC parameters, so even if it fails
+        * to load the file, no need to fail the setup.
+        */
+       err = request_firmware_direct(&fw, fwname, &hdev->dev);
+       if (err < 0)
+               return 0;
+
+       BT_INFO("%s: Found Intel DDC parameters: %s", hdev->name, fwname);
+
+       fw_ptr = fw->data;
+
+       /* DDC file contains one or more DDC structure which has
+        * Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2).
+        */
+       while (fw->size > fw_ptr - fw->data) {
+               u8 cmd_plen = fw_ptr[0] + sizeof(u8);
+
+               skb = __hci_cmd_sync(hdev, 0xfc8b, cmd_plen, fw_ptr,
+                                    HCI_INIT_TIMEOUT);
+               if (IS_ERR(skb)) {
+                       BT_ERR("%s: Failed to send Intel_Write_DDC (%ld)",
+                              hdev->name, PTR_ERR(skb));
+                       release_firmware(fw);
+                       return PTR_ERR(skb);
+               }
+
+               fw_ptr += cmd_plen;
+               kfree_skb(skb);
+       }
+
+       release_firmware(fw);
+
+       BT_INFO("%s: Applying Intel DDC parameters completed", hdev->name);
+
        return 0;
 }