aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h2
-rw-r--r--net/bluetooth/hci_core.c24
-rw-r--r--net/bluetooth/hci_event.c19
-rw-r--r--net/bluetooth/mgmt.c67
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);
1286void mgmt_index_removed(struct hci_dev *hdev); 1286void mgmt_index_removed(struct hci_dev *hdev);
1287void mgmt_set_powered_failed(struct hci_dev *hdev, int err); 1287void mgmt_set_powered_failed(struct hci_dev *hdev, int err);
1288int mgmt_powered(struct hci_dev *hdev, u8 powered); 1288int mgmt_powered(struct hci_dev *hdev, u8 powered);
1289int mgmt_update_adv_data(struct hci_dev *hdev);
1289void mgmt_discoverable_timeout(struct hci_dev *hdev); 1290void mgmt_discoverable_timeout(struct hci_dev *hdev);
1290void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
1291void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); 1291void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
1292void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, 1292void 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
2658static void hci_update_scan_state(struct hci_dev *hdev, u8 scan) 2658static 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
2678int hci_dev_cmd(unsigned int cmd, void __user *arg) 2694int 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
336done: 327done:
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
909int 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
909static void create_eir(struct hci_dev *hdev, u8 *data) 919static 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
6034void 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
6071void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) 6052void 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);