diff options
-rw-r--r-- | include/net/bluetooth/hci_core.h | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 24 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 19 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 67 |
4 files changed, 50 insertions, 62 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 76675c55be15..b65efb22be54 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -1286,8 +1286,8 @@ void mgmt_index_added(struct hci_dev *hdev); | |||
1286 | void mgmt_index_removed(struct hci_dev *hdev); | 1286 | void mgmt_index_removed(struct hci_dev *hdev); |
1287 | void mgmt_set_powered_failed(struct hci_dev *hdev, int err); | 1287 | void mgmt_set_powered_failed(struct hci_dev *hdev, int err); |
1288 | int mgmt_powered(struct hci_dev *hdev, u8 powered); | 1288 | int mgmt_powered(struct hci_dev *hdev, u8 powered); |
1289 | int mgmt_update_adv_data(struct hci_dev *hdev); | ||
1289 | void mgmt_discoverable_timeout(struct hci_dev *hdev); | 1290 | void mgmt_discoverable_timeout(struct hci_dev *hdev); |
1290 | void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); | ||
1291 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); | 1291 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); |
1292 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | 1292 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, |
1293 | bool persistent); | 1293 | bool persistent); |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 27c40e4901a3..3321c65c73ac 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -2657,7 +2657,7 @@ done: | |||
2657 | 2657 | ||
2658 | static void hci_update_scan_state(struct hci_dev *hdev, u8 scan) | 2658 | static void hci_update_scan_state(struct hci_dev *hdev, u8 scan) |
2659 | { | 2659 | { |
2660 | bool conn_changed; | 2660 | bool conn_changed, discov_changed; |
2661 | 2661 | ||
2662 | BT_DBG("%s scan 0x%02x", hdev->name, scan); | 2662 | BT_DBG("%s scan 0x%02x", hdev->name, scan); |
2663 | 2663 | ||
@@ -2668,11 +2668,27 @@ static void hci_update_scan_state(struct hci_dev *hdev, u8 scan) | |||
2668 | conn_changed = test_and_clear_bit(HCI_CONNECTABLE, | 2668 | conn_changed = test_and_clear_bit(HCI_CONNECTABLE, |
2669 | &hdev->dev_flags); | 2669 | &hdev->dev_flags); |
2670 | 2670 | ||
2671 | if ((scan & SCAN_INQUIRY)) { | ||
2672 | discov_changed = !test_and_set_bit(HCI_DISCOVERABLE, | ||
2673 | &hdev->dev_flags); | ||
2674 | } else { | ||
2675 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
2676 | discov_changed = test_and_clear_bit(HCI_DISCOVERABLE, | ||
2677 | &hdev->dev_flags); | ||
2678 | } | ||
2679 | |||
2671 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 2680 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) |
2672 | return; | 2681 | return; |
2673 | 2682 | ||
2674 | if (conn_changed) | 2683 | if (conn_changed || discov_changed) { |
2684 | /* In case this was disabled through mgmt */ | ||
2685 | set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); | ||
2686 | |||
2687 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) | ||
2688 | mgmt_update_adv_data(hdev); | ||
2689 | |||
2675 | mgmt_new_settings(hdev); | 2690 | mgmt_new_settings(hdev); |
2691 | } | ||
2676 | } | 2692 | } |
2677 | 2693 | ||
2678 | int hci_dev_cmd(unsigned int cmd, void __user *arg) | 2694 | int hci_dev_cmd(unsigned int cmd, void __user *arg) |
@@ -2736,8 +2752,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
2736 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, | 2752 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, |
2737 | HCI_INIT_TIMEOUT); | 2753 | HCI_INIT_TIMEOUT); |
2738 | 2754 | ||
2739 | /* Ensure that the connectable state gets correctly | 2755 | /* Ensure that the connectable and discoverable states |
2740 | * modified as this was a non-mgmt change. | 2756 | * get correctly modified as this was a non-mgmt change. |
2741 | */ | 2757 | */ |
2742 | if (!err) | 2758 | if (!err) |
2743 | hci_update_scan_state(hdev, dr.dev_opt); | 2759 | hci_update_scan_state(hdev, dr.dev_opt); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 38a0e457eaf9..760bbd88f3c5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -296,7 +296,6 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
296 | { | 296 | { |
297 | __u8 status = *((__u8 *) skb->data); | 297 | __u8 status = *((__u8 *) skb->data); |
298 | __u8 param; | 298 | __u8 param; |
299 | int old_pscan, old_iscan; | ||
300 | void *sent; | 299 | void *sent; |
301 | 300 | ||
302 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 301 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
@@ -315,23 +314,15 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
315 | goto done; | 314 | goto done; |
316 | } | 315 | } |
317 | 316 | ||
318 | /* We need to ensure that we set this back on if someone changed | 317 | if (param & SCAN_INQUIRY) |
319 | * the scan mode through a raw HCI socket. | ||
320 | */ | ||
321 | set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); | ||
322 | |||
323 | old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); | ||
324 | old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); | ||
325 | |||
326 | if (param & SCAN_INQUIRY) { | ||
327 | set_bit(HCI_ISCAN, &hdev->flags); | 318 | set_bit(HCI_ISCAN, &hdev->flags); |
328 | if (!old_iscan) | 319 | else |
329 | mgmt_discoverable(hdev, 1); | 320 | clear_bit(HCI_ISCAN, &hdev->flags); |
330 | } else if (old_iscan) | ||
331 | mgmt_discoverable(hdev, 0); | ||
332 | 321 | ||
333 | if (param & SCAN_PAGE) | 322 | if (param & SCAN_PAGE) |
334 | set_bit(HCI_PSCAN, &hdev->flags); | 323 | set_bit(HCI_PSCAN, &hdev->flags); |
324 | else | ||
325 | clear_bit(HCI_ISCAN, &hdev->flags); | ||
335 | 326 | ||
336 | done: | 327 | done: |
337 | hci_dev_unlock(hdev); | 328 | hci_dev_unlock(hdev); |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 9f9f11c8488b..1dad7bffc6af 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -906,6 +906,16 @@ static void update_adv_data(struct hci_request *req) | |||
906 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | 906 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); |
907 | } | 907 | } |
908 | 908 | ||
909 | int mgmt_update_adv_data(struct hci_dev *hdev) | ||
910 | { | ||
911 | struct hci_request req; | ||
912 | |||
913 | hci_req_init(&req, hdev); | ||
914 | update_adv_data(&req); | ||
915 | |||
916 | return hci_req_run(&req, NULL); | ||
917 | } | ||
918 | |||
909 | static void create_eir(struct hci_dev *hdev, u8 *data) | 919 | static void create_eir(struct hci_dev *hdev, u8 *data) |
910 | { | 920 | { |
911 | u8 *ptr = data; | 921 | u8 *ptr = data; |
@@ -1743,7 +1753,7 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) | |||
1743 | { | 1753 | { |
1744 | struct pending_cmd *cmd; | 1754 | struct pending_cmd *cmd; |
1745 | struct mgmt_mode *cp; | 1755 | struct mgmt_mode *cp; |
1746 | bool changed; | 1756 | bool conn_changed, discov_changed; |
1747 | 1757 | ||
1748 | BT_DBG("status 0x%02x", status); | 1758 | BT_DBG("status 0x%02x", status); |
1749 | 1759 | ||
@@ -1760,15 +1770,23 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) | |||
1760 | } | 1770 | } |
1761 | 1771 | ||
1762 | cp = cmd->param; | 1772 | cp = cmd->param; |
1763 | if (cp->val) | 1773 | if (cp->val) { |
1764 | changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); | 1774 | conn_changed = !test_and_set_bit(HCI_CONNECTABLE, |
1765 | else | 1775 | &hdev->dev_flags); |
1766 | changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); | 1776 | discov_changed = false; |
1777 | } else { | ||
1778 | conn_changed = test_and_clear_bit(HCI_CONNECTABLE, | ||
1779 | &hdev->dev_flags); | ||
1780 | discov_changed = test_and_clear_bit(HCI_DISCOVERABLE, | ||
1781 | &hdev->dev_flags); | ||
1782 | } | ||
1767 | 1783 | ||
1768 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); | 1784 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); |
1769 | 1785 | ||
1770 | if (changed) { | 1786 | if (conn_changed || discov_changed) { |
1771 | new_settings(hdev, cmd->sk); | 1787 | new_settings(hdev, cmd->sk); |
1788 | if (discov_changed) | ||
1789 | mgmt_update_adv_data(hdev); | ||
1772 | hci_update_background_scan(hdev); | 1790 | hci_update_background_scan(hdev); |
1773 | } | 1791 | } |
1774 | 1792 | ||
@@ -6031,43 +6049,6 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev) | |||
6031 | hci_dev_unlock(hdev); | 6049 | hci_dev_unlock(hdev); |
6032 | } | 6050 | } |
6033 | 6051 | ||
6034 | void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | ||
6035 | { | ||
6036 | bool changed; | ||
6037 | |||
6038 | /* Nothing needed here if there's a pending command since that | ||
6039 | * commands request completion callback takes care of everything | ||
6040 | * necessary. | ||
6041 | */ | ||
6042 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) | ||
6043 | return; | ||
6044 | |||
6045 | /* Powering off may clear the scan mode - don't let that interfere */ | ||
6046 | if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) | ||
6047 | return; | ||
6048 | |||
6049 | if (discoverable) { | ||
6050 | changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | ||
6051 | } else { | ||
6052 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
6053 | changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | ||
6054 | } | ||
6055 | |||
6056 | if (changed) { | ||
6057 | struct hci_request req; | ||
6058 | |||
6059 | /* In case this change in discoverable was triggered by | ||
6060 | * a disabling of connectable there could be a need to | ||
6061 | * update the advertising flags. | ||
6062 | */ | ||
6063 | hci_req_init(&req, hdev); | ||
6064 | update_adv_data(&req); | ||
6065 | hci_req_run(&req, NULL); | ||
6066 | |||
6067 | new_settings(hdev, NULL); | ||
6068 | } | ||
6069 | } | ||
6070 | |||
6071 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) | 6052 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) |
6072 | { | 6053 | { |
6073 | u8 mgmt_err = mgmt_status(status); | 6054 | u8 mgmt_err = mgmt_status(status); |