diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2015-11-11 01:11:19 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2015-11-19 11:50:29 -0500 |
commit | 4ebeee2dff9815619be6ff9a845d33716f48468c (patch) | |
tree | d8ba8497c1a04a6566f27426ba14bf95c4eb5cb9 | |
parent | 51d7a94d56f842a6bd752c11de2f80f2cbc4a507 (diff) |
Bluetooth: Add HCI status return parameter to hci_req_sync()
In some cases it may be important to get the exact HCI status rather
than the converted HCI-to-errno value. Add an optional return
parameter to the hci_req_sync() API to allow for this. Since there are
no good HCI translation candidates for cancelation and timeout, use
the "unknown" status code for those cases.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r-- | include/net/bluetooth/hci.h | 3 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 26 | ||||
-rw-r--r-- | net/bluetooth/hci_request.c | 12 | ||||
-rw-r--r-- | net/bluetooth/hci_request.h | 4 |
4 files changed, 26 insertions, 19 deletions
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 0205b80cc90b..cc2216727655 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -452,7 +452,8 @@ enum { | |||
452 | #define HCI_ERROR_REMOTE_POWER_OFF 0x15 | 452 | #define HCI_ERROR_REMOTE_POWER_OFF 0x15 |
453 | #define HCI_ERROR_LOCAL_HOST_TERM 0x16 | 453 | #define HCI_ERROR_LOCAL_HOST_TERM 0x16 |
454 | #define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18 | 454 | #define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18 |
455 | #define HCI_ERROR_INVALID_LL_PARAMS 0x1E | 455 | #define HCI_ERROR_INVALID_LL_PARAMS 0x1e |
456 | #define HCI_ERROR_UNSPECIFIED 0x1f | ||
456 | #define HCI_ERROR_ADVERTISING_TIMEOUT 0x3c | 457 | #define HCI_ERROR_ADVERTISING_TIMEOUT 0x3c |
457 | 458 | ||
458 | /* Flow control modes */ | 459 | /* Flow control modes */ |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 965bc01a0d91..029d7798cffa 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -768,14 +768,14 @@ static int __hci_init(struct hci_dev *hdev) | |||
768 | { | 768 | { |
769 | int err; | 769 | int err; |
770 | 770 | ||
771 | err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT); | 771 | err = __hci_req_sync(hdev, hci_init1_req, 0, HCI_INIT_TIMEOUT, NULL); |
772 | if (err < 0) | 772 | if (err < 0) |
773 | return err; | 773 | return err; |
774 | 774 | ||
775 | if (hci_dev_test_flag(hdev, HCI_SETUP)) | 775 | if (hci_dev_test_flag(hdev, HCI_SETUP)) |
776 | hci_debugfs_create_basic(hdev); | 776 | hci_debugfs_create_basic(hdev); |
777 | 777 | ||
778 | err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT); | 778 | err = __hci_req_sync(hdev, hci_init2_req, 0, HCI_INIT_TIMEOUT, NULL); |
779 | if (err < 0) | 779 | if (err < 0) |
780 | return err; | 780 | return err; |
781 | 781 | ||
@@ -786,11 +786,11 @@ static int __hci_init(struct hci_dev *hdev) | |||
786 | if (hdev->dev_type != HCI_BREDR) | 786 | if (hdev->dev_type != HCI_BREDR) |
787 | return 0; | 787 | return 0; |
788 | 788 | ||
789 | err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT); | 789 | err = __hci_req_sync(hdev, hci_init3_req, 0, HCI_INIT_TIMEOUT, NULL); |
790 | if (err < 0) | 790 | if (err < 0) |
791 | return err; | 791 | return err; |
792 | 792 | ||
793 | err = __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT); | 793 | err = __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT, NULL); |
794 | if (err < 0) | 794 | if (err < 0) |
795 | return err; | 795 | return err; |
796 | 796 | ||
@@ -846,7 +846,7 @@ static int __hci_unconf_init(struct hci_dev *hdev) | |||
846 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) | 846 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) |
847 | return 0; | 847 | return 0; |
848 | 848 | ||
849 | err = __hci_req_sync(hdev, hci_init0_req, 0, HCI_INIT_TIMEOUT); | 849 | err = __hci_req_sync(hdev, hci_init0_req, 0, HCI_INIT_TIMEOUT, NULL); |
850 | if (err < 0) | 850 | if (err < 0) |
851 | return err; | 851 | return err; |
852 | 852 | ||
@@ -1204,7 +1204,7 @@ int hci_inquiry(void __user *arg) | |||
1204 | 1204 | ||
1205 | if (do_inquiry) { | 1205 | if (do_inquiry) { |
1206 | err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir, | 1206 | err = hci_req_sync(hdev, hci_inq_req, (unsigned long) &ir, |
1207 | timeo); | 1207 | timeo, NULL); |
1208 | if (err < 0) | 1208 | if (err < 0) |
1209 | goto done; | 1209 | goto done; |
1210 | 1210 | ||
@@ -1570,7 +1570,7 @@ int hci_dev_do_close(struct hci_dev *hdev) | |||
1570 | if (test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks) && | 1570 | if (test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks) && |
1571 | !auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { | 1571 | !auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) { |
1572 | set_bit(HCI_INIT, &hdev->flags); | 1572 | set_bit(HCI_INIT, &hdev->flags); |
1573 | __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); | 1573 | __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT, NULL); |
1574 | clear_bit(HCI_INIT, &hdev->flags); | 1574 | clear_bit(HCI_INIT, &hdev->flags); |
1575 | } | 1575 | } |
1576 | 1576 | ||
@@ -1667,7 +1667,7 @@ static int hci_dev_do_reset(struct hci_dev *hdev) | |||
1667 | atomic_set(&hdev->cmd_cnt, 1); | 1667 | atomic_set(&hdev->cmd_cnt, 1); |
1668 | hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; | 1668 | hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; |
1669 | 1669 | ||
1670 | ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); | 1670 | ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT, NULL); |
1671 | 1671 | ||
1672 | hci_req_sync_unlock(hdev); | 1672 | hci_req_sync_unlock(hdev); |
1673 | return ret; | 1673 | return ret; |
@@ -1802,7 +1802,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
1802 | switch (cmd) { | 1802 | switch (cmd) { |
1803 | case HCISETAUTH: | 1803 | case HCISETAUTH: |
1804 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, | 1804 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, |
1805 | HCI_INIT_TIMEOUT); | 1805 | HCI_INIT_TIMEOUT, NULL); |
1806 | break; | 1806 | break; |
1807 | 1807 | ||
1808 | case HCISETENCRYPT: | 1808 | case HCISETENCRYPT: |
@@ -1814,18 +1814,18 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
1814 | if (!test_bit(HCI_AUTH, &hdev->flags)) { | 1814 | if (!test_bit(HCI_AUTH, &hdev->flags)) { |
1815 | /* Auth must be enabled first */ | 1815 | /* Auth must be enabled first */ |
1816 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, | 1816 | err = hci_req_sync(hdev, hci_auth_req, dr.dev_opt, |
1817 | HCI_INIT_TIMEOUT); | 1817 | HCI_INIT_TIMEOUT, NULL); |
1818 | if (err) | 1818 | if (err) |
1819 | break; | 1819 | break; |
1820 | } | 1820 | } |
1821 | 1821 | ||
1822 | err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt, | 1822 | err = hci_req_sync(hdev, hci_encrypt_req, dr.dev_opt, |
1823 | HCI_INIT_TIMEOUT); | 1823 | HCI_INIT_TIMEOUT, NULL); |
1824 | break; | 1824 | break; |
1825 | 1825 | ||
1826 | case HCISETSCAN: | 1826 | case HCISETSCAN: |
1827 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, | 1827 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, |
1828 | HCI_INIT_TIMEOUT); | 1828 | HCI_INIT_TIMEOUT, NULL); |
1829 | 1829 | ||
1830 | /* Ensure that the connectable and discoverable states | 1830 | /* Ensure that the connectable and discoverable states |
1831 | * get correctly modified as this was a non-mgmt change. | 1831 | * get correctly modified as this was a non-mgmt change. |
@@ -1836,7 +1836,7 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
1836 | 1836 | ||
1837 | case HCISETLINKPOL: | 1837 | case HCISETLINKPOL: |
1838 | err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt, | 1838 | err = hci_req_sync(hdev, hci_linkpol_req, dr.dev_opt, |
1839 | HCI_INIT_TIMEOUT); | 1839 | HCI_INIT_TIMEOUT, NULL); |
1840 | break; | 1840 | break; |
1841 | 1841 | ||
1842 | case HCISETLINKMODE: | 1842 | case HCISETLINKMODE: |
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 0adbb59ec2f0..b1d4d5bba7c1 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c | |||
@@ -186,7 +186,7 @@ EXPORT_SYMBOL(__hci_cmd_sync); | |||
186 | /* Execute request and wait for completion. */ | 186 | /* Execute request and wait for completion. */ |
187 | int __hci_req_sync(struct hci_dev *hdev, void (*func)(struct hci_request *req, | 187 | int __hci_req_sync(struct hci_dev *hdev, void (*func)(struct hci_request *req, |
188 | unsigned long opt), | 188 | unsigned long opt), |
189 | unsigned long opt, __u32 timeout) | 189 | unsigned long opt, u32 timeout, u8 *hci_status) |
190 | { | 190 | { |
191 | struct hci_request req; | 191 | struct hci_request req; |
192 | DECLARE_WAITQUEUE(wait, current); | 192 | DECLARE_WAITQUEUE(wait, current); |
@@ -231,14 +231,20 @@ int __hci_req_sync(struct hci_dev *hdev, void (*func)(struct hci_request *req, | |||
231 | switch (hdev->req_status) { | 231 | switch (hdev->req_status) { |
232 | case HCI_REQ_DONE: | 232 | case HCI_REQ_DONE: |
233 | err = -bt_to_errno(hdev->req_result); | 233 | err = -bt_to_errno(hdev->req_result); |
234 | if (hci_status) | ||
235 | *hci_status = hdev->req_result; | ||
234 | break; | 236 | break; |
235 | 237 | ||
236 | case HCI_REQ_CANCELED: | 238 | case HCI_REQ_CANCELED: |
237 | err = -hdev->req_result; | 239 | err = -hdev->req_result; |
240 | if (hci_status) | ||
241 | *hci_status = HCI_ERROR_UNSPECIFIED; | ||
238 | break; | 242 | break; |
239 | 243 | ||
240 | default: | 244 | default: |
241 | err = -ETIMEDOUT; | 245 | err = -ETIMEDOUT; |
246 | if (hci_status) | ||
247 | *hci_status = HCI_ERROR_UNSPECIFIED; | ||
242 | break; | 248 | break; |
243 | } | 249 | } |
244 | 250 | ||
@@ -251,7 +257,7 @@ int __hci_req_sync(struct hci_dev *hdev, void (*func)(struct hci_request *req, | |||
251 | 257 | ||
252 | int hci_req_sync(struct hci_dev *hdev, void (*req)(struct hci_request *req, | 258 | int hci_req_sync(struct hci_dev *hdev, void (*req)(struct hci_request *req, |
253 | unsigned long opt), | 259 | unsigned long opt), |
254 | unsigned long opt, __u32 timeout) | 260 | unsigned long opt, u32 timeout, u8 *hci_status) |
255 | { | 261 | { |
256 | int ret; | 262 | int ret; |
257 | 263 | ||
@@ -260,7 +266,7 @@ int hci_req_sync(struct hci_dev *hdev, void (*req)(struct hci_request *req, | |||
260 | 266 | ||
261 | /* Serialize all requests */ | 267 | /* Serialize all requests */ |
262 | hci_req_sync_lock(hdev); | 268 | hci_req_sync_lock(hdev); |
263 | ret = __hci_req_sync(hdev, req, opt, timeout); | 269 | ret = __hci_req_sync(hdev, req, opt, timeout, hci_status); |
264 | hci_req_sync_unlock(hdev); | 270 | hci_req_sync_unlock(hdev); |
265 | 271 | ||
266 | return ret; | 272 | return ret; |
diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h index 983e687fee22..8441d12a62dd 100644 --- a/net/bluetooth/hci_request.h +++ b/net/bluetooth/hci_request.h | |||
@@ -46,10 +46,10 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status, | |||
46 | 46 | ||
47 | int hci_req_sync(struct hci_dev *hdev, void (*req)(struct hci_request *req, | 47 | int hci_req_sync(struct hci_dev *hdev, void (*req)(struct hci_request *req, |
48 | unsigned long opt), | 48 | unsigned long opt), |
49 | unsigned long opt, __u32 timeout); | 49 | unsigned long opt, u32 timeout, u8 *hci_status); |
50 | int __hci_req_sync(struct hci_dev *hdev, void (*func)(struct hci_request *req, | 50 | int __hci_req_sync(struct hci_dev *hdev, void (*func)(struct hci_request *req, |
51 | unsigned long opt), | 51 | unsigned long opt), |
52 | unsigned long opt, __u32 timeout); | 52 | unsigned long opt, u32 timeout, u8 *hci_status); |
53 | void hci_req_sync_cancel(struct hci_dev *hdev, int err); | 53 | void hci_req_sync_cancel(struct hci_dev *hdev, int err); |
54 | 54 | ||
55 | struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, | 55 | struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, |