aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Pawlowski <jpawlowski@google.com>2015-03-17 12:04:14 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2015-03-17 12:31:00 -0400
commit07d2334ae747772fc4426077340aa3efe499f50b (patch)
treea6d218d89270d7713d418ce44034691f101142b5
parent812abb13a97b7049c883ffb8431b81eb404a0938 (diff)
Bluetooth: Add simultaneous dual mode scan
When doing scan through mgmt api, some controllers can do both le and classic scan at same time. They can be distinguished by HCI_QUIRK_SIMULTANEOUS_DISCOVERY set. This patch enables them to use this feature when doing dual mode scan. Instead of doing le, then classic scan, both scans are run at once. Signed-off-by: Jakub Pawlowski <jpawlowski@google.com> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
-rw-r--r--net/bluetooth/hci_core.c24
-rw-r--r--net/bluetooth/hci_event.c22
-rw-r--r--net/bluetooth/mgmt.c34
3 files changed, 70 insertions, 10 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 750d3445f2d2..773f2164d9a1 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2902,12 +2902,26 @@ static void le_scan_disable_work_complete(struct hci_dev *hdev, u8 status,
2902 2902
2903 hci_dev_lock(hdev); 2903 hci_dev_lock(hdev);
2904 2904
2905 hci_inquiry_cache_flush(hdev); 2905 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
2906 &hdev->quirks)) {
2907 /* If we were running LE only scan, change discovery
2908 * state. If we were running both LE and BR/EDR inquiry
2909 * simultaneously, and BR/EDR inquiry is already
2910 * finished, stop discovery, otherwise BR/EDR inquiry
2911 * will stop discovery when finished.
2912 */
2913 if (!test_bit(HCI_INQUIRY, &hdev->flags))
2914 hci_discovery_set_state(hdev,
2915 DISCOVERY_STOPPED);
2916 } else {
2917 hci_inquiry_cache_flush(hdev);
2906 2918
2907 err = hci_req_run(&req, inquiry_complete); 2919 err = hci_req_run(&req, inquiry_complete);
2908 if (err) { 2920 if (err) {
2909 BT_ERR("Inquiry request failed: err %d", err); 2921 BT_ERR("Inquiry request failed: err %d", err);
2910 hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 2922 hci_discovery_set_state(hdev,
2923 DISCOVERY_STOPPED);
2924 }
2911 } 2925 }
2912 2926
2913 hci_dev_unlock(hdev); 2927 hci_dev_unlock(hdev);
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index d800f0c5aa21..62f92a508961 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2126,7 +2126,16 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2126 goto unlock; 2126 goto unlock;
2127 2127
2128 if (list_empty(&discov->resolve)) { 2128 if (list_empty(&discov->resolve)) {
2129 hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 2129 /* When BR/EDR inquiry is active and no LE scanning is in
2130 * progress, then change discovery state to indicate completion.
2131 *
2132 * When running LE scanning and BR/EDR inquiry simultaneously
2133 * and the LE scan already finished, then change the discovery
2134 * state to indicate completion.
2135 */
2136 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
2137 !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
2138 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
2130 goto unlock; 2139 goto unlock;
2131 } 2140 }
2132 2141
@@ -2135,7 +2144,16 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2135 e->name_state = NAME_PENDING; 2144 e->name_state = NAME_PENDING;
2136 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING); 2145 hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
2137 } else { 2146 } else {
2138 hci_discovery_set_state(hdev, DISCOVERY_STOPPED); 2147 /* When BR/EDR inquiry is active and no LE scanning is in
2148 * progress, then change discovery state to indicate completion.
2149 *
2150 * When running LE scanning and BR/EDR inquiry simultaneously
2151 * and the LE scan already finished, then change the discovery
2152 * state to indicate completion.
2153 */
2154 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
2155 !test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
2156 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
2139 } 2157 }
2140 2158
2141unlock: 2159unlock:
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 5a4b9d5a224f..7bcdf61afe11 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1408,9 +1408,10 @@ static bool hci_stop_discovery(struct hci_request *req)
1408 1408
1409 switch (hdev->discovery.state) { 1409 switch (hdev->discovery.state) {
1410 case DISCOVERY_FINDING: 1410 case DISCOVERY_FINDING:
1411 if (test_bit(HCI_INQUIRY, &hdev->flags)) { 1411 if (test_bit(HCI_INQUIRY, &hdev->flags))
1412 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL); 1412 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1413 } else { 1413
1414 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
1414 cancel_delayed_work(&hdev->le_scan_disable); 1415 cancel_delayed_work(&hdev->le_scan_disable);
1415 hci_req_add_le_scan_disable(req); 1416 hci_req_add_le_scan_disable(req);
1416 } 1417 }
@@ -4019,6 +4020,22 @@ static bool trigger_discovery(struct hci_request *req, u8 *status)
4019 break; 4020 break;
4020 4021
4021 case DISCOV_TYPE_INTERLEAVED: 4022 case DISCOV_TYPE_INTERLEAVED:
4023 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY,
4024 &hdev->quirks)) {
4025 /* During simultaneous discovery, we double LE scan
4026 * interval. We must leave some time for the controller
4027 * to do BR/EDR inquiry.
4028 */
4029 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT * 2,
4030 status))
4031 return false;
4032
4033 if (!trigger_bredr_inquiry(req, status))
4034 return false;
4035
4036 return true;
4037 }
4038
4022 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) { 4039 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
4023 *status = MGMT_STATUS_NOT_SUPPORTED; 4040 *status = MGMT_STATUS_NOT_SUPPORTED;
4024 return false; 4041 return false;
@@ -4072,7 +4089,18 @@ static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4072 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT); 4089 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4073 break; 4090 break;
4074 case DISCOV_TYPE_INTERLEAVED: 4091 case DISCOV_TYPE_INTERLEAVED:
4075 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout); 4092 /* When running simultaneous discovery, the LE scanning time
4093 * should occupy the whole discovery time sine BR/EDR inquiry
4094 * and LE scanning are scheduled by the controller.
4095 *
4096 * For interleaving discovery in comparison, BR/EDR inquiry
4097 * and LE scanning are done sequentially with separate
4098 * timeouts.
4099 */
4100 if (test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
4101 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
4102 else
4103 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
4076 break; 4104 break;
4077 case DISCOV_TYPE_BREDR: 4105 case DISCOV_TYPE_BREDR:
4078 timeout = 0; 4106 timeout = 0;