| /* |
| * Copyright 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #pragma once |
| |
| #include <gtest/gtest_prod.h> |
| |
| #include <cstdint> |
| #include <list> |
| #include <optional> |
| #include <vector> |
| |
| #include "hci/address_with_type.h" |
| #include "hci/hci_packets.h" |
| |
| namespace bluetooth::hci { |
| |
| /// The LE Scanning reassembler is responsible for defragmenting |
| /// LE advertising reports that are too large to fit inside an HCI event |
| /// and were fragmented by the compiler. |
| /// The reassembler also joins scan response data with the |
| /// matching advertising data. |
| |
| class LeScanningReassembler { |
| public: |
| LeScanningReassembler(){}; |
| LeScanningReassembler(const LeScanningReassembler&) = delete; |
| LeScanningReassembler& operator=(const LeScanningReassembler&) = delete; |
| |
| /// Process an incoming advertsing report, extracted from any of the |
| /// HCI LE Advertising Report or the HCI LE Extended Advertising Report |
| /// events. |
| /// Returns the completed advertising data if the event was complete, or the |
| /// completion of a fragmented advertising event. |
| std::optional<std::vector<uint8_t>> ProcessAdvertisingReport( |
| uint16_t event_type, |
| uint8_t address_type, |
| Address address, |
| uint8_t advertising_sid, |
| const std::vector<uint8_t>& advertising_data); |
| |
| /// Configure the scan response filter. |
| /// If true all scan responses are ignored. |
| void SetIgnoreScanResponses(bool ignore_scan_responses) { |
| ignore_scan_responses_ = ignore_scan_responses; |
| } |
| |
| private: |
| /// Determine if scan responses should be processed or ignored. |
| bool ignore_scan_responses_{false}; |
| |
| /// Constants for parsing event_type. |
| static constexpr uint8_t kScannableBit = 1; |
| static constexpr uint8_t kDirectedBit = 2; |
| static constexpr uint8_t kScanResponseBit = 3; |
| static constexpr uint8_t kLegacyBit = 4; |
| static constexpr uint8_t kDataStatusBits = 5; |
| |
| /// Packs the information necessary to disambiguate advertising events: |
| /// - For legacy advertising events, the advertising address and |
| /// advertising address type are used to disambiguate advertisers. |
| /// - For extended advertising events, the SID is optionally used to |
| /// differentiate between advertising sets of the same advertiser. |
| /// The advertiser can also be anonymous in which case |
| /// the address is not provided. In this case, and when the SID |
| /// is missing, we trust the controller to send fragments of the same |
| /// advertisement together and not interleaved with that of other |
| /// advertisers. |
| struct AdvertisingKey { |
| std::optional<AddressWithType> address; |
| std::optional<uint8_t> sid; |
| |
| AdvertisingKey(Address address, DirectAdvertisingAddressType address_type, uint8_t sid); |
| bool operator==(const AdvertisingKey& other); |
| }; |
| |
| /// Packs incomplete advertising data. |
| struct AdvertisingFragment { |
| AdvertisingKey key; |
| std::vector<uint8_t> data; |
| |
| AdvertisingFragment(const AdvertisingKey& key, const std::vector<uint8_t>& data) |
| : key(key), data(data.begin(), data.end()) {} |
| }; |
| |
| /// Advertising cache for de-fragmenting extended advertising reports, |
| /// and joining advertising reports with the matching scan response when |
| /// applicable. |
| /// The cached advertising data is removed as soon as the complete |
| /// advertisement is got (including the scan response). |
| static constexpr size_t kMaximumCacheSize = 16; |
| std::list<AdvertisingFragment> cache_; |
| |
| /// Advertising cache management methods. |
| std::list<AdvertisingFragment>::iterator AppendFragment( |
| const AdvertisingKey& key, const std::vector<uint8_t>& data); |
| void RemoveFragment(const AdvertisingKey& key); |
| bool ContainsFragment(const AdvertisingKey& key); |
| std::list<AdvertisingFragment>::iterator FindFragment(const AdvertisingKey& key); |
| |
| /// Trim the advertising data by removing empty or overflowing |
| /// GAP Data entries. |
| static std::vector<uint8_t> TrimAdvertisingData(const std::vector<uint8_t>& advertising_data); |
| |
| FRIEND_TEST(LeScanningReassemblerTest, trim_advertising_data); |
| }; |
| |
| } // namespace bluetooth::hci |