/* * Copyright 2020 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.h" #include "hci/address_with_type.h" #include "packets/hci_packets.h" namespace rootcanal { // Duration type for slots (increments of 625us). using slots = std::chrono::duration>; // User defined literal for slots, e.g. `0x800_slots` slots operator"" _slots(unsigned long long count); using namespace bluetooth::hci; // Advertising interface common to legacy and extended advertisers. class Advertiser { public: Advertiser() = default; ~Advertiser() = default; bool IsEnabled() const { return advertising_enable; } void Disable() { advertising_enable = false; } AddressWithType GetAdvertisingAddress() const { return advertising_address; } AddressWithType GetTargetAddress() const { return target_address; } // HCI properties. bool advertising_enable{false}; AddressWithType advertising_address{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS}; AddressWithType target_address{Address::kEmpty, AddressType::PUBLIC_DEVICE_ADDRESS}; // Time keeping. std::chrono::steady_clock::time_point next_event{}; std::optional timeout{}; }; // Implement the unique legacy advertising instance. // For extended advertising check the ExtendedAdvertiser class. class LegacyAdvertiser : public Advertiser { public: LegacyAdvertiser() = default; ~LegacyAdvertiser() = default; bool IsScannable() const { return advertising_type != AdvertisingType::ADV_NONCONN_IND && advertising_type != AdvertisingType::ADV_DIRECT_IND_HIGH && advertising_type != AdvertisingType::ADV_DIRECT_IND_LOW; } bool IsConnectable() const { return advertising_type != AdvertisingType::ADV_NONCONN_IND && advertising_type != AdvertisingType::ADV_SCAN_IND; } bool IsDirected() const { return advertising_type == AdvertisingType::ADV_DIRECT_IND_HIGH || advertising_type == AdvertisingType::ADV_DIRECT_IND_LOW; } // Host configuration parameters. Gather the configuration from the // legacy advertising HCI commands. The initial configuration // matches the default values of the parameters of the HCI command // LE Set Advertising Parameters. slots advertising_interval{0x0800}; AdvertisingType advertising_type{AdvertisingType::ADV_IND}; OwnAddressType own_address_type{OwnAddressType::PUBLIC_DEVICE_ADDRESS}; PeerAddressType peer_address_type{PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS}; Address peer_address{}; uint8_t advertising_channel_map{0x07}; AdvertisingFilterPolicy advertising_filter_policy{AdvertisingFilterPolicy::ALL_DEVICES}; std::vector advertising_data{}; std::vector scan_response_data{}; }; // Implement a single extended advertising set. // The configuration is set by the extended advertising commands; // for the legacy advertiser check the LegacyAdvertiser class. class ExtendedAdvertiser : public Advertiser { public: ExtendedAdvertiser(uint8_t advertising_handle = 0) : advertising_handle(advertising_handle) {} ~ExtendedAdvertiser() = default; void Enable() { advertising_enable = true; periodic_advertising_enable_latch = periodic_advertising_enable; next_event = std::chrono::steady_clock::now(); } void EnablePeriodic() { periodic_advertising_enable = true; periodic_advertising_enable_latch = advertising_enable; next_periodic_event = std::chrono::steady_clock::now(); } void DisablePeriodic() { periodic_advertising_enable = false; periodic_advertising_enable_latch = false; } bool IsPeriodicEnabled() const { return periodic_advertising_enable_latch; } bool IsScannable() const { return advertising_event_properties.scannable_; } bool IsConnectable() const { return advertising_event_properties.connectable_; } bool IsDirected() const { return advertising_event_properties.directed_; } // Host configuration parameters. Gather the configuration from the // extended advertising HCI commands. uint8_t advertising_handle; AdvertisingEventProperties advertising_event_properties{}; slots primary_advertising_interval{}; uint8_t primary_advertising_channel_map{}; OwnAddressType own_address_type{}; PeerAddressType peer_address_type{}; Address peer_address{}; std::optional
random_address{}; AdvertisingFilterPolicy advertising_filter_policy{}; uint8_t advertising_tx_power{}; PrimaryPhyType primary_advertising_phy{}; uint8_t secondary_max_skip{}; SecondaryPhyType secondary_advertising_phy{}; uint8_t advertising_sid{}; bool scan_request_notification_enable{}; std::vector advertising_data{}; std::vector scan_response_data{}; bool partial_advertising_data{false}; bool partial_scan_response_data{false}; // Periodic advertising configuration. // Note: the enable flag has a latch because of the semantic describe in the // specification: // // If the advertising set is not currently enabled, the periodic advertising // is not started until the advertising set is enabled. Once the advertising // set has been enabled, the Controller shall continue periodic advertising // until the Host issues an HCI_LE_Set_Periodic_Advertising_Enable command // with bit 0 of Enable set to 0 (periodic advertising is disabled). // Disabling the advertising set has no effect on the periodic advertising // once the advertising set has been enabled. // // Thus the enable latch is set when the advertising set is enabled and // periodic advertising is enabled, and cleared when periodic advertising // gets disabled. bool periodic_advertising_enable{false}; bool periodic_advertising_enable_latch{false}; slots periodic_advertising_interval{}; std::vector periodic_advertising_data{}; bool partial_periodic_advertising_data{false}; // Time keeping for periodic advertising. std::chrono::steady_clock::time_point next_periodic_event{}; // Enabled state. uint8_t max_extended_advertising_events{0}; uint8_t num_completed_extended_advertising_events{0}; // Not implemented at the moment. bool constant_tone_extensions{false}; // Compute the maximum advertising data payload size for the selected // advertising event properties. The advertising data is not present if // 0 is returned. static uint16_t GetMaxAdvertisingDataLength(const AdvertisingEventProperties& properties); // Compute the maximum scan response data payload size for the selected // advertising event properties. The scan response data is not present if // 0 is returned. static uint16_t GetMaxScanResponseDataLength(const AdvertisingEventProperties& properties); // Reconstitute the raw Advertising_Event_Properties bitmask. static uint16_t GetRawAdvertisingEventProperties(const AdvertisingEventProperties& properties); // Compute the maximum periodic advertising data payload size for the // selected periodic advertising interval. static uint16_t GetMaxPeriodicAdvertisingDataLength(slots periodic_advertising_interval); }; } // namespace rootcanal