blob: 2e426a86fbb2ac11be4394778b7663296ca66b21 [file] [log] [blame]
/*
* Copyright 2017 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 <algorithm>
#include <chrono>
#include <map>
#include <set>
#include <vector>
#include "hci/address.h"
#include "include/phy.h"
#include "model/controller/acl_connection_handler.h"
#include "model/controller/controller_properties.h"
#include "model/controller/le_advertiser.h"
#include "packets/hci_packets.h"
#include "packets/link_layer_packets.h"
#include "rootcanal_rs.h"
namespace rootcanal {
using ::bluetooth::hci::Address;
using ::bluetooth::hci::AddressType;
using ::bluetooth::hci::AuthenticationEnable;
using ::bluetooth::hci::ErrorCode;
using ::bluetooth::hci::FilterAcceptListAddressType;
using ::bluetooth::hci::OpCode;
using ::bluetooth::hci::PageScanRepetitionMode;
// Create an address with type Public Device Address or Random Device Address.
AddressWithType PeerDeviceAddress(Address address,
PeerAddressType peer_address_type);
// Create an address with type Public Identity Address or Random Identity
// address.
AddressWithType PeerIdentityAddress(Address address,
PeerAddressType peer_address_type);
class LinkLayerController {
public:
static constexpr size_t kIrkSize = 16;
static constexpr size_t kLtkSize = 16;
static constexpr size_t kLocalNameSize = 248;
static constexpr size_t kExtendedInquiryResponseSize = 240;
// Unique instance identifier.
const uint32_t id_;
// Generate a resolvable private address using the specified IRK.
static Address generate_rpa(
std::array<uint8_t, LinkLayerController::kIrkSize> irk);
// Return true if the input IRK is all 0s.
static bool irk_is_zero(std::array<uint8_t, LinkLayerController::kIrkSize> irk);
LinkLayerController(const Address& address,
const ControllerProperties& properties, uint32_t id = 0);
~LinkLayerController();
ErrorCode SendCommandToRemoteByAddress(OpCode opcode, pdl::packet::slice args,
const Address& own_address,
const Address& peer_address);
ErrorCode SendLeCommandToRemoteByAddress(OpCode opcode,
const Address& own_address,
const Address& peer_address);
ErrorCode SendCommandToRemoteByHandle(OpCode opcode, pdl::packet::slice args,
uint16_t handle);
ErrorCode SendScoToRemote(bluetooth::hci::ScoView sco_packet);
ErrorCode SendAclToRemote(bluetooth::hci::AclView acl_packet);
void ForwardToLm(bluetooth::hci::CommandView command);
void ForwardToLl(bluetooth::hci::CommandView command);
std::vector<bluetooth::hci::Lap> const& ReadCurrentIacLap() const;
void WriteCurrentIacLap(std::vector<bluetooth::hci::Lap> iac_lap);
ErrorCode AcceptConnectionRequest(const Address& addr, bool try_role_switch);
void MakePeripheralConnection(const Address& addr, bool try_role_switch);
ErrorCode RejectConnectionRequest(const Address& addr, uint8_t reason);
void RejectPeripheralConnection(const Address& addr, uint8_t reason);
// HCI command Create Connection (Vol 4, Part E § 7.1.5).
ErrorCode CreateConnection(const Address& bd_addr, uint16_t packet_type,
uint8_t page_scan_mode, uint16_t clock_offset,
uint8_t allow_role_switch);
// HCI command Disconnect (Vol 4, Part E § 7.1.6).
// \p host_reason is taken from the Disconnect command, and sent over
// to the remote as disconnect error. \p controller_reason is the code
// used in the DisconnectionComplete event.
ErrorCode Disconnect(uint16_t handle, ErrorCode host_reason,
ErrorCode controller_reason =
ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST);
// HCI command Create Connection Cancel (Vol 4, Part E § 7.1.7).
ErrorCode CreateConnectionCancel(const Address& bd_addr);
// Internal task scheduler.
// This scheduler is driven by the tick function only,
// hence the precision of the scheduler is within a tick period.
class Task;
using TaskId = uint32_t;
using TaskCallback = std::function<void(void)>;
static constexpr TaskId kInvalidTaskId = 0;
/// Schedule a task to be executed \p delay ms in the future.
TaskId ScheduleTask(std::chrono::milliseconds delay,
TaskCallback task_callback);
/// Schedule a task to be executed every \p period ms starting
/// \p delay ms in the future. Note that the task will be executed
/// at most once per \ref Tick() invocation, hence the period
/// cannot be lower than the \ref Tick() period.
TaskId SchedulePeriodicTask(std::chrono::milliseconds delay,
std::chrono::milliseconds period,
TaskCallback task_callback);
/// Cancel the selected task.
void CancelScheduledTask(TaskId task_id);
// Execute tasks that are pending at the current time.
void RunPendingTasks();
private:
void SendDisconnectionCompleteEvent(uint16_t handle, ErrorCode reason);
public:
const Address& GetAddress() const;
void IncomingPacket(model::packets::LinkLayerPacketView incoming,
int8_t rssi);
void Tick();
void Close();
// Set the callbacks for sending packets to the HCI.
void RegisterEventChannel(
const std::function<void(std::shared_ptr<bluetooth::hci::EventBuilder>)>&
send_event);
void RegisterAclChannel(
const std::function<void(std::shared_ptr<bluetooth::hci::AclBuilder>)>&
send_acl);
void RegisterScoChannel(
const std::function<void(std::shared_ptr<bluetooth::hci::ScoBuilder>)>&
send_sco);
void RegisterIsoChannel(
const std::function<void(std::shared_ptr<bluetooth::hci::IsoBuilder>)>&
send_iso);
void RegisterRemoteChannel(
const std::function<
void(std::shared_ptr<model::packets::LinkLayerPacketBuilder>,
Phy::Type, int8_t)>& send_to_remote);
void Reset();
void Paging();
void LeAdvertising();
void LeScanning();
void LeSynchronization();
void LeConnectionUpdateComplete(uint16_t handle, uint16_t interval_min,
uint16_t interval_max, uint16_t latency,
uint16_t supervision_timeout);
ErrorCode LeConnectionUpdate(uint16_t handle, uint16_t interval_min,
uint16_t interval_max, uint16_t latency,
uint16_t supervision_timeout);
ErrorCode LeRemoteConnectionParameterRequestReply(
uint16_t connection_handle, uint16_t interval_min, uint16_t interval_max,
uint16_t timeout, uint16_t latency, uint16_t minimum_ce_length,
uint16_t maximum_ce_length);
ErrorCode LeRemoteConnectionParameterRequestNegativeReply(
uint16_t connection_handle, bluetooth::hci::ErrorCode reason);
uint16_t HandleLeConnection(AddressWithType addr, AddressWithType own_addr,
bluetooth::hci::Role role,
uint16_t connection_interval,
uint16_t connection_latency,
uint16_t supervision_timeout,
bool send_le_channel_selection_algorithm_event);
bool ResolvingListBusy();
bool FilterAcceptListBusy();
bool LeFilterAcceptListContainsDevice(
FilterAcceptListAddressType address_type, Address address);
bool LeFilterAcceptListContainsDevice(AddressWithType address);
bool LePeriodicAdvertiserListContainsDevice(
bluetooth::hci::AdvertiserAddressType advertiser_address_type,
Address advertiser_address, uint8_t advertising_sid);
enum IrkSelection {
Peer, // Use Peer IRK for RPA resolution or generation.
Local // Use Local IRK for RPA resolution or generation.
};
// If the selected address is a Resolvable Private Address, then
// resolve the address using the resolving list. If the address cannot
// be resolved none is returned. If the address is not a Resolvable
// Private Address, the original address is returned.
std::optional<AddressWithType> ResolvePrivateAddress(AddressWithType address,
IrkSelection irk);
// Generate a Resolvable Private for the selected peer.
// If the address is not found in the resolving list none is returned.
// `local` indicates whether to use the local (true) or peer (false) IRK when
// generating the Resolvable Private Address.
std::optional<AddressWithType> GenerateResolvablePrivateAddress(
AddressWithType address, IrkSelection irk);
// Check if the selected address matches one of the controller's device
// addresses (public or random static).
bool IsLocalPublicOrRandomAddress(AddressWithType address) {
switch (address.GetAddressType()) {
case AddressType::PUBLIC_DEVICE_ADDRESS:
return address.GetAddress() == address_;
case AddressType::RANDOM_DEVICE_ADDRESS:
return address.GetAddress() == random_address_;
default:
return false;
}
}
void HandleLeEnableEncryption(uint16_t handle, std::array<uint8_t, 8> rand,
uint16_t ediv,
std::array<uint8_t, kLtkSize> ltk);
ErrorCode LeEnableEncryption(uint16_t handle, std::array<uint8_t, 8> rand,
uint16_t ediv,
std::array<uint8_t, kLtkSize> ltk);
ErrorCode LeLongTermKeyRequestReply(uint16_t handle,
std::array<uint8_t, kLtkSize> ltk);
ErrorCode LeLongTermKeyRequestNegativeReply(uint16_t handle);
uint8_t LeReadNumberOfSupportedAdvertisingSets();
// Classic
void StartInquiry(std::chrono::milliseconds timeout);
void InquiryCancel();
void InquiryTimeout();
void SetInquiryMode(uint8_t mode);
void SetInquiryLAP(uint64_t lap);
void SetInquiryMaxResponses(uint8_t max);
void Inquiry();
bool GetInquiryScanEnable() const { return inquiry_scan_enable_; }
void SetInquiryScanEnable(bool enable);
bool GetPageScanEnable() const { return page_scan_enable_; }
void SetPageScanEnable(bool enable);
uint16_t GetPageTimeout() const { return page_timeout_; }
void SetPageTimeout(uint16_t page_timeout);
ErrorCode ChangeConnectionPacketType(uint16_t handle, uint16_t types);
ErrorCode ChangeConnectionLinkKey(uint16_t handle);
ErrorCode CentralLinkKey(uint8_t key_flag);
ErrorCode HoldMode(uint16_t handle, uint16_t hold_mode_max_interval,
uint16_t hold_mode_min_interval);
ErrorCode SniffMode(uint16_t handle, uint16_t sniff_max_interval,
uint16_t sniff_min_interval, uint16_t sniff_attempt,
uint16_t sniff_timeout);
ErrorCode ExitSniffMode(uint16_t handle);
ErrorCode QosSetup(uint16_t handle, uint8_t service_type, uint32_t token_rate,
uint32_t peak_bandwidth, uint32_t latency,
uint32_t delay_variation);
ErrorCode RoleDiscovery(uint16_t handle, bluetooth::hci::Role* role);
ErrorCode SwitchRole(Address bd_addr, bluetooth::hci::Role role);
ErrorCode ReadLinkPolicySettings(uint16_t handle, uint16_t* settings);
ErrorCode WriteLinkPolicySettings(uint16_t handle, uint16_t settings);
ErrorCode FlowSpecification(uint16_t handle, uint8_t flow_direction,
uint8_t service_type, uint32_t token_rate,
uint32_t token_bucket_size,
uint32_t peak_bandwidth, uint32_t access_latency);
ErrorCode WriteLinkSupervisionTimeout(uint16_t handle, uint16_t timeout);
ErrorCode WriteDefaultLinkPolicySettings(uint16_t settings);
void CheckExpiringConnection(uint16_t handle);
uint16_t ReadDefaultLinkPolicySettings() const;
void ReadLocalOobData();
void ReadLocalOobExtendedData();
ErrorCode AddScoConnection(uint16_t connection_handle, uint16_t packet_type,
ScoDatapath datapath);
ErrorCode SetupSynchronousConnection(
uint16_t connection_handle, uint32_t transmit_bandwidth,
uint32_t receive_bandwidth, uint16_t max_latency, uint16_t voice_setting,
uint8_t retransmission_effort, uint16_t packet_types,
ScoDatapath datapath);
ErrorCode AcceptSynchronousConnection(
Address bd_addr, uint32_t transmit_bandwidth, uint32_t receive_bandwidth,
uint16_t max_latency, uint16_t voice_setting,
uint8_t retransmission_effort, uint16_t packet_types);
ErrorCode RejectSynchronousConnection(Address bd_addr, uint16_t reason);
// Returns true if any ACL connection exists.
bool HasAclConnection();
// Returns true if the specified ACL connection handle is valid.
bool HasAclConnection(uint16_t connection_handle);
void HandleIso(bluetooth::hci::IsoView iso);
// BR/EDR Commands
// HCI Read Rssi command (Vol 4, Part E § 7.5.4).
ErrorCode ReadRssi(uint16_t connection_handle, int8_t* rssi);
// LE Commands
// HCI LE Set Random Address command (Vol 4, Part E § 7.8.4).
ErrorCode LeSetRandomAddress(Address random_address);
// HCI LE Set Resolvable Private Address Timeout command
// (Vol 4, Part E § 7.8.45).
ErrorCode LeSetResolvablePrivateAddressTimeout(uint16_t rpa_timeout);
// HCI LE Read Phy command (Vol 4, Part E § 7.8.47).
ErrorCode LeReadPhy(uint16_t connection_handle,
bluetooth::hci::PhyType* tx_phy,
bluetooth::hci::PhyType* rx_phy);
// HCI LE Set Default Phy command (Vol 4, Part E § 7.8.48).
ErrorCode LeSetDefaultPhy(bool all_phys_no_transmit_preference,
bool all_phys_no_receive_preference,
uint8_t tx_phys, uint8_t rx_phys);
// HCI LE Set Phy command (Vol 4, Part E § 7.8.49).
ErrorCode LeSetPhy(uint16_t connection_handle,
bool all_phys_no_transmit_preference,
bool all_phys_no_receive_preference, uint8_t tx_phys,
uint8_t rx_phys, bluetooth::hci::PhyOptions phy_options);
// HCI LE Set Host Feature command (Vol 4, Part E § 7.8.115).
ErrorCode LeSetHostFeature(uint8_t bit_number, uint8_t bit_value);
// LE Filter Accept List
// HCI command LE_Clear_Filter_Accept_List (Vol 4, Part E § 7.8.15).
ErrorCode LeClearFilterAcceptList();
// HCI command LE_Add_Device_To_Filter_Accept_List (Vol 4, Part E § 7.8.16).
ErrorCode LeAddDeviceToFilterAcceptList(
FilterAcceptListAddressType address_type, Address address);
// HCI command LE_Remove_Device_From_Filter_Accept_List (Vol 4, Part E
// § 7.8.17).
ErrorCode LeRemoveDeviceFromFilterAcceptList(
FilterAcceptListAddressType address_type, Address address);
// LE Address Resolving
// HCI command LE_Add_Device_To_Resolving_List (Vol 4, Part E § 7.8.38).
ErrorCode LeAddDeviceToResolvingList(
PeerAddressType peer_identity_address_type, Address peer_identity_address,
std::array<uint8_t, kIrkSize> peer_irk,
std::array<uint8_t, kIrkSize> local_irk);
// HCI command LE_Remove_Device_From_Resolving_List (Vol 4, Part E § 7.8.39).
ErrorCode LeRemoveDeviceFromResolvingList(
PeerAddressType peer_identity_address_type,
Address peer_identity_address);
// HCI command LE_Clear_Resolving_List (Vol 4, Part E § 7.8.40).
ErrorCode LeClearResolvingList();
// HCI command LE_Read_Peer_Resolvable_Address (Vol 4, Part E § 7.8.42).
ErrorCode LeReadPeerResolvableAddress(
PeerAddressType peer_identity_address_type, Address peer_identity_address,
Address* peer_resolvable_address);
// HCI command LE_Read_Local_Resolvable_Address (Vol 4, Part E § 7.8.43).
ErrorCode LeReadLocalResolvableAddress(
PeerAddressType peer_identity_address_type, Address peer_identity_address,
Address* local_resolvable_address);
// HCI command LE_Set_Address_Resolution_Enable (Vol 4, Part E § 7.8.44).
ErrorCode LeSetAddressResolutionEnable(bool enable);
// HCI command LE_Set_Privacy_Mode (Vol 4, Part E § 7.8.77).
ErrorCode LeSetPrivacyMode(PeerAddressType peer_identity_address_type,
Address peer_identity_address,
bluetooth::hci::PrivacyMode privacy_mode);
// Legacy Advertising
// HCI command LE_Set_Advertising_Parameters (Vol 4, Part E § 7.8.5).
ErrorCode LeSetAdvertisingParameters(
uint16_t advertising_interval_min, uint16_t advertising_interval_max,
bluetooth::hci::AdvertisingType advertising_type,
bluetooth::hci::OwnAddressType own_address_type,
bluetooth::hci::PeerAddressType peer_address_type, Address peer_address,
uint8_t advertising_channel_map,
bluetooth::hci::AdvertisingFilterPolicy advertising_filter_policy);
// HCI command LE_Set_Advertising_Data (Vol 4, Part E § 7.8.7).
ErrorCode LeSetAdvertisingData(const std::vector<uint8_t>& advertising_data);
// HCI command LE_Set_Scan_Response_Data (Vol 4, Part E § 7.8.8).
ErrorCode LeSetScanResponseData(
const std::vector<uint8_t>& scan_response_data);
// HCI command LE_Advertising_Enable (Vol 4, Part E § 7.8.9).
ErrorCode LeSetAdvertisingEnable(bool advertising_enable);
// Extended Advertising
// HCI command LE_Set_Advertising_Set_Random_Address (Vol 4, Part E § 7.8.52).
ErrorCode LeSetAdvertisingSetRandomAddress(uint8_t advertising_handle,
Address random_address);
// HCI command LE_Set_Advertising_Parameters (Vol 4, Part E § 7.8.53).
ErrorCode LeSetExtendedAdvertisingParameters(
uint8_t advertising_handle,
AdvertisingEventProperties advertising_event_properties,
uint16_t primary_advertising_interval_min,
uint16_t primary_advertising_interval_max,
uint8_t primary_advertising_channel_map,
bluetooth::hci::OwnAddressType own_address_type,
bluetooth::hci::PeerAddressType peer_address_type, Address peer_address,
bluetooth::hci::AdvertisingFilterPolicy advertising_filter_policy,
uint8_t advertising_tx_power,
bluetooth::hci::PrimaryPhyType primary_advertising_phy,
uint8_t secondary_max_skip,
bluetooth::hci::SecondaryPhyType secondary_advertising_phy,
uint8_t advertising_sid, bool scan_request_notification_enable);
// HCI command LE_Set_Extended_Advertising_Data (Vol 4, Part E § 7.8.54).
ErrorCode LeSetExtendedAdvertisingData(
uint8_t advertising_handle, bluetooth::hci::Operation operation,
bluetooth::hci::FragmentPreference fragment_preference,
const std::vector<uint8_t>& advertising_data);
// HCI command LE_Set_Extended_Scan_Response_Data (Vol 4, Part E § 7.8.55).
ErrorCode LeSetExtendedScanResponseData(
uint8_t advertising_handle, bluetooth::hci::Operation operation,
bluetooth::hci::FragmentPreference fragment_preference,
const std::vector<uint8_t>& scan_response_data);
// HCI command LE_Set_Extended_Advertising_Enable (Vol 4, Part E § 7.8.56).
ErrorCode LeSetExtendedAdvertisingEnable(
bool enable, const std::vector<bluetooth::hci::EnabledSet>& sets);
// HCI command LE_Remove_Advertising_Set (Vol 4, Part E § 7.8.59).
ErrorCode LeRemoveAdvertisingSet(uint8_t advertising_handle);
// HCI command LE_Clear_Advertising_Sets (Vol 4, Part E § 7.8.60).
ErrorCode LeClearAdvertisingSets();
// Legacy Scanning
// HCI command LE_Set_Scan_Parameters (Vol 4, Part E § 7.8.10).
ErrorCode LeSetScanParameters(
bluetooth::hci::LeScanType scan_type, uint16_t scan_interval,
uint16_t scan_window, bluetooth::hci::OwnAddressType own_address_type,
bluetooth::hci::LeScanningFilterPolicy scanning_filter_policy);
// HCI command LE_Set_Scan_Enable (Vol 4, Part E § 7.8.11).
ErrorCode LeSetScanEnable(bool enable, bool filter_duplicates);
// Extended Scanning
// HCI command LE_Set_Extended_Scan_Parameters (Vol 4, Part E § 7.8.64).
ErrorCode LeSetExtendedScanParameters(
bluetooth::hci::OwnAddressType own_address_type,
bluetooth::hci::LeScanningFilterPolicy scanning_filter_policy,
uint8_t scanning_phys,
std::vector<bluetooth::hci::ScanningPhyParameters>
scanning_phy_parameters);
// HCI command LE_Set_Extended_Scan_Enable (Vol 4, Part E § 7.8.65).
ErrorCode LeSetExtendedScanEnable(
bool enable, bluetooth::hci::FilterDuplicates filter_duplicates,
uint16_t duration, uint16_t period);
// Legacy Connection
// HCI LE Create Connection command (Vol 4, Part E § 7.8.12).
ErrorCode LeCreateConnection(
uint16_t scan_interval, uint16_t scan_window,
bluetooth::hci::InitiatorFilterPolicy initiator_filter_policy,
AddressWithType peer_address,
bluetooth::hci::OwnAddressType own_address_type,
uint16_t connection_interval_min, uint16_t connection_interval_max,
uint16_t max_latency, uint16_t supervision_timeout,
uint16_t min_ce_length, uint16_t max_ce_length);
// HCI LE Create Connection Cancel command (Vol 4, Part E § 7.8.12).
ErrorCode LeCreateConnectionCancel();
// Extended Connection
// HCI LE Extended Create Connection command (Vol 4, Part E § 7.8.66).
ErrorCode LeExtendedCreateConnection(
bluetooth::hci::InitiatorFilterPolicy initiator_filter_policy,
bluetooth::hci::OwnAddressType own_address_type,
AddressWithType peer_address, uint8_t initiating_phys,
std::vector<bluetooth::hci::InitiatingPhyParameters>
initiating_phy_parameters);
// Periodic Advertising
// HCI LE Set Periodic Advertising Parameters command (Vol 4, Part E
// § 7.8.61).
ErrorCode LeSetPeriodicAdvertisingParameters(
uint8_t advertising_handle, uint16_t periodic_advertising_interval_min,
uint16_t periodic_advertising_interval_max, bool include_tx_power);
// HCI LE Set Periodic Advertising Data command (Vol 4, Part E § 7.8.62).
ErrorCode LeSetPeriodicAdvertisingData(
uint8_t advertising_handle, bluetooth::hci::Operation operation,
const std::vector<uint8_t>& advertising_data);
// HCI LE Set Periodic Advertising Enable command (Vol 4, Part E § 7.8.63).
ErrorCode LeSetPeriodicAdvertisingEnable(bool enable, bool include_adi,
uint8_t advertising_handle);
// Periodic Sync
// HCI LE Periodic Advertising Create Sync command (Vol 4, Part E § 7.8.67).
ErrorCode LePeriodicAdvertisingCreateSync(
bluetooth::hci::PeriodicAdvertisingOptions options,
uint8_t advertising_sid,
bluetooth::hci::AdvertiserAddressType advertiser_address_type,
Address advertiser_address, uint16_t skip, uint16_t sync_timeout,
uint8_t sync_cte_type);
// HCI LE Periodic Advertising Create Sync Cancel command (Vol 4, Part E
// § 7.8.68).
ErrorCode LePeriodicAdvertisingCreateSyncCancel();
// HCI LE Periodic Advertising Terminate Sync command (Vol 4, Part E
// § 7.8.69).
ErrorCode LePeriodicAdvertisingTerminateSync(uint16_t sync_handle);
// Periodic Advertiser List
// HCI LE Add Device To Periodic Advertiser List command (Vol 4, Part E
// § 7.8.70).
ErrorCode LeAddDeviceToPeriodicAdvertiserList(
bluetooth::hci::AdvertiserAddressType advertiser_address_type,
Address advertiser_address, uint8_t advertising_sid);
// HCI LE Remove Device From Periodic Advertiser List command
// (Vol 4, Part E § 7.8.71).
ErrorCode LeRemoveDeviceFromPeriodicAdvertiserList(
bluetooth::hci::AdvertiserAddressType advertiser_address_type,
Address advertiser_address, uint8_t advertising_sid);
// HCI LE Clear Periodic Advertiser List command (Vol 4, Part E § 7.8.72).
ErrorCode LeClearPeriodicAdvertiserList();
protected:
void SendLinkLayerPacket(
std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet,
int8_t tx_power = 0);
void SendLeLinkLayerPacket(
std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet,
int8_t tx_power = 0);
void IncomingAclPacket(model::packets::LinkLayerPacketView incoming,
int8_t rssi);
void IncomingScoPacket(model::packets::LinkLayerPacketView incoming);
void IncomingDisconnectPacket(model::packets::LinkLayerPacketView incoming);
void IncomingEncryptConnection(model::packets::LinkLayerPacketView incoming);
void IncomingEncryptConnectionResponse(
model::packets::LinkLayerPacketView incoming);
void IncomingInquiryPacket(model::packets::LinkLayerPacketView incoming,
uint8_t rssi);
void IncomingInquiryResponsePacket(
model::packets::LinkLayerPacketView incoming);
void IncomingLmpPacket(model::packets::LinkLayerPacketView incoming);
void IncomingLlcpPacket(model::packets::LinkLayerPacketView incoming);
void IncomingLeConnectedIsochronousPdu(
model::packets::LinkLayerPacketView incoming);
void ScanIncomingLeLegacyAdvertisingPdu(
model::packets::LeLegacyAdvertisingPduView& pdu, uint8_t rssi);
void ScanIncomingLeExtendedAdvertisingPdu(
model::packets::LeExtendedAdvertisingPduView& pdu, uint8_t rssi);
void ConnectIncomingLeLegacyAdvertisingPdu(
model::packets::LeLegacyAdvertisingPduView& pdu);
void ConnectIncomingLeExtendedAdvertisingPdu(
model::packets::LeExtendedAdvertisingPduView& pdu);
void IncomingLeLegacyAdvertisingPdu(
model::packets::LinkLayerPacketView incoming, uint8_t rssi);
void IncomingLeExtendedAdvertisingPdu(
model::packets::LinkLayerPacketView incoming, uint8_t rssi);
void IncomingLePeriodicAdvertisingPdu(
model::packets::LinkLayerPacketView incoming, uint8_t rssi);
void IncomingLeConnectPacket(model::packets::LinkLayerPacketView incoming);
void IncomingLeConnectCompletePacket(
model::packets::LinkLayerPacketView incoming);
void IncomingLeConnectionParameterRequest(
model::packets::LinkLayerPacketView incoming);
void IncomingLeConnectionParameterUpdate(
model::packets::LinkLayerPacketView incoming);
void IncomingLeEncryptConnection(
model::packets::LinkLayerPacketView incoming);
void IncomingLeEncryptConnectionResponse(
model::packets::LinkLayerPacketView incoming);
void IncomingLeReadRemoteFeatures(
model::packets::LinkLayerPacketView incoming);
void IncomingLeReadRemoteFeaturesResponse(
model::packets::LinkLayerPacketView incoming);
void ProcessIncomingLegacyScanRequest(
AddressWithType scanning_address,
AddressWithType resolved_scanning_address,
AddressWithType advertising_address);
void ProcessIncomingExtendedScanRequest(
ExtendedAdvertiser const& advertiser, AddressWithType scanning_address,
AddressWithType resolved_scanning_address,
AddressWithType advertising_address);
bool ProcessIncomingLegacyConnectRequest(
model::packets::LeConnectView const& connect_ind);
bool ProcessIncomingExtendedConnectRequest(
ExtendedAdvertiser& advertiser,
model::packets::LeConnectView const& connect_ind);
void IncomingLeScanPacket(model::packets::LinkLayerPacketView incoming);
void IncomingLeScanResponsePacket(
model::packets::LinkLayerPacketView incoming, uint8_t rssi);
void IncomingPagePacket(model::packets::LinkLayerPacketView incoming);
void IncomingPageRejectPacket(model::packets::LinkLayerPacketView incoming);
void IncomingPageResponsePacket(model::packets::LinkLayerPacketView incoming);
void IncomingReadRemoteLmpFeatures(
model::packets::LinkLayerPacketView incoming);
void IncomingReadRemoteLmpFeaturesResponse(
model::packets::LinkLayerPacketView incoming);
void IncomingReadRemoteSupportedFeatures(
model::packets::LinkLayerPacketView incoming);
void IncomingReadRemoteSupportedFeaturesResponse(
model::packets::LinkLayerPacketView incoming);
void IncomingReadRemoteExtendedFeatures(
model::packets::LinkLayerPacketView incoming);
void IncomingReadRemoteExtendedFeaturesResponse(
model::packets::LinkLayerPacketView incoming);
void IncomingReadRemoteVersion(model::packets::LinkLayerPacketView incoming);
void IncomingReadRemoteVersionResponse(
model::packets::LinkLayerPacketView incoming);
void IncomingReadClockOffset(model::packets::LinkLayerPacketView incoming);
void IncomingReadClockOffsetResponse(
model::packets::LinkLayerPacketView incoming);
void IncomingRemoteNameRequest(model::packets::LinkLayerPacketView incoming);
void IncomingRemoteNameRequestResponse(
model::packets::LinkLayerPacketView incoming);
void IncomingScoConnectionRequest(
model::packets::LinkLayerPacketView incoming);
void IncomingScoConnectionResponse(
model::packets::LinkLayerPacketView incoming);
void IncomingScoDisconnect(model::packets::LinkLayerPacketView incoming);
void IncomingPingRequest(model::packets::LinkLayerPacketView incoming);
void IncomingRoleSwitchRequest(model::packets::LinkLayerPacketView incoming);
void IncomingRoleSwitchResponse(model::packets::LinkLayerPacketView incoming);
void IncomingLlPhyReq(model::packets::LinkLayerPacketView incoming);
void IncomingLlPhyRsp(model::packets::LinkLayerPacketView incoming);
void IncomingLlPhyUpdateInd(model::packets::LinkLayerPacketView incoming);
public:
bool IsEventUnmasked(bluetooth::hci::EventCode event) const;
bool IsLeEventUnmasked(bluetooth::hci::SubeventCode subevent) const;
// TODO
// The Clock Offset should be specific to an ACL connection.
// Returning a proper value is not that important.
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
uint32_t GetClockOffset() const { return 0; }
// TODO
// The Page Scan Repetition Mode should be specific to an ACL connection or
// a paging session.
PageScanRepetitionMode GetPageScanRepetitionMode() const {
return page_scan_repetition_mode_;
}
// TODO
// The Encryption Key Size should be specific to an ACL connection.
uint8_t GetEncryptionKeySize() const { return min_encryption_key_size_; }
bool GetScoFlowControlEnable() const { return sco_flow_control_enable_; }
AuthenticationEnable GetAuthenticationEnable() {
return authentication_enable_;
}
std::array<uint8_t, kLocalNameSize> const& GetLocalName() {
return local_name_;
}
uint64_t GetLeSupportedFeatures() const {
return properties_.le_features | le_host_supported_features_;
}
uint16_t GetConnectionAcceptTimeout() const {
return connection_accept_timeout_;
}
uint16_t GetVoiceSetting() const { return voice_setting_; }
uint32_t GetClassOfDevice() const { return class_of_device_; }
uint8_t GetMaxLmpFeaturesPageNumber() {
return properties_.lmp_features.size() - 1;
}
uint64_t GetLmpFeatures(uint8_t page_number = 0) {
return page_number == 1 ? host_supported_features_
: properties_.lmp_features[page_number];
}
void SetLocalName(std::vector<uint8_t> const& local_name);
void SetLocalName(std::array<uint8_t, kLocalNameSize> const& local_name);
void SetExtendedInquiryResponse(
std::array<uint8_t, 240> const& extended_inquiry_response);
void SetExtendedInquiryResponse(
std::vector<uint8_t> const& extended_inquiry_response);
void SetClassOfDevice(uint32_t class_of_device) {
class_of_device_ = class_of_device;
}
void SetAuthenticationEnable(AuthenticationEnable enable) {
authentication_enable_ = enable;
}
void SetScoFlowControlEnable(bool enable) {
sco_flow_control_enable_ = enable;
}
void SetVoiceSetting(uint16_t voice_setting) {
voice_setting_ = voice_setting;
}
void SetEventMask(uint64_t event_mask) { event_mask_ = event_mask; }
void SetEventMaskPage2(uint64_t event_mask) {
event_mask_page_2_ = event_mask;
}
void SetLeEventMask(uint64_t le_event_mask) {
le_event_mask_ = le_event_mask;
}
void SetLeHostSupport(bool enable);
void SetSecureSimplePairingSupport(bool enable);
void SetSecureConnectionsSupport(bool enable);
void SetConnectionAcceptTimeout(uint16_t timeout) {
connection_accept_timeout_ = timeout;
}
bool LegacyAdvertising() const { return legacy_advertising_in_use_; }
bool ExtendedAdvertising() const { return extended_advertising_in_use_; }
bool SelectLegacyAdvertising() {
if (extended_advertising_in_use_) {
return false;
}
legacy_advertising_in_use_ = true;
return true;
}
bool SelectExtendedAdvertising() {
if (legacy_advertising_in_use_) {
return false;
}
extended_advertising_in_use_ = true;
return true;
}
uint16_t GetLeSuggestedMaxTxOctets() const {
return le_suggested_max_tx_octets_;
}
uint16_t GetLeSuggestedMaxTxTime() const { return le_suggested_max_tx_time_; }
void SetLeSuggestedMaxTxOctets(uint16_t max_tx_octets) {
le_suggested_max_tx_octets_ = max_tx_octets;
}
void SetLeSuggestedMaxTxTime(uint16_t max_tx_time) {
le_suggested_max_tx_time_ = max_tx_time;
}
TaskId StartScoStream(Address address);
private:
const Address& address_;
const ControllerProperties& properties_;
// Host Supported Features (Vol 2, Part C § 3.3 Feature Mask Definition).
// Page 1 of the LMP feature mask.
uint64_t host_supported_features_{0};
bool le_host_support_{false};
bool secure_simple_pairing_host_support_{false};
bool secure_connections_host_support_{false};
// Le Host Supported Features (Vol 4, Part E § 7.8.3).
// Specifies the bits indicating Host support.
uint64_t le_host_supported_features_{0};
bool connected_isochronous_stream_host_support_{false};
bool connection_subrating_host_support_{false};
// LE Random Address (Vol 4, Part E § 7.8.4).
Address random_address_{Address::kEmpty};
// HCI configuration parameters.
//
// Provide the current HCI Configuration Parameters as defined in section
// Vol 4, Part E § 6 of the core specification.
// Scan Enable (Vol 4, Part E § 6.1).
bool page_scan_enable_{false};
bool inquiry_scan_enable_{false};
// Inquiry Scan Interval and Window
// (Vol 4, Part E § 6.2, 6.3).
uint16_t inquiry_scan_interval_{0x1000};
uint16_t inquiry_scan_window_{0x0012};
// Page Timeout (Vol 4, Part E § 6.6).
uint16_t page_timeout_{0x2000};
// Connection Accept Timeout (Vol 4, Part E § 6.7).
uint16_t connection_accept_timeout_{0x1FA0};
// Page Scan Interval and Window
// (Vol 4, Part E § 6.8, 6.9).
uint16_t page_scan_interval_{0x0800};
uint16_t page_scan_window_{0x0012};
// Voice Setting (Vol 4, Part E § 6.12).
uint16_t voice_setting_{0x0060};
// Authentication Enable (Vol 4, Part E § 6.16).
AuthenticationEnable authentication_enable_{
AuthenticationEnable::NOT_REQUIRED};
// Default Link Policy Settings (Vol 4, Part E § 6.18).
uint8_t default_link_policy_settings_{0x0000};
// Synchronous Flow Control Enable (Vol 4, Part E § 6.22).
bool sco_flow_control_enable_{false};
// Local Name (Vol 4, Part E § 6.23).
std::array<uint8_t, kLocalNameSize> local_name_{};
// Extended Inquiry Response (Vol 4, Part E § 6.24).
std::array<uint8_t, kExtendedInquiryResponseSize>
extended_inquiry_response_{};
// Class of Device (Vol 4, Part E § 6.26).
uint32_t class_of_device_{0};
// Other configuration parameters.
// Current IAC LAP (Vol 4, Part E § 7.3.44).
std::vector<bluetooth::hci::Lap> current_iac_lap_list_{};
// Min Encryption Key Size (Vol 4, Part E § 7.3.102).
uint8_t min_encryption_key_size_{16};
// Event Mask (Vol 4, Part E § 7.3.1) and
// Event Mask Page 2 (Vol 4, Part E § 7.3.69) and
// LE Event Mask (Vol 4, Part E § 7.8.1).
uint64_t event_mask_{0x00001fffffffffff};
uint64_t event_mask_page_2_{0x0};
uint64_t le_event_mask_{0x01f};
// Suggested Default Data Length (Vol 4, Part E § 7.8.34).
uint16_t le_suggested_max_tx_octets_{0x001b};
uint16_t le_suggested_max_tx_time_{0x0148};
// Resolvable Private Address Timeout (Vol 4, Part E § 7.8.45).
std::chrono::seconds resolvable_private_address_timeout_{0x0384};
// Page Scan Repetition Mode (Vol 2 Part B § 8.3.1 Page Scan substate).
// The Page Scan Repetition Mode depends on the selected Page Scan Interval.
PageScanRepetitionMode page_scan_repetition_mode_{PageScanRepetitionMode::R0};
AclConnectionHandler connections_;
// Callbacks to send packets back to the HCI.
std::function<void(std::shared_ptr<bluetooth::hci::AclBuilder>)> send_acl_;
std::function<void(std::shared_ptr<bluetooth::hci::EventBuilder>)>
send_event_;
std::function<void(std::shared_ptr<bluetooth::hci::ScoBuilder>)> send_sco_;
std::function<void(std::shared_ptr<bluetooth::hci::IsoBuilder>)> send_iso_;
// Callback to send packets to remote devices.
std::function<void(std::shared_ptr<model::packets::LinkLayerPacketBuilder>,
Phy::Type phy_type, int8_t tx_power)>
send_to_remote_;
uint32_t oob_id_{1};
uint32_t key_id_{1};
struct FilterAcceptListEntry {
FilterAcceptListAddressType address_type;
Address address;
};
std::vector<FilterAcceptListEntry> le_filter_accept_list_;
struct ResolvingListEntry {
PeerAddressType peer_identity_address_type;
Address peer_identity_address;
std::array<uint8_t, kIrkSize> peer_irk;
std::array<uint8_t, kIrkSize> local_irk;
bluetooth::hci::PrivacyMode privacy_mode;
// Resolvable Private Address being used by the local device.
// It is the last resolvable private address generated for
// this identity address.
std::optional<Address> local_resolvable_address;
// Resolvable Private Address being used by the peer device.
// It is the last resolvable private address received that resolved
// to this identity address.
std::optional<Address> peer_resolvable_address;
};
std::vector<ResolvingListEntry> le_resolving_list_;
bool le_resolving_list_enabled_{false};
// Flag set when any legacy advertising command has been received
// since the last power-on-reset.
// From Vol 4, Part E § 3.1.1 Legacy and extended advertising,
// extended advertising are rejected when this bit is set.
bool legacy_advertising_in_use_{false};
// Flag set when any extended advertising command has been received
// since the last power-on-reset.
// From Vol 4, Part E § 3.1.1 Legacy and extended advertising,
// legacy advertising are rejected when this bit is set.
bool extended_advertising_in_use_{false};
// Legacy advertising state.
LegacyAdvertiser legacy_advertiser_{};
// Extended advertising sets.
std::unordered_map<uint8_t, ExtendedAdvertiser> extended_advertisers_{};
// Local phy preferences, defaults to LE 1M Phy.
uint8_t default_tx_phys_{0x1};
uint8_t default_rx_phys_{0x1};
uint8_t requested_tx_phys_{0x1};
uint8_t requested_rx_phys_{0x1};
struct PeriodicAdvertiserListEntry {
bluetooth::hci::AdvertiserAddressType advertiser_address_type;
Address advertiser_address;
uint8_t advertising_sid;
};
std::vector<PeriodicAdvertiserListEntry> le_periodic_advertiser_list_;
struct Scanner {
bool scan_enable;
std::chrono::steady_clock::duration period;
std::chrono::steady_clock::duration duration;
bluetooth::hci::FilterDuplicates filter_duplicates;
bluetooth::hci::OwnAddressType own_address_type;
bluetooth::hci::LeScanningFilterPolicy scan_filter_policy;
struct PhyParameters {
bool enabled;
bluetooth::hci::LeScanType scan_type;
uint16_t scan_interval;
uint16_t scan_window;
};
PhyParameters le_1m_phy;
PhyParameters le_coded_phy;
// Save information about the advertising PDU being scanned.
bool connectable_scan_response;
std::optional<AddressWithType> pending_scan_request{};
// Time keeping
std::optional<std::chrono::steady_clock::time_point> timeout;
std::optional<std::chrono::steady_clock::time_point> periodical_timeout;
// Packet History
std::vector<pdl::packet::slice> history;
bool IsEnabled() const { return scan_enable; }
bool IsPacketInHistory(pdl::packet::slice const& packet) const {
return std::any_of(
history.begin(), history.end(),
[packet](pdl::packet::slice const& a) { return a == packet; });
}
void AddPacketToHistory(pdl::packet::slice packet) {
history.push_back(packet);
}
};
// Legacy and extended scanning properties.
// Legacy and extended scanning are disambiguated by the use
// of legacy_advertising_in_use_ and extended_advertising_in_use_ flags.
// Only one type of advertising may be used during a controller session.
Scanner scanner_{};
struct Initiator {
bool connect_enable;
bluetooth::hci::InitiatorFilterPolicy initiator_filter_policy;
bluetooth::hci::AddressWithType peer_address{};
bluetooth::hci::OwnAddressType own_address_type;
struct PhyParameters {
bool enabled;
uint16_t scan_interval;
uint16_t scan_window;
uint16_t connection_interval_min;
uint16_t connection_interval_max;
uint16_t max_latency;
uint16_t supervision_timeout;
uint16_t min_ce_length;
uint16_t max_ce_length;
};
PhyParameters le_1m_phy;
PhyParameters le_2m_phy;
PhyParameters le_coded_phy;
// Save information about the ongoing connection.
Address initiating_address{}; // TODO: AddressWithType
std::optional<AddressWithType> pending_connect_request{};
bool IsEnabled() const { return connect_enable; }
void Disable() { connect_enable = false; }
};
// Legacy and extended initiating properties.
// Legacy and extended initiating are disambiguated by the use
// of legacy_advertising_in_use_ and extended_advertising_in_use_ flags.
// Only one type of advertising may be used during a controller session.
Initiator initiator_{};
struct Synchronizing {
bluetooth::hci::PeriodicAdvertisingOptions options{};
bluetooth::hci::AdvertiserAddressType advertiser_address_type{};
Address advertiser_address{};
uint8_t advertising_sid{};
std::chrono::steady_clock::duration sync_timeout{};
};
struct Synchronized {
bluetooth::hci::AdvertiserAddressType advertiser_address_type;
Address advertiser_address;
uint8_t advertising_sid;
uint16_t sync_handle;
std::chrono::steady_clock::duration sync_timeout;
std::chrono::steady_clock::time_point timeout;
};
// Periodic advertising synchronizing and synchronized states.
// Contains information for the currently established syncs, and the
// pending sync.
std::optional<Synchronizing> synchronizing_{};
std::unordered_map<uint16_t, Synchronized> synchronized_{};
// Buffer to contain the ISO SDU sent from the host stack over HCI.
// The SDU is forwarded to the peer only when complete.
std::vector<uint8_t> iso_sdu_{};
// Rust state.
std::unique_ptr<const LinkManager, void (*)(const LinkManager*)> lm_;
std::unique_ptr<const LinkLayer, void (*)(const LinkLayer*)> ll_;
struct ControllerOps controller_ops_;
// Classic state.
struct Page {
Address bd_addr;
uint8_t allow_role_switch;
std::chrono::steady_clock::time_point next_page_event{};
std::chrono::steady_clock::time_point page_timeout{};
};
// Page substate.
// RootCanal will allow only one page request running at the same time.
std::optional<Page> page_;
std::chrono::steady_clock::time_point last_inquiry_;
model::packets::InquiryType inquiry_mode_{
model::packets::InquiryType::STANDARD};
TaskId inquiry_timer_task_id_ = kInvalidTaskId;
uint64_t inquiry_lap_{};
uint8_t inquiry_max_responses_{};
public:
// Type of scheduled tasks.
class Task {
public:
Task(std::chrono::steady_clock::time_point time,
std::chrono::milliseconds period, TaskCallback callback,
TaskId task_id)
: time(time),
periodic(true),
period(period),
callback(std::move(callback)),
task_id(task_id) {}
Task(std::chrono::steady_clock::time_point time, TaskCallback callback,
TaskId task_id)
: time(time),
periodic(false),
callback(std::move(callback)),
task_id(task_id) {}
// Operators needed to be in a collection
bool operator<(const Task& another) const {
return std::make_pair(time, task_id) <
std::make_pair(another.time, another.task_id);
}
// These fields should no longer be public if the class ever becomes
// public or gets more complex
std::chrono::steady_clock::time_point time;
const bool periodic;
std::chrono::milliseconds period{};
TaskCallback callback;
TaskId task_id;
};
private:
// List currently pending tasks.
std::set<Task> task_queue_{};
TaskId task_counter_{0};
// Return the next valid unused task identifier.
TaskId NextTaskId();
};
} // namespace rootcanal