1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include <gtest/gtest_prod.h> 19 20 #include <cstdint> 21 #include <list> 22 #include <optional> 23 #include <vector> 24 25 #include "hci/address_with_type.h" 26 #include "hci/hci_packets.h" 27 28 namespace bluetooth::hci { 29 30 /// The LE Scanning reassembler is responsible for defragmenting 31 /// LE advertising reports that are too large to fit inside an HCI event 32 /// and were fragmented by the controller. 33 /// The reassembler also joins scan response data with the 34 /// matching advertising data. 35 36 class LeScanningReassembler { 37 public: 38 struct CompleteAdvertisingData { 39 uint16_t extended_event_type; 40 std::vector<uint8_t> data; 41 }; 42 LeScanningReassembler()43 LeScanningReassembler() {} 44 45 LeScanningReassembler(const LeScanningReassembler&) = delete; 46 47 LeScanningReassembler& operator=(const LeScanningReassembler&) = delete; 48 49 /// Process an incoming advertsing report, extracted from any of the 50 /// HCI LE Advertising Report or the HCI LE Extended Advertising Report 51 /// events. 52 /// Returns the completed advertising data if the event was complete, or the 53 /// completion of a fragmented advertising event. 54 std::optional<CompleteAdvertisingData> ProcessAdvertisingReport( 55 uint16_t event_type, uint8_t address_type, Address address, uint8_t advertising_sid, 56 const std::vector<uint8_t>& advertising_data); 57 58 /// Process an incoming periodic advertising report, extracted from the 59 /// HCI LE Periodic Advertising Report events. 60 /// Returns the completed advertising data if the event was complete, 61 /// or the completion of a fragmented advertising event. 62 std::optional<std::vector<uint8_t>> ProcessPeriodicAdvertisingReport( 63 uint16_t sync_handle, DataStatus status, const std::vector<uint8_t>& advertising_data); 64 65 /// Configure the scan response filter. 66 /// If true all scan responses are ignored. SetIgnoreScanResponses(bool ignore_scan_responses)67 void SetIgnoreScanResponses(bool ignore_scan_responses) { 68 ignore_scan_responses_ = ignore_scan_responses; 69 } 70 71 private: 72 /// Determine if scan responses should be processed or ignored. 73 bool ignore_scan_responses_{false}; 74 75 /// Constants for parsing event_type. 76 static constexpr uint8_t kConnectableBit = 0; 77 static constexpr uint8_t kScannableBit = 1; 78 static constexpr uint8_t kDirectedBit = 2; 79 static constexpr uint8_t kScanResponseBit = 3; 80 static constexpr uint8_t kLegacyBit = 4; 81 static constexpr uint8_t kDataStatusBits = 5; 82 83 /// Packs the information necessary to disambiguate advertising events: 84 /// - For legacy advertising events, the advertising address and 85 /// advertising address type are used to disambiguate advertisers. 86 /// - For extended advertising events, the SID is optionally used to 87 /// differentiate between advertising sets of the same advertiser. 88 /// The advertiser can also be anonymous in which case 89 /// the address is not provided. In this case, and when the SID 90 /// is missing, we trust the controller to send fragments of the same 91 /// advertisement together and not interleaved with that of other 92 /// advertisers. 93 struct AdvertisingKey { 94 std::optional<AddressWithType> address; 95 std::optional<uint8_t> sid; 96 97 AdvertisingKey(Address address, DirectAdvertisingAddressType address_type, uint8_t sid); 98 bool operator==(const AdvertisingKey& other); 99 }; 100 101 /// Packs incomplete advertising data. 102 struct AdvertisingFragment { 103 AdvertisingKey key; 104 uint16_t extended_event_type; 105 std::vector<uint8_t> data; 106 AdvertisingFragmentAdvertisingFragment107 AdvertisingFragment(const AdvertisingKey& key, uint16_t extended_event_type, 108 const std::vector<uint8_t>& data) 109 : key(key), extended_event_type(extended_event_type), data(data.begin(), data.end()) {} 110 }; 111 112 /// Packs incomplete periodic advertising data. 113 struct PeriodicAdvertisingFragment { 114 std::optional<uint16_t> sync_handle; 115 std::vector<uint8_t> data; 116 PeriodicAdvertisingFragmentPeriodicAdvertisingFragment117 PeriodicAdvertisingFragment(uint16_t sync_handle, const std::vector<uint8_t>& data) 118 : sync_handle(sync_handle), data(data.begin(), data.end()) {} 119 }; 120 121 /// Advertising cache for de-fragmenting extended advertising reports, 122 /// and joining advertising reports with the matching scan response when 123 /// applicable. 124 /// The cached advertising data is removed as soon as the complete 125 /// advertisement is got (including the scan response). 126 static constexpr size_t kMaximumCacheSize = 16; 127 std::list<AdvertisingFragment> cache_; 128 129 /// Advertising cache management methods. 130 std::list<AdvertisingFragment>::iterator AppendFragment(const AdvertisingKey& key, 131 uint16_t extended_event_type, 132 const std::vector<uint8_t>& data); 133 134 void RemoveFragment(const AdvertisingKey& key); 135 136 bool ContainsFragment(const AdvertisingKey& key); 137 138 std::list<AdvertisingFragment>::iterator FindFragment(const AdvertisingKey& key); 139 140 /// Advertising cache for de-fragmenting periodic advertising reports. 141 static constexpr size_t kMaximumPeriodicCacheSize = 16; 142 std::list<PeriodicAdvertisingFragment> periodic_cache_; 143 144 std::list<PeriodicAdvertisingFragment>::iterator AppendPeriodicFragment( 145 uint16_t sync_handle, const std::vector<uint8_t>& data); 146 147 std::list<PeriodicAdvertisingFragment>::iterator FindPeriodicFragment(uint16_t sync_handle); 148 149 /// Trim the advertising data by removing empty or overflowing 150 /// GAP Data entries. 151 static std::vector<uint8_t> TrimAdvertisingData(const std::vector<uint8_t>& advertising_data); 152 153 FRIEND_TEST(LeScanningReassemblerTest, trim_advertising_data); 154 }; 155 156 } // namespace bluetooth::hci 157