if (IS_ERR(skb)) {
err = PTR_ERR(skb);
if (err == -ENODATA)
- return 0;
+ goto done;
BT_ERR("%s: Changing Intel diagnostic mode failed (%d)",
hdev->name, err);
return err;
}
kfree_skb(skb);
+done:
+ btintel_set_event_mask(hdev, enable);
return 0;
}
EXPORT_SYMBOL_GPL(btintel_set_diag);
}
EXPORT_SYMBOL_GPL(btintel_load_ddc_config);
+int btintel_set_event_mask(struct hci_dev *hdev, bool debug)
+{
+ u8 mask[8] = { 0x87, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ struct sk_buff *skb;
+ int err;
+
+ if (debug)
+ mask[1] |= 0x62;
+
+ skb = __hci_cmd_sync(hdev, 0xfc52, 8, mask, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: Setting Intel event mask failed (%d)",
+ hdev->name, err);
+ return err;
+ }
+ kfree_skb(skb);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btintel_set_event_mask);
+
+int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug)
+{
+ struct sk_buff *skb;
+ u8 param[2];
+ int err;
+
+ param[0] = 0x01;
+ param[1] = 0x00;
+
+ skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: Entering Intel manufacturer mode failed (%d)",
+ hdev->name, err);
+ return PTR_ERR(skb);
+ }
+ kfree_skb(skb);
+
+ err = btintel_set_event_mask(hdev, debug);
+
+ param[0] = 0x00;
+ param[1] = 0x00;
+
+ skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: Leaving Intel manufacturer mode failed (%d)",
+ hdev->name, err);
+ return PTR_ERR(skb);
+ }
+ kfree_skb(skb);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(btintel_set_event_mask_mfg);
+
/* ------- REGMAP IBT SUPPORT ------- */
#define IBT_REG_MODE_8BIT 0x00
int btintel_secure_send(struct hci_dev *hdev, u8 fragment_type, u32 plen,
const void *param);
int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name);
+int btintel_set_event_mask(struct hci_dev *hdev, bool debug);
+int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug);
struct regmap *btintel_regmap_init(struct hci_dev *hdev, u16 opcode_read,
u16 opcode_write);
return -EOPNOTSUPP;
}
+static inline int btintel_set_event_mask(struct hci_dev *hdev, bool debug)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug)
+{
+ return -EOPNOTSUPP;
+}
+
static inline struct regmap *btintel_regmap_init(struct hci_dev *hdev,
u16 opcode_read,
u16 opcode_write)
BT_INFO("%s: Intel device is already patched. patch num: %02x",
hdev->name, ver->fw_patch_num);
kfree_skb(skb);
- btintel_check_bdaddr(hdev);
- return 0;
+ goto complete;
}
/* Opens the firmware patch file based on the firmware version read
fw = btusb_setup_intel_get_fw(hdev, ver);
if (!fw) {
kfree_skb(skb);
- btintel_check_bdaddr(hdev);
- return 0;
+ goto complete;
}
fw_ptr = fw->data;
BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",
hdev->name);
- btintel_check_bdaddr(hdev);
- return 0;
+ goto complete;
exit_mfg_disable:
/* Disable the manufacturer mode without reset */
BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name);
- btintel_check_bdaddr(hdev);
- return 0;
+ goto complete;
exit_mfg_deactivate:
release_firmware(fw);
BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",
hdev->name);
+complete:
+ /* Set the event mask for Intel specific vendor events. This enables
+ * a few extra events that are useful during general operation.
+ */
+ btintel_set_event_mask_mfg(hdev, false);
+
btintel_check_bdaddr(hdev);
return 0;
}
*/
btintel_load_ddc_config(hdev, fwname);
+ /* Set the event mask for Intel specific vendor events. This enables
+ * a few extra events that are useful during general operation. It
+ * does not enable any debugging related events.
+ *
+ * The device will function correctly without these events enabled
+ * and thus no need to fail the setup.
+ */
+ btintel_set_event_mask(hdev, false);
+
return 0;
}