121 lines
4.5 KiB
C
121 lines
4.5 KiB
C
|
|
/*
|
||
|
|
* 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
|