/* * 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 #include #include #include #include #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 controller. /// The reassembler also joins scan response data with the /// matching advertising data. class LeScanningReassembler { public: struct CompleteAdvertisingData { uint16_t extended_event_type; std::vector data; }; 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 ProcessAdvertisingReport( uint16_t event_type, uint8_t address_type, Address address, uint8_t advertising_sid, const std::vector& advertising_data); /// Process an incoming periodic advertising report, extracted from the /// HCI LE Periodic Advertising Report events. /// Returns the completed advertising data if the event was complete, /// or the completion of a fragmented advertising event. std::optional> ProcessPeriodicAdvertisingReport( uint16_t sync_handle, DataStatus status, const std::vector& 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 kConnectableBit = 0; 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 address; std::optional sid; AdvertisingKey(Address address, DirectAdvertisingAddressType address_type, uint8_t sid); bool operator==(const AdvertisingKey& other); }; /// Packs incomplete advertising data. struct AdvertisingFragment { AdvertisingKey key; uint16_t extended_event_type; std::vector data; AdvertisingFragment( const AdvertisingKey& key, uint16_t extended_event_type, const std::vector& data) : key(key), extended_event_type(extended_event_type), data(data.begin(), data.end()) {} }; /// Packs incomplete periodic advertising data. struct PeriodicAdvertisingFragment { std::optional sync_handle; std::vector data; PeriodicAdvertisingFragment(uint16_t sync_handle, const std::vector& data) : sync_handle(sync_handle), 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 cache_; /// Advertising cache management methods. std::list::iterator AppendFragment( const AdvertisingKey& key, uint16_t extended_event_type, const std::vector& data); void RemoveFragment(const AdvertisingKey& key); bool ContainsFragment(const AdvertisingKey& key); std::list::iterator FindFragment(const AdvertisingKey& key); /// Advertising cache for de-fragmenting periodic advertising reports. static constexpr size_t kMaximumPeriodicCacheSize = 16; std::list periodic_cache_; std::list::iterator AppendPeriodicFragment( uint16_t sync_handle, const std::vector& data); std::list::iterator FindPeriodicFragment(uint16_t sync_handle); /// Trim the advertising data by removing empty or overflowing /// GAP Data entries. static std::vector TrimAdvertisingData(const std::vector& advertising_data); FRIEND_TEST(LeScanningReassemblerTest, trim_advertising_data); }; } // namespace bluetooth::hci