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, 56 uint8_t address_type, 57 Address address, 58 uint8_t advertising_sid, 59 const std::vector<uint8_t>& advertising_data); 60 61 /// Process an incoming periodic advertising report, extracted from the 62 /// HCI LE Periodic Advertising Report events. 63 /// Returns the completed advertising data if the event was complete, 64 /// or the completion of a fragmented advertising event. 65 std::optional<std::vector<uint8_t>> ProcessPeriodicAdvertisingReport( 66 uint16_t sync_handle, DataStatus status, const std::vector<uint8_t>& advertising_data); 67 68 /// Configure the scan response filter. 69 /// If true all scan responses are ignored. SetIgnoreScanResponses(bool ignore_scan_responses)70 void SetIgnoreScanResponses(bool ignore_scan_responses) { 71 ignore_scan_responses_ = ignore_scan_responses; 72 } 73 74 private: 75 /// Determine if scan responses should be processed or ignored. 76 bool ignore_scan_responses_{false}; 77 78 /// Constants for parsing event_type. 79 static constexpr uint8_t kConnectableBit = 0; 80 static constexpr uint8_t kScannableBit = 1; 81 static constexpr uint8_t kDirectedBit = 2; 82 static constexpr uint8_t kScanResponseBit = 3; 83 static constexpr uint8_t kLegacyBit = 4; 84 static constexpr uint8_t kDataStatusBits = 5; 85 86 /// Packs the information necessary to disambiguate advertising events: 87 /// - For legacy advertising events, the advertising address and 88 /// advertising address type are used to disambiguate advertisers. 89 /// - For extended advertising events, the SID is optionally used to 90 /// differentiate between advertising sets of the same advertiser. 91 /// The advertiser can also be anonymous in which case 92 /// the address is not provided. In this case, and when the SID 93 /// is missing, we trust the controller to send fragments of the same 94 /// advertisement together and not interleaved with that of other 95 /// advertisers. 96 struct AdvertisingKey { 97 std::optional<AddressWithType> address; 98 std::optional<uint8_t> sid; 99 100 AdvertisingKey(Address address, DirectAdvertisingAddressType address_type, uint8_t sid); 101 bool operator==(const AdvertisingKey& other); 102 }; 103 104 /// Packs incomplete advertising data. 105 struct AdvertisingFragment { 106 AdvertisingKey key; 107 uint16_t extended_event_type; 108 std::vector<uint8_t> data; 109 AdvertisingFragmentAdvertisingFragment110 AdvertisingFragment( 111 const AdvertisingKey& key, uint16_t extended_event_type, const std::vector<uint8_t>& data) 112 : key(key), extended_event_type(extended_event_type), data(data.begin(), data.end()) {} 113 }; 114 115 /// Packs incomplete periodic advertising data. 116 struct PeriodicAdvertisingFragment { 117 std::optional<uint16_t> sync_handle; 118 std::vector<uint8_t> data; 119 PeriodicAdvertisingFragmentPeriodicAdvertisingFragment120 PeriodicAdvertisingFragment(uint16_t sync_handle, const std::vector<uint8_t>& data) 121 : sync_handle(sync_handle), data(data.begin(), data.end()) {} 122 }; 123 124 /// Advertising cache for de-fragmenting extended advertising reports, 125 /// and joining advertising reports with the matching scan response when 126 /// applicable. 127 /// The cached advertising data is removed as soon as the complete 128 /// advertisement is got (including the scan response). 129 static constexpr size_t kMaximumCacheSize = 16; 130 std::list<AdvertisingFragment> cache_; 131 132 /// Advertising cache management methods. 133 std::list<AdvertisingFragment>::iterator AppendFragment( 134 const AdvertisingKey& key, uint16_t extended_event_type, const std::vector<uint8_t>& data); 135 136 void RemoveFragment(const AdvertisingKey& key); 137 138 bool ContainsFragment(const AdvertisingKey& key); 139 140 std::list<AdvertisingFragment>::iterator FindFragment(const AdvertisingKey& key); 141 142 /// Advertising cache for de-fragmenting periodic advertising reports. 143 static constexpr size_t kMaximumPeriodicCacheSize = 16; 144 std::list<PeriodicAdvertisingFragment> periodic_cache_; 145 146 std::list<PeriodicAdvertisingFragment>::iterator AppendPeriodicFragment( 147 uint16_t sync_handle, const std::vector<uint8_t>& data); 148 149 std::list<PeriodicAdvertisingFragment>::iterator FindPeriodicFragment(uint16_t sync_handle); 150 151 /// Trim the advertising data by removing empty or overflowing 152 /// GAP Data entries. 153 static std::vector<uint8_t> TrimAdvertisingData(const std::vector<uint8_t>& advertising_data); 154 155 FRIEND_TEST(LeScanningReassemblerTest, trim_advertising_data); 156 }; 157 158 } // namespace bluetooth::hci 159