aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/bluetooth
diff options
context:
space:
mode:
authorLoic Poulain <loic.poulain@intel.com>2015-12-03 10:10:22 -0500
committerMarcel Holtmann <marcel@holtmann.org>2015-12-09 18:51:50 -0500
commit28dc4b92e20e0fd18be2d8356abf959d58c7346a (patch)
tree38967870eb36b45e689755e08ebedc93d8beec0a /drivers/bluetooth
parent1623d0bf847d3b38d8cf24367b3689ba0e3fe2aa (diff)
Bluetooth: btintel: Add manufacturing enter/exit helpers
Older Intel controllers need to enter manufacturing mode to perform some vendor specific operations (patching, configuration...). Add enter/exit manufaturing methods and refactor existing manufacturing code. Exit can be configured to perform a reset. Reset can be performed either with patches activated or deactivated. Signed-off-by: Loic Poulain <loic.poulain@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'drivers/bluetooth')
-rw-r--r--drivers/bluetooth/btintel.c114
-rw-r--r--drivers/bluetooth/btintel.h12
-rw-r--r--drivers/bluetooth/btusb.c54
3 files changed, 86 insertions, 94 deletions
diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
index 1f13e617bf56..54410479f2f5 100644
--- a/drivers/bluetooth/btintel.c
+++ b/drivers/bluetooth/btintel.c
@@ -73,6 +73,48 @@ int btintel_check_bdaddr(struct hci_dev *hdev)
73} 73}
74EXPORT_SYMBOL_GPL(btintel_check_bdaddr); 74EXPORT_SYMBOL_GPL(btintel_check_bdaddr);
75 75
76int btintel_enter_mfg(struct hci_dev *hdev)
77{
78 const u8 param[] = { 0x01, 0x00 };
79 struct sk_buff *skb;
80
81 skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT);
82 if (IS_ERR(skb)) {
83 bt_dev_err(hdev, "Entering manufacturer mode failed (%ld)",
84 PTR_ERR(skb));
85 return PTR_ERR(skb);
86 }
87 kfree_skb(skb);
88
89 return 0;
90}
91EXPORT_SYMBOL_GPL(btintel_enter_mfg);
92
93int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched)
94{
95 u8 param[] = { 0x00, 0x00 };
96 struct sk_buff *skb;
97
98 /* The 2nd command parameter specifies the manufacturing exit method:
99 * 0x00: Just disable the manufacturing mode (0x00).
100 * 0x01: Disable manufacturing mode and reset with patches deactivated.
101 * 0x02: Disable manufacturing mode and reset with patches activated.
102 */
103 if (reset)
104 param[1] |= patched ? 0x02 : 0x01;
105
106 skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_CMD_TIMEOUT);
107 if (IS_ERR(skb)) {
108 bt_dev_err(hdev, "Exiting manufacturer mode failed (%ld)",
109 PTR_ERR(skb));
110 return PTR_ERR(skb);
111 }
112 kfree_skb(skb);
113
114 return 0;
115}
116EXPORT_SYMBOL_GPL(btintel_exit_mfg);
117
76int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) 118int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
77{ 119{
78 struct sk_buff *skb; 120 struct sk_buff *skb;
@@ -126,37 +168,19 @@ EXPORT_SYMBOL_GPL(btintel_set_diag);
126 168
127int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable) 169int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable)
128{ 170{
129 struct sk_buff *skb; 171 int err, ret;
130 u8 param[2];
131 int err;
132
133 param[0] = 0x01;
134 param[1] = 0x00;
135
136 skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
137 if (IS_ERR(skb)) {
138 err = PTR_ERR(skb);
139 BT_ERR("%s: Entering Intel manufacturer mode failed (%d)",
140 hdev->name, err);
141 return PTR_ERR(skb);
142 }
143 kfree_skb(skb);
144 172
145 err = btintel_set_diag(hdev, enable); 173 err = btintel_enter_mfg(hdev);
174 if (err)
175 return err;
146 176
147 param[0] = 0x00; 177 ret = btintel_set_diag(hdev, enable);
148 param[1] = 0x00;
149 178
150 skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT); 179 err = btintel_exit_mfg(hdev, false, false);
151 if (IS_ERR(skb)) { 180 if (err)
152 err = PTR_ERR(skb); 181 return err;
153 BT_ERR("%s: Leaving Intel manufacturer mode failed (%d)",
154 hdev->name, err);
155 return PTR_ERR(skb);
156 }
157 kfree_skb(skb);
158 182
159 return err; 183 return ret;
160} 184}
161EXPORT_SYMBOL_GPL(btintel_set_diag_mfg); 185EXPORT_SYMBOL_GPL(btintel_set_diag_mfg);
162 186
@@ -309,37 +333,19 @@ EXPORT_SYMBOL_GPL(btintel_set_event_mask);
309 333
310int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug) 334int btintel_set_event_mask_mfg(struct hci_dev *hdev, bool debug)
311{ 335{
312 struct sk_buff *skb; 336 int err, ret;
313 u8 param[2];
314 int err;
315 337
316 param[0] = 0x01; 338 err = btintel_enter_mfg(hdev);
317 param[1] = 0x00; 339 if (err)
318 340 return err;
319 skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT);
320 if (IS_ERR(skb)) {
321 err = PTR_ERR(skb);
322 BT_ERR("%s: Entering Intel manufacturer mode failed (%d)",
323 hdev->name, err);
324 return PTR_ERR(skb);
325 }
326 kfree_skb(skb);
327
328 err = btintel_set_event_mask(hdev, debug);
329 341
330 param[0] = 0x00; 342 ret = btintel_set_event_mask(hdev, debug);
331 param[1] = 0x00;
332 343
333 skb = __hci_cmd_sync(hdev, 0xfc11, 2, param, HCI_INIT_TIMEOUT); 344 err = btintel_exit_mfg(hdev, false, false);
334 if (IS_ERR(skb)) { 345 if (err)
335 err = PTR_ERR(skb); 346 return err;
336 BT_ERR("%s: Leaving Intel manufacturer mode failed (%d)",
337 hdev->name, err);
338 return PTR_ERR(skb);
339 }
340 kfree_skb(skb);
341 347
342 return err; 348 return ret;
343} 349}
344EXPORT_SYMBOL_GPL(btintel_set_event_mask_mfg); 350EXPORT_SYMBOL_GPL(btintel_set_event_mask_mfg);
345 351
diff --git a/drivers/bluetooth/btintel.h b/drivers/bluetooth/btintel.h
index 07e58e05a7fa..fa72eaec3461 100644
--- a/drivers/bluetooth/btintel.h
+++ b/drivers/bluetooth/btintel.h
@@ -72,6 +72,8 @@ struct intel_secure_send_result {
72#if IS_ENABLED(CONFIG_BT_INTEL) 72#if IS_ENABLED(CONFIG_BT_INTEL)
73 73
74int btintel_check_bdaddr(struct hci_dev *hdev); 74int btintel_check_bdaddr(struct hci_dev *hdev);
75int btintel_enter_mfg(struct hci_dev *hdev);
76int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched);
75int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr); 77int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
76int btintel_set_diag(struct hci_dev *hdev, bool enable); 78int btintel_set_diag(struct hci_dev *hdev, bool enable);
77int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable); 79int btintel_set_diag_mfg(struct hci_dev *hdev, bool enable);
@@ -94,6 +96,16 @@ static inline int btintel_check_bdaddr(struct hci_dev *hdev)
94 return -EOPNOTSUPP; 96 return -EOPNOTSUPP;
95} 97}
96 98
99static inline int btintel_enter_mfg(struct hci_dev *hdev)
100{
101 return -EOPNOTSUPP;
102}
103
104static inline int btintel_exit_mfg(struct hci_dev *hdev, bool reset, bool patched)
105{
106 return -EOPNOTSUPP;
107}
108
97static inline int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr) 109static inline int btintel_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
98{ 110{
99 return -EOPNOTSUPP; 111 return -EOPNOTSUPP;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 25beb3a28eee..6e141cdb98a4 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -1646,14 +1646,9 @@ static int btusb_setup_intel(struct hci_dev *hdev)
1646 struct sk_buff *skb; 1646 struct sk_buff *skb;
1647 const struct firmware *fw; 1647 const struct firmware *fw;
1648 const u8 *fw_ptr; 1648 const u8 *fw_ptr;
1649 int disable_patch; 1649 int disable_patch, err;
1650 struct intel_version *ver; 1650 struct intel_version *ver;
1651 1651
1652 const u8 mfg_enable[] = { 0x01, 0x00 };
1653 const u8 mfg_disable[] = { 0x00, 0x00 };
1654 const u8 mfg_reset_deactivate[] = { 0x00, 0x01 };
1655 const u8 mfg_reset_activate[] = { 0x00, 0x02 };
1656
1657 BT_DBG("%s", hdev->name); 1652 BT_DBG("%s", hdev->name);
1658 1653
1659 /* The controller has a bug with the first HCI command sent to it 1654 /* The controller has a bug with the first HCI command sent to it
@@ -1725,22 +1720,16 @@ static int btusb_setup_intel(struct hci_dev *hdev)
1725 1720
1726 kfree_skb(skb); 1721 kfree_skb(skb);
1727 1722
1728 /* This Intel specific command enables the manufacturer mode of the 1723 /* Enable the manufacturer mode of the controller.
1729 * controller.
1730 *
1731 * Only while this mode is enabled, the driver can download the 1724 * Only while this mode is enabled, the driver can download the
1732 * firmware patch data and configuration parameters. 1725 * firmware patch data and configuration parameters.
1733 */ 1726 */
1734 skb = __hci_cmd_sync(hdev, 0xfc11, 2, mfg_enable, HCI_INIT_TIMEOUT); 1727 err = btintel_enter_mfg(hdev);
1735 if (IS_ERR(skb)) { 1728 if (err) {
1736 BT_ERR("%s entering Intel manufacturer mode failed (%ld)",
1737 hdev->name, PTR_ERR(skb));
1738 release_firmware(fw); 1729 release_firmware(fw);
1739 return PTR_ERR(skb); 1730 return err;
1740 } 1731 }
1741 1732
1742 kfree_skb(skb);
1743
1744 disable_patch = 1; 1733 disable_patch = 1;
1745 1734
1746 /* The firmware data file consists of list of Intel specific HCI 1735 /* The firmware data file consists of list of Intel specific HCI
@@ -1780,14 +1769,9 @@ static int btusb_setup_intel(struct hci_dev *hdev)
1780 /* Patching completed successfully and disable the manufacturer mode 1769 /* Patching completed successfully and disable the manufacturer mode
1781 * with reset and activate the downloaded firmware patches. 1770 * with reset and activate the downloaded firmware patches.
1782 */ 1771 */
1783 skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_reset_activate), 1772 err = btintel_exit_mfg(hdev, true, true);
1784 mfg_reset_activate, HCI_INIT_TIMEOUT); 1773 if (err)
1785 if (IS_ERR(skb)) { 1774 return err;
1786 BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
1787 hdev->name, PTR_ERR(skb));
1788 return PTR_ERR(skb);
1789 }
1790 kfree_skb(skb);
1791 1775
1792 BT_INFO("%s: Intel Bluetooth firmware patch completed and activated", 1776 BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",
1793 hdev->name); 1777 hdev->name);
@@ -1796,14 +1780,9 @@ static int btusb_setup_intel(struct hci_dev *hdev)
1796 1780
1797exit_mfg_disable: 1781exit_mfg_disable:
1798 /* Disable the manufacturer mode without reset */ 1782 /* Disable the manufacturer mode without reset */
1799 skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_disable), mfg_disable, 1783 err = btintel_exit_mfg(hdev, false, false);
1800 HCI_INIT_TIMEOUT); 1784 if (err)
1801 if (IS_ERR(skb)) { 1785 return err;
1802 BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
1803 hdev->name, PTR_ERR(skb));
1804 return PTR_ERR(skb);
1805 }
1806 kfree_skb(skb);
1807 1786
1808 BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name); 1787 BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name);
1809 1788
@@ -1815,14 +1794,9 @@ exit_mfg_deactivate:
1815 /* Patching failed. Disable the manufacturer mode with reset and 1794 /* Patching failed. Disable the manufacturer mode with reset and
1816 * deactivate the downloaded firmware patches. 1795 * deactivate the downloaded firmware patches.
1817 */ 1796 */
1818 skb = __hci_cmd_sync(hdev, 0xfc11, sizeof(mfg_reset_deactivate), 1797 err = btintel_exit_mfg(hdev, true, false);
1819 mfg_reset_deactivate, HCI_INIT_TIMEOUT); 1798 if (err)
1820 if (IS_ERR(skb)) { 1799 return err;
1821 BT_ERR("%s exiting Intel manufacturer mode failed (%ld)",
1822 hdev->name, PTR_ERR(skb));
1823 return PTR_ERR(skb);
1824 }
1825 kfree_skb(skb);
1826 1800
1827 BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated", 1801 BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",
1828 hdev->name); 1802 hdev->name);