aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/bluetooth/hci_core.h1
-rw-r--r--net/bluetooth/mgmt.c53
2 files changed, 49 insertions, 5 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index d3a232be9d9b..52863c3e0b13 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1334,6 +1334,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event);
1334#define DISCOV_INTERLEAVED_TIMEOUT 5120 /* msec */ 1334#define DISCOV_INTERLEAVED_TIMEOUT 5120 /* msec */
1335#define DISCOV_INTERLEAVED_INQUIRY_LEN 0x04 1335#define DISCOV_INTERLEAVED_INQUIRY_LEN 0x04
1336#define DISCOV_BREDR_INQUIRY_LEN 0x08 1336#define DISCOV_BREDR_INQUIRY_LEN 0x08
1337#define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */
1337 1338
1338int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); 1339int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
1339int mgmt_new_settings(struct hci_dev *hdev); 1340int mgmt_new_settings(struct hci_dev *hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8c2520a7f386..9e50b5c09b02 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -7262,6 +7262,21 @@ static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7262 return false; 7262 return false;
7263} 7263}
7264 7264
7265static void restart_le_scan(struct hci_dev *hdev)
7266{
7267 /* If controller is not scanning we are done. */
7268 if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags))
7269 return;
7270
7271 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7272 hdev->discovery.scan_start +
7273 hdev->discovery.scan_duration))
7274 return;
7275
7276 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7277 DISCOV_LE_RESTART_DELAY);
7278}
7279
7265void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, 7280void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7266 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags, 7281 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7267 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len) 7282 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
@@ -7284,14 +7299,18 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7284 7299
7285 /* When using service discovery with a RSSI threshold, then check 7300 /* When using service discovery with a RSSI threshold, then check
7286 * if such a RSSI threshold is specified. If a RSSI threshold has 7301 * if such a RSSI threshold is specified. If a RSSI threshold has
7287 * been specified, then all results with a RSSI smaller than the 7302 * been specified, and HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set,
7288 * RSSI threshold will be dropped. 7303 * then all results with a RSSI smaller than the RSSI threshold will be
7304 * dropped. If the quirk is set, let it through for further processing,
7305 * as we might need to restart the scan.
7289 * 7306 *
7290 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry, 7307 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7291 * the results are also dropped. 7308 * the results are also dropped.
7292 */ 7309 */
7293 if (hdev->discovery.rssi != HCI_RSSI_INVALID && 7310 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7294 (rssi < hdev->discovery.rssi || rssi == HCI_RSSI_INVALID)) 7311 (rssi == HCI_RSSI_INVALID ||
7312 (rssi < hdev->discovery.rssi &&
7313 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7295 return; 7314 return;
7296 7315
7297 /* Make sure that the buffer is big enough. The 5 extra bytes 7316 /* Make sure that the buffer is big enough. The 5 extra bytes
@@ -7326,12 +7345,20 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7326 * kept and checking possible scan response data 7345 * kept and checking possible scan response data
7327 * will be skipped. 7346 * will be skipped.
7328 */ 7347 */
7329 if (hdev->discovery.uuid_count > 0) 7348 if (hdev->discovery.uuid_count > 0) {
7330 match = eir_has_uuids(eir, eir_len, 7349 match = eir_has_uuids(eir, eir_len,
7331 hdev->discovery.uuid_count, 7350 hdev->discovery.uuid_count,
7332 hdev->discovery.uuids); 7351 hdev->discovery.uuids);
7333 else 7352 /* If duplicate filtering does not report RSSI changes,
7353 * then restart scanning to ensure updated result with
7354 * updated RSSI values.
7355 */
7356 if (match && test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
7357 &hdev->quirks))
7358 restart_le_scan(hdev);
7359 } else {
7334 match = true; 7360 match = true;
7361 }
7335 7362
7336 if (!match && !scan_rsp_len) 7363 if (!match && !scan_rsp_len)
7337 return; 7364 return;
@@ -7364,6 +7391,14 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7364 hdev->discovery.uuid_count, 7391 hdev->discovery.uuid_count,
7365 hdev->discovery.uuids)) 7392 hdev->discovery.uuids))
7366 return; 7393 return;
7394
7395 /* If duplicate filtering does not report RSSI changes,
7396 * then restart scanning to ensure updated result with
7397 * updated RSSI values.
7398 */
7399 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
7400 &hdev->quirks))
7401 restart_le_scan(hdev);
7367 } 7402 }
7368 7403
7369 /* Append scan response data to event */ 7404 /* Append scan response data to event */
@@ -7377,6 +7412,14 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7377 return; 7412 return;
7378 } 7413 }
7379 7414
7415 /* Validate the reported RSSI value against the RSSI threshold once more
7416 * incase HCI_QUIRK_STRICT_DUPLICATE_FILTER forced a restart of LE
7417 * scanning.
7418 */
7419 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7420 rssi < hdev->discovery.rssi)
7421 return;
7422
7380 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len); 7423 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7381 ev_size = sizeof(*ev) + eir_len + scan_rsp_len; 7424 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
7382 7425