blob: b287123efeeec42cc8f420b759e0731785904bf6 [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 "acl_connection_handler.h"
#include "hci/address.h"
#include "hci/hci_packets.h"
#include "include/hci.h"
#include "include/inquiry.h"
#include "include/phy.h"
#include "model/devices/device_properties.h"
#include "model/setup/async_manager.h"
#include "packets/link_layer_packets.h"
#include "security_manager.h"
namespace test_vendor_lib {
using ::bluetooth::hci::Address;
using ::bluetooth::hci::ErrorCode;
using ::bluetooth::hci::OpCode;
class LinkLayerController {
public:
static constexpr size_t kIrk_size = 16;
LinkLayerController(const DeviceProperties& properties) : properties_(properties) {}
ErrorCode SendCommandToRemoteByAddress(
OpCode opcode, bluetooth::packet::PacketView<true> args,
const Address& remote);
ErrorCode SendCommandToRemoteByHandle(
OpCode opcode, bluetooth::packet::PacketView<true> args, uint16_t handle);
ErrorCode SendScoToRemote(bluetooth::hci::ScoPacketView sco_packet);
ErrorCode SendAclToRemote(bluetooth::hci::AclPacketView acl_packet);
void WriteSimplePairingMode(bool enabled);
void StartSimplePairing(const Address& address);
void AuthenticateRemoteStage1(const Address& address, PairingType pairing_type);
void AuthenticateRemoteStage2(const Address& address);
ErrorCode LinkKeyRequestReply(const Address& address,
const std::array<uint8_t, 16>& key);
ErrorCode LinkKeyRequestNegativeReply(const Address& address);
ErrorCode IoCapabilityRequestReply(const Address& peer, uint8_t io_capability,
uint8_t oob_data_present_flag,
uint8_t authentication_requirements);
ErrorCode IoCapabilityRequestNegativeReply(const Address& peer,
ErrorCode reason);
ErrorCode UserConfirmationRequestReply(const Address& peer);
ErrorCode UserConfirmationRequestNegativeReply(const Address& peer);
ErrorCode UserPasskeyRequestReply(const Address& peer,
uint32_t numeric_value);
ErrorCode UserPasskeyRequestNegativeReply(const Address& peer);
ErrorCode RemoteOobDataRequestReply(const Address& peer,
const std::vector<uint8_t>& c,
const std::vector<uint8_t>& r);
ErrorCode RemoteOobDataRequestNegativeReply(const Address& peer);
void HandleSetConnectionEncryption(const Address& address, uint16_t handle, uint8_t encryption_enable);
ErrorCode SetConnectionEncryption(uint16_t handle, uint8_t encryption_enable);
void HandleAuthenticationRequest(const Address& address, uint16_t handle);
ErrorCode AuthenticationRequested(uint16_t handle);
ErrorCode AcceptConnectionRequest(const Address& addr, bool try_role_switch);
void MakeSlaveConnection(const Address& addr, bool try_role_switch);
ErrorCode RejectConnectionRequest(const Address& addr, uint8_t reason);
void RejectSlaveConnection(const Address& addr, uint8_t reason);
ErrorCode CreateConnection(const Address& addr, uint16_t packet_type,
uint8_t page_scan_mode, uint16_t clock_offset,
uint8_t allow_role_switch);
ErrorCode CreateConnectionCancel(const Address& addr);
ErrorCode Disconnect(uint16_t handle, uint8_t reason);
private:
void DisconnectCleanup(uint16_t handle, uint8_t reason);
public:
void IncomingPacket(model::packets::LinkLayerPacketView incoming);
void TimerTick();
AsyncTaskId ScheduleTask(std::chrono::milliseconds delay_ms, const TaskCallback& task);
void CancelScheduledTask(AsyncTaskId task);
// Set the callbacks for sending packets to the HCI.
void RegisterEventChannel(
const std::function<void(
std::shared_ptr<bluetooth::hci::EventPacketBuilder>)>& send_event);
void RegisterAclChannel(
const std::function<
void(std::shared_ptr<bluetooth::hci::AclPacketBuilder>)>& send_acl);
void RegisterScoChannel(const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& send_sco);
void RegisterIsoChannel(
const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>&
send_iso);
void RegisterRemoteChannel(
const std::function<void(
std::shared_ptr<model::packets::LinkLayerPacketBuilder>, Phy::Type)>&
send_to_remote);
// Set the callbacks for scheduling tasks.
void RegisterTaskScheduler(
std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)> event_scheduler);
void RegisterPeriodicTaskScheduler(
std::function<AsyncTaskId(std::chrono::milliseconds, std::chrono::milliseconds, const TaskCallback&)>
periodic_event_scheduler);
void RegisterTaskCancel(std::function<void(AsyncTaskId)> cancel);
void Reset();
void AddControllerEvent(std::chrono::milliseconds delay, const TaskCallback& task);
void PageScan();
void Connections();
void LeAdvertising();
void HandleLeConnection(Address addr, uint8_t addr_type, uint8_t own_addr_type, uint8_t role,
uint16_t connection_interval, uint16_t connection_latency, uint16_t supervision_timeout);
void LeWhiteListClear();
void LeWhiteListAddDevice(Address addr, uint8_t addr_type);
void LeWhiteListRemoveDevice(Address addr, uint8_t addr_type);
bool LeWhiteListContainsDevice(Address addr, uint8_t addr_type);
bool LeWhiteListFull();
void LeResolvingListClear();
void LeResolvingListAddDevice(Address addr, uint8_t addr_type,
std::array<uint8_t, kIrk_size> peerIrk,
std::array<uint8_t, kIrk_size> localIrk);
void LeResolvingListRemoveDevice(Address addr, uint8_t addr_type);
bool LeResolvingListContainsDevice(Address addr, uint8_t addr_type);
bool LeResolvingListFull();
void LeSetPrivacyMode(uint8_t address_type, Address addr, uint8_t mode);
ErrorCode SetLeAdvertisingEnable(uint8_t le_advertising_enable) {
le_advertising_enable_ = le_advertising_enable;
// TODO: Check properties and return errors
return ErrorCode::SUCCESS;
}
void SetLeScanEnable(uint8_t le_scan_enable) {
le_scan_enable_ = le_scan_enable;
}
void SetLeScanType(uint8_t le_scan_type) {
le_scan_type_ = le_scan_type;
}
void SetLeScanInterval(uint16_t le_scan_interval) {
le_scan_interval_ = le_scan_interval;
}
void SetLeScanWindow(uint16_t le_scan_window) {
le_scan_window_ = le_scan_window;
}
void SetLeScanFilterPolicy(uint8_t le_scan_filter_policy) {
le_scan_filter_policy_ = le_scan_filter_policy;
}
void SetLeFilterDuplicates(uint8_t le_scan_filter_duplicates) {
le_scan_filter_duplicates_ = le_scan_filter_duplicates;
}
void SetLeAddressType(uint8_t le_address_type) {
le_address_type_ = le_address_type;
}
ErrorCode SetLeConnect(bool le_connect) {
le_connect_ = le_connect;
return ErrorCode::SUCCESS;
}
void SetLeConnectionIntervalMin(uint16_t min) {
le_connection_interval_min_ = min;
}
void SetLeConnectionIntervalMax(uint16_t max) {
le_connection_interval_max_ = max;
}
void SetLeConnectionLatency(uint16_t latency) {
le_connection_latency_ = latency;
}
void SetLeSupervisionTimeout(uint16_t timeout) {
le_connection_supervision_timeout_ = timeout;
}
void SetLeMinimumCeLength(uint16_t min) {
le_connection_minimum_ce_length_ = min;
}
void SetLeMaximumCeLength(uint16_t max) {
le_connection_maximum_ce_length_ = max;
}
void SetLeInitiatorFilterPolicy(uint8_t le_initiator_filter_policy) {
le_initiator_filter_policy_ = le_initiator_filter_policy;
}
void SetLePeerAddressType(uint8_t peer_address_type) {
le_peer_address_type_ = peer_address_type;
}
void SetLePeerAddress(const Address& peer_address) {
le_peer_address_ = peer_address;
}
// 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();
void SetInquiryScanEnable(bool enable);
void SetPageScanEnable(bool enable);
ErrorCode ChangeConnectionPacketType(uint16_t handle, uint16_t types);
ErrorCode ChangeConnectionLinkKey(uint16_t handle);
ErrorCode MasterLinkKey(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 SwitchRole(Address bd_addr, uint8_t role);
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);
protected:
void SendLeLinkLayerPacket(
std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet);
void SendLinkLayerPacket(
std::unique_ptr<model::packets::LinkLayerPacketBuilder> packet);
void IncomingAclPacket(model::packets::LinkLayerPacketView packet);
void IncomingAclAckPacket(model::packets::LinkLayerPacketView packet);
void IncomingCreateConnectionPacket(
model::packets::LinkLayerPacketView packet);
void IncomingDisconnectPacket(model::packets::LinkLayerPacketView packet);
void IncomingEncryptConnection(model::packets::LinkLayerPacketView packet);
void IncomingEncryptConnectionResponse(
model::packets::LinkLayerPacketView packet);
void IncomingInquiryPacket(model::packets::LinkLayerPacketView packet);
void IncomingInquiryResponsePacket(
model::packets::LinkLayerPacketView packet);
void IncomingIoCapabilityRequestPacket(
model::packets::LinkLayerPacketView packet);
void IncomingIoCapabilityResponsePacket(
model::packets::LinkLayerPacketView packet);
void IncomingIoCapabilityNegativeResponsePacket(
model::packets::LinkLayerPacketView packet);
void IncomingLeAdvertisementPacket(
model::packets::LinkLayerPacketView packet);
void IncomingLeConnectPacket(model::packets::LinkLayerPacketView packet);
void IncomingLeConnectCompletePacket(
model::packets::LinkLayerPacketView packet);
void IncomingLeScanPacket(model::packets::LinkLayerPacketView packet);
void IncomingLeScanResponsePacket(model::packets::LinkLayerPacketView packet);
void IncomingPagePacket(model::packets::LinkLayerPacketView packet);
void IncomingPageRejectPacket(model::packets::LinkLayerPacketView packet);
void IncomingPageResponsePacket(model::packets::LinkLayerPacketView packet);
void IncomingReadRemoteLmpFeatures(
model::packets::LinkLayerPacketView packet);
void IncomingReadRemoteLmpFeaturesResponse(
model::packets::LinkLayerPacketView packet);
void IncomingReadRemoteSupportedFeatures(
model::packets::LinkLayerPacketView packet);
void IncomingReadRemoteSupportedFeaturesResponse(
model::packets::LinkLayerPacketView packet);
void IncomingReadRemoteExtendedFeatures(
model::packets::LinkLayerPacketView packet);
void IncomingReadRemoteExtendedFeaturesResponse(
model::packets::LinkLayerPacketView packet);
void IncomingReadRemoteVersion(model::packets::LinkLayerPacketView packet);
void IncomingReadRemoteVersionResponse(
model::packets::LinkLayerPacketView packet);
void IncomingReadClockOffset(model::packets::LinkLayerPacketView packet);
void IncomingReadClockOffsetResponse(
model::packets::LinkLayerPacketView packet);
void IncomingRemoteNameRequest(model::packets::LinkLayerPacketView packet);
void IncomingRemoteNameRequestResponse(
model::packets::LinkLayerPacketView packet);
private:
const DeviceProperties& properties_;
AclConnectionHandler connections_;
// Add timestamps?
std::vector<std::shared_ptr<model::packets::LinkLayerPacketBuilder>>
commands_awaiting_responses_;
// Timing related state
std::vector<AsyncTaskId> controller_events_;
AsyncTaskId timer_tick_task_;
std::chrono::milliseconds timer_period_ = std::chrono::milliseconds(100);
// Callbacks to schedule tasks.
std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)> schedule_task_;
std::function<AsyncTaskId(std::chrono::milliseconds, std::chrono::milliseconds, const TaskCallback&)>
schedule_periodic_task_;
std::function<void(AsyncTaskId)> cancel_task_;
// Callbacks to send packets back to the HCI.
std::function<void(std::shared_ptr<bluetooth::hci::AclPacketBuilder>)>
send_acl_;
std::function<void(std::shared_ptr<bluetooth::hci::EventPacketBuilder>)>
send_event_;
std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_sco_;
std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_iso_;
// Callback to send packets to remote devices.
std::function<void(std::shared_ptr<model::packets::LinkLayerPacketBuilder>,
Phy::Type phy_type)>
send_to_remote_;
// LE state
std::vector<uint8_t> le_event_mask_;
std::vector<std::tuple<Address, uint8_t>> le_white_list_;
std::vector<std::tuple<Address, uint8_t, std::array<uint8_t, kIrk_size>,
std::array<uint8_t, kIrk_size>>>
le_resolving_list_;
uint8_t le_advertising_enable_{false};
std::chrono::steady_clock::time_point last_le_advertisement_;
uint8_t le_scan_enable_{false};
uint8_t le_scan_type_;
uint16_t le_scan_interval_;
uint16_t le_scan_window_;
uint8_t le_scan_filter_policy_;
uint8_t le_scan_filter_duplicates_;
uint8_t le_address_type_;
bool le_connect_{false};
uint16_t le_connection_interval_min_;
uint16_t le_connection_interval_max_;
uint16_t le_connection_latency_;
uint16_t le_connection_supervision_timeout_;
uint16_t le_connection_minimum_ce_length_;
uint16_t le_connection_maximum_ce_length_;
uint8_t le_initiator_filter_policy_;
Address le_peer_address_;
uint8_t le_peer_address_type_;
// Classic state
SecurityManager security_manager_{10};
std::chrono::steady_clock::time_point last_inquiry_;
model::packets::InquiryType inquiry_mode_;
Inquiry::InquiryState inquiry_state_;
uint64_t inquiry_lap_;
uint8_t inquiry_max_responses_;
bool page_scans_enabled_{false};
bool inquiry_scans_enabled_{false};
bool simple_pairing_mode_enabled_{false};
};
} // namespace test_vendor_lib