diff options
| -rw-r--r-- | include/net/bluetooth/hci_core.h | 1 | ||||
| -rw-r--r-- | net/bluetooth/mgmt.c | 53 |
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 | ||
| 1338 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); | 1339 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); |
| 1339 | int mgmt_new_settings(struct hci_dev *hdev); | 1340 | int 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 | ||
| 7265 | static 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 | |||
| 7265 | void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 7280 | void 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 | ||
