/* * Copyright 2015 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. */ #include "dual_mode_controller.h" #include #include #include #include "crypto_toolbox/crypto_toolbox.h" #include "log.h" #include "packet/raw_builder.h" namespace gd_hci = ::bluetooth::hci; using gd_hci::ErrorCode; using gd_hci::LoopbackMode; using gd_hci::OpCode; using std::vector; namespace rootcanal { constexpr uint16_t kNumCommandPackets = 0x01; constexpr uint16_t kLeMaximumAdvertisingDataLength = 256; constexpr uint16_t kLeMaximumDataLength = 64; constexpr uint16_t kLeMaximumDataTime = 0x148; // Device methods. std::string DualModeController::GetTypeString() const { return "Simulated Bluetooth Controller"; } void DualModeController::IncomingPacket( model::packets::LinkLayerPacketView incoming) { link_layer_controller_.IncomingPacket(incoming); } void DualModeController::TimerTick() { link_layer_controller_.TimerTick(); } void DualModeController::Close() { link_layer_controller_.Close(); Device::Close(); } void DualModeController::SendCommandCompleteUnknownOpCodeEvent( uint16_t op_code) const { std::unique_ptr raw_builder_ptr = std::make_unique(); raw_builder_ptr->AddOctets1(kNumCommandPackets); raw_builder_ptr->AddOctets2(op_code); raw_builder_ptr->AddOctets1( static_cast(ErrorCode::UNKNOWN_HCI_COMMAND)); send_event_(gd_hci::EventBuilder::Create(gd_hci::EventCode::COMMAND_COMPLETE, std::move(raw_builder_ptr))); } #ifdef ROOTCANAL_LMP DualModeController::DualModeController(const std::string& properties_filename, uint16_t) : Device(), properties_(properties_filename) { #else DualModeController::DualModeController(const std::string& properties_filename, uint16_t num_keys) : Device(), properties_(properties_filename), security_manager_(num_keys) { #endif loopback_mode_ = LoopbackMode::NO_LOOPBACK; Address public_address{}; ASSERT(Address::FromString("3C:5A:B4:04:05:06", public_address)); SetAddress(public_address); link_layer_controller_.RegisterRemoteChannel( [this](std::shared_ptr packet, Phy::Type phy_type) { DualModeController::SendLinkLayerPacket(packet, phy_type); }); std::array supported_commands{0}; #define SET_HANDLER(name, method) \ active_hci_commands_[OpCode::name] = [this](CommandView param) { \ method(std::move(param)); \ }; #define SET_VENDOR_HANDLER(op_code, method) \ active_hci_commands_[static_cast(op_code)] = \ [this](CommandView param) { method(std::move(param)); }; #define SET_SUPPORTED(name, method) \ SET_HANDLER(name, method); \ { \ uint16_t index = (uint16_t)bluetooth::hci::OpCodeIndex::name; \ uint16_t byte_index = index / 10; \ uint8_t bit = 1 << (index % 10); \ supported_commands[byte_index] = supported_commands[byte_index] | bit; \ } SET_SUPPORTED(RESET, Reset); SET_SUPPORTED(READ_BUFFER_SIZE, ReadBufferSize); SET_SUPPORTED(HOST_BUFFER_SIZE, HostBufferSize); SET_SUPPORTED(SNIFF_SUBRATING, SniffSubrating); SET_SUPPORTED(READ_ENCRYPTION_KEY_SIZE, ReadEncryptionKeySize); SET_SUPPORTED(READ_LOCAL_VERSION_INFORMATION, ReadLocalVersionInformation); SET_SUPPORTED(READ_BD_ADDR, ReadBdAddr); SET_HANDLER(READ_LOCAL_SUPPORTED_COMMANDS, ReadLocalSupportedCommands); SET_SUPPORTED(READ_LOCAL_SUPPORTED_FEATURES, ReadLocalSupportedFeatures); SET_SUPPORTED(READ_LOCAL_SUPPORTED_CODECS_V1, ReadLocalSupportedCodecs); SET_SUPPORTED(READ_LOCAL_EXTENDED_FEATURES, ReadLocalExtendedFeatures); SET_SUPPORTED(READ_REMOTE_EXTENDED_FEATURES, ReadRemoteExtendedFeatures); SET_SUPPORTED(SWITCH_ROLE, SwitchRole); SET_SUPPORTED(READ_REMOTE_SUPPORTED_FEATURES, ReadRemoteSupportedFeatures); SET_SUPPORTED(READ_CLOCK_OFFSET, ReadClockOffset); SET_HANDLER(ADD_SCO_CONNECTION, AddScoConnection); SET_SUPPORTED(SETUP_SYNCHRONOUS_CONNECTION, SetupSynchronousConnection); SET_SUPPORTED(ACCEPT_SYNCHRONOUS_CONNECTION, AcceptSynchronousConnection); SET_SUPPORTED(REJECT_SYNCHRONOUS_CONNECTION, RejectSynchronousConnection); SET_SUPPORTED(ENHANCED_SETUP_SYNCHRONOUS_CONNECTION, EnhancedSetupSynchronousConnection); SET_SUPPORTED(ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION, EnhancedAcceptSynchronousConnection); SET_SUPPORTED(IO_CAPABILITY_REQUEST_REPLY, IoCapabilityRequestReply); SET_SUPPORTED(USER_CONFIRMATION_REQUEST_REPLY, UserConfirmationRequestReply); SET_SUPPORTED(USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, UserConfirmationRequestNegativeReply); SET_SUPPORTED(USER_PASSKEY_REQUEST_REPLY, UserPasskeyRequestReply); SET_SUPPORTED(USER_PASSKEY_REQUEST_NEGATIVE_REPLY, UserPasskeyRequestNegativeReply); SET_SUPPORTED(PIN_CODE_REQUEST_REPLY, PinCodeRequestReply); SET_SUPPORTED(PIN_CODE_REQUEST_NEGATIVE_REPLY, PinCodeRequestNegativeReply); SET_SUPPORTED(REMOTE_OOB_DATA_REQUEST_REPLY, RemoteOobDataRequestReply); SET_SUPPORTED(REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY, RemoteOobDataRequestNegativeReply); SET_SUPPORTED(IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, IoCapabilityRequestNegativeReply); SET_SUPPORTED(REMOTE_OOB_EXTENDED_DATA_REQUEST_REPLY, RemoteOobExtendedDataRequestReply); SET_SUPPORTED(READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL, ReadInquiryResponseTransmitPowerLevel); SET_SUPPORTED(SEND_KEYPRESS_NOTIFICATION, SendKeypressNotification); SET_SUPPORTED(ENHANCED_FLUSH, EnhancedFlush); SET_HANDLER(SET_EVENT_MASK_PAGE_2, SetEventMaskPage2); SET_SUPPORTED(READ_LOCAL_OOB_DATA, ReadLocalOobData); SET_SUPPORTED(READ_LOCAL_OOB_EXTENDED_DATA, ReadLocalOobExtendedData); SET_SUPPORTED(WRITE_SIMPLE_PAIRING_MODE, WriteSimplePairingMode); SET_SUPPORTED(WRITE_LE_HOST_SUPPORT, WriteLeHostSupport); SET_SUPPORTED(WRITE_SECURE_CONNECTIONS_HOST_SUPPORT, WriteSecureConnectionsHostSupport); SET_SUPPORTED(SET_EVENT_MASK, SetEventMask); SET_SUPPORTED(READ_INQUIRY_MODE, ReadInquiryMode); SET_SUPPORTED(WRITE_INQUIRY_MODE, WriteInquiryMode); SET_SUPPORTED(READ_PAGE_SCAN_TYPE, ReadPageScanType); SET_SUPPORTED(WRITE_PAGE_SCAN_TYPE, WritePageScanType); SET_SUPPORTED(WRITE_INQUIRY_SCAN_TYPE, WriteInquiryScanType); SET_SUPPORTED(READ_INQUIRY_SCAN_TYPE, ReadInquiryScanType); SET_SUPPORTED(AUTHENTICATION_REQUESTED, AuthenticationRequested); SET_SUPPORTED(SET_CONNECTION_ENCRYPTION, SetConnectionEncryption); SET_SUPPORTED(CHANGE_CONNECTION_LINK_KEY, ChangeConnectionLinkKey); SET_SUPPORTED(CENTRAL_LINK_KEY, CentralLinkKey); SET_SUPPORTED(WRITE_AUTHENTICATION_ENABLE, WriteAuthenticationEnable); SET_SUPPORTED(READ_AUTHENTICATION_ENABLE, ReadAuthenticationEnable); SET_SUPPORTED(WRITE_CLASS_OF_DEVICE, WriteClassOfDevice); SET_SUPPORTED(READ_PAGE_TIMEOUT, ReadPageTimeout); SET_SUPPORTED(WRITE_PAGE_TIMEOUT, WritePageTimeout); SET_SUPPORTED(WRITE_LINK_SUPERVISION_TIMEOUT, WriteLinkSupervisionTimeout); SET_SUPPORTED(HOLD_MODE, HoldMode); SET_SUPPORTED(SNIFF_MODE, SniffMode); SET_SUPPORTED(EXIT_SNIFF_MODE, ExitSniffMode); SET_SUPPORTED(QOS_SETUP, QosSetup); SET_SUPPORTED(ROLE_DISCOVERY, RoleDiscovery); SET_SUPPORTED(READ_DEFAULT_LINK_POLICY_SETTINGS, ReadDefaultLinkPolicySettings); SET_SUPPORTED(WRITE_DEFAULT_LINK_POLICY_SETTINGS, WriteDefaultLinkPolicySettings); SET_SUPPORTED(FLOW_SPECIFICATION, FlowSpecification); SET_SUPPORTED(READ_LINK_POLICY_SETTINGS, ReadLinkPolicySettings); SET_SUPPORTED(WRITE_LINK_POLICY_SETTINGS, WriteLinkPolicySettings); SET_SUPPORTED(CHANGE_CONNECTION_PACKET_TYPE, ChangeConnectionPacketType); SET_SUPPORTED(WRITE_LOCAL_NAME, WriteLocalName); SET_SUPPORTED(READ_LOCAL_NAME, ReadLocalName); SET_SUPPORTED(WRITE_EXTENDED_INQUIRY_RESPONSE, WriteExtendedInquiryResponse); SET_SUPPORTED(REFRESH_ENCRYPTION_KEY, RefreshEncryptionKey); SET_SUPPORTED(WRITE_VOICE_SETTING, WriteVoiceSetting); SET_SUPPORTED(READ_NUMBER_OF_SUPPORTED_IAC, ReadNumberOfSupportedIac); SET_SUPPORTED(READ_CURRENT_IAC_LAP, ReadCurrentIacLap); SET_SUPPORTED(WRITE_CURRENT_IAC_LAP, WriteCurrentIacLap); SET_SUPPORTED(READ_PAGE_SCAN_ACTIVITY, ReadPageScanActivity); SET_SUPPORTED(WRITE_PAGE_SCAN_ACTIVITY, WritePageScanActivity); SET_SUPPORTED(READ_INQUIRY_SCAN_ACTIVITY, ReadInquiryScanActivity); SET_SUPPORTED(WRITE_INQUIRY_SCAN_ACTIVITY, WriteInquiryScanActivity); SET_SUPPORTED(READ_SCAN_ENABLE, ReadScanEnable); SET_SUPPORTED(WRITE_SCAN_ENABLE, WriteScanEnable); SET_SUPPORTED(SET_EVENT_FILTER, SetEventFilter); SET_SUPPORTED(INQUIRY, Inquiry); SET_SUPPORTED(INQUIRY_CANCEL, InquiryCancel); SET_SUPPORTED(ACCEPT_CONNECTION_REQUEST, AcceptConnectionRequest); SET_SUPPORTED(REJECT_CONNECTION_REQUEST, RejectConnectionRequest); SET_SUPPORTED(LINK_KEY_REQUEST_REPLY, LinkKeyRequestReply); SET_SUPPORTED(LINK_KEY_REQUEST_NEGATIVE_REPLY, LinkKeyRequestNegativeReply); SET_SUPPORTED(DELETE_STORED_LINK_KEY, DeleteStoredLinkKey); SET_SUPPORTED(REMOTE_NAME_REQUEST, RemoteNameRequest); SET_SUPPORTED(LE_SET_EVENT_MASK, LeSetEventMask); SET_SUPPORTED(LE_SET_HOST_FEATURE, LeSetHostFeature); SET_SUPPORTED(LE_READ_BUFFER_SIZE_V1, LeReadBufferSize); SET_SUPPORTED(LE_READ_BUFFER_SIZE_V2, LeReadBufferSizeV2); SET_SUPPORTED(LE_READ_LOCAL_SUPPORTED_FEATURES, LeReadLocalSupportedFeatures); SET_SUPPORTED(LE_SET_RANDOM_ADDRESS, LeSetRandomAddress); SET_SUPPORTED(LE_SET_ADVERTISING_PARAMETERS, LeSetAdvertisingParameters); SET_SUPPORTED(LE_READ_ADVERTISING_PHYSICAL_CHANNEL_TX_POWER, LeReadAdvertisingPhysicalChannelTxPower); SET_SUPPORTED(LE_SET_ADVERTISING_DATA, LeSetAdvertisingData); SET_SUPPORTED(LE_SET_SCAN_RESPONSE_DATA, LeSetScanResponseData); SET_SUPPORTED(LE_SET_ADVERTISING_ENABLE, LeSetAdvertisingEnable); SET_SUPPORTED(LE_SET_SCAN_PARAMETERS, LeSetScanParameters); SET_SUPPORTED(LE_SET_SCAN_ENABLE, LeSetScanEnable); SET_SUPPORTED(LE_CREATE_CONNECTION, LeCreateConnection); SET_SUPPORTED(CREATE_CONNECTION, CreateConnection); SET_SUPPORTED(CREATE_CONNECTION_CANCEL, CreateConnectionCancel); SET_SUPPORTED(DISCONNECT, Disconnect); SET_SUPPORTED(LE_CREATE_CONNECTION_CANCEL, LeCreateConnectionCancel); SET_SUPPORTED(LE_READ_FILTER_ACCEPT_LIST_SIZE, LeReadFilterAcceptListSize); SET_SUPPORTED(LE_CLEAR_FILTER_ACCEPT_LIST, LeClearFilterAcceptList); SET_SUPPORTED(LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST, LeAddDeviceToFilterAcceptList); SET_SUPPORTED(LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST, LeRemoveDeviceFromFilterAcceptList); SET_SUPPORTED(LE_ENCRYPT, LeEncrypt); SET_SUPPORTED(LE_RAND, LeRand); SET_SUPPORTED(LE_READ_SUPPORTED_STATES, LeReadSupportedStates); SET_HANDLER(LE_GET_VENDOR_CAPABILITIES, LeVendorCap); SET_VENDOR_HANDLER(CSR_VENDOR, CsrVendorCommand); SET_HANDLER(LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY, LeRemoteConnectionParameterRequestReply); SET_HANDLER(LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY, LeRemoteConnectionParameterRequestNegativeReply); SET_HANDLER(LE_MULTI_ADVT, LeVendorMultiAdv); SET_HANDLER(LE_ADV_FILTER, LeAdvertisingFilter); SET_HANDLER(LE_ENERGY_INFO, LeEnergyInfo); SET_SUPPORTED(LE_SET_ADVERTISING_SET_RANDOM_ADDRESS, LeSetAdvertisingSetRandomAddress); SET_SUPPORTED(LE_SET_EXTENDED_ADVERTISING_PARAMETERS, LeSetExtendedAdvertisingParameters); SET_SUPPORTED(LE_SET_EXTENDED_ADVERTISING_DATA, LeSetExtendedAdvertisingData); SET_SUPPORTED(LE_SET_EXTENDED_SCAN_RESPONSE_DATA, LeSetExtendedScanResponseData); SET_SUPPORTED(LE_SET_EXTENDED_ADVERTISING_ENABLE, LeSetExtendedAdvertisingEnable); SET_SUPPORTED(LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH, LeReadMaximumAdvertisingDataLength); SET_SUPPORTED(LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS, LeReadNumberOfSupportedAdvertisingSets); SET_SUPPORTED(LE_REMOVE_ADVERTISING_SET, LeRemoveAdvertisingSet); SET_SUPPORTED(LE_CLEAR_ADVERTISING_SETS, LeClearAdvertisingSets); SET_SUPPORTED(LE_READ_REMOTE_FEATURES, LeReadRemoteFeatures); SET_SUPPORTED(READ_REMOTE_VERSION_INFORMATION, ReadRemoteVersionInformation); SET_SUPPORTED(LE_CONNECTION_UPDATE, LeConnectionUpdate); SET_SUPPORTED(LE_START_ENCRYPTION, LeStartEncryption); SET_SUPPORTED(LE_LONG_TERM_KEY_REQUEST_REPLY, LeLongTermKeyRequestReply); SET_SUPPORTED(LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY, LeLongTermKeyRequestNegativeReply); SET_SUPPORTED(LE_ADD_DEVICE_TO_RESOLVING_LIST, LeAddDeviceToResolvingList); SET_SUPPORTED(LE_REMOVE_DEVICE_FROM_RESOLVING_LIST, LeRemoveDeviceFromResolvingList); SET_SUPPORTED(LE_CLEAR_RESOLVING_LIST, LeClearResolvingList); SET_SUPPORTED(LE_READ_RESOLVING_LIST_SIZE, LeReadResolvingListSize); SET_SUPPORTED(LE_READ_MAXIMUM_DATA_LENGTH, LeReadMaximumDataLength); SET_SUPPORTED(LE_SET_EXTENDED_SCAN_PARAMETERS, LeSetExtendedScanParameters); SET_SUPPORTED(LE_SET_EXTENDED_SCAN_ENABLE, LeSetExtendedScanEnable); SET_SUPPORTED(LE_EXTENDED_CREATE_CONNECTION, LeExtendedCreateConnection); SET_SUPPORTED(LE_SET_PRIVACY_MODE, LeSetPrivacyMode); SET_SUPPORTED(LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH, LeReadSuggestedDefaultDataLength); SET_SUPPORTED(LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH, LeWriteSuggestedDefaultDataLength); // ISO Commands SET_SUPPORTED(LE_READ_ISO_TX_SYNC, LeReadIsoTxSync); SET_SUPPORTED(LE_SET_CIG_PARAMETERS, LeSetCigParameters); SET_SUPPORTED(LE_CREATE_CIS, LeCreateCis); SET_SUPPORTED(LE_REMOVE_CIG, LeRemoveCig); SET_SUPPORTED(LE_ACCEPT_CIS_REQUEST, LeAcceptCisRequest); SET_SUPPORTED(LE_REJECT_CIS_REQUEST, LeRejectCisRequest); SET_SUPPORTED(LE_CREATE_BIG, LeCreateBig); SET_SUPPORTED(LE_TERMINATE_BIG, LeTerminateBig); SET_SUPPORTED(LE_BIG_CREATE_SYNC, LeBigCreateSync); SET_SUPPORTED(LE_BIG_TERMINATE_SYNC, LeBigTerminateSync); SET_SUPPORTED(LE_REQUEST_PEER_SCA, LeRequestPeerSca); SET_SUPPORTED(LE_SETUP_ISO_DATA_PATH, LeSetupIsoDataPath); SET_SUPPORTED(LE_REMOVE_ISO_DATA_PATH, LeRemoveIsoDataPath); // Testing Commands SET_SUPPORTED(READ_LOOPBACK_MODE, ReadLoopbackMode); SET_SUPPORTED(WRITE_LOOPBACK_MODE, WriteLoopbackMode); SET_SUPPORTED(READ_CLASS_OF_DEVICE, ReadClassOfDevice); SET_SUPPORTED(READ_VOICE_SETTING, ReadVoiceSetting); SET_SUPPORTED(READ_CONNECTION_ACCEPT_TIMEOUT, ReadConnectionAcceptTimeout); SET_SUPPORTED(WRITE_CONNECTION_ACCEPT_TIMEOUT, WriteConnectionAcceptTimeout); SET_SUPPORTED(LE_SET_ADDRESS_RESOLUTION_ENABLE, LeSetAddressResolutionEnable); SET_SUPPORTED(LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT, LeSetResolvablePrivateAddressTimeout); SET_SUPPORTED(READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE, ReadSynchronousFlowControlEnable); SET_SUPPORTED(WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE, WriteSynchronousFlowControlEnable); #undef SET_HANDLER #undef SET_SUPPORTED properties_.SetSupportedCommands(supported_commands); } void DualModeController::SniffSubrating(CommandView command) { auto command_view = gd_hci::SniffSubratingView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); send_event_(gd_hci::SniffSubratingCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, command_view.GetConnectionHandle())); } void DualModeController::RegisterTaskScheduler( std::function oneshot_scheduler) { link_layer_controller_.RegisterTaskScheduler(oneshot_scheduler); } void DualModeController::RegisterPeriodicTaskScheduler( std::function periodic_scheduler) { link_layer_controller_.RegisterPeriodicTaskScheduler(periodic_scheduler); } void DualModeController::RegisterTaskCancel( std::function task_cancel) { link_layer_controller_.RegisterTaskCancel(task_cancel); } void DualModeController::HandleAcl( std::shared_ptr> packet) { bluetooth::hci::PacketView raw_packet(packet); auto acl_packet = bluetooth::hci::AclView::Create(raw_packet); ASSERT(acl_packet.IsValid()); if (loopback_mode_ == LoopbackMode::ENABLE_LOCAL) { uint16_t handle = acl_packet.GetHandle(); std::vector completed_packets; bluetooth::hci::CompletedPackets cp; cp.connection_handle_ = handle; cp.host_num_of_completed_packets_ = 1; completed_packets.push_back(cp); send_event_(bluetooth::hci::NumberOfCompletedPacketsBuilder::Create( completed_packets)); return; } link_layer_controller_.SendAclToRemote(acl_packet); } void DualModeController::HandleSco( std::shared_ptr> packet) { bluetooth::hci::PacketView raw_packet(packet); auto sco_packet = bluetooth::hci::ScoView::Create(raw_packet); ASSERT(sco_packet.IsValid()); if (loopback_mode_ == LoopbackMode::ENABLE_LOCAL) { uint16_t handle = sco_packet.GetHandle(); send_sco_(bluetooth::hci::ScoBuilder::Create( handle, sco_packet.GetPacketStatusFlag(), sco_packet.GetData())); std::vector completed_packets; bluetooth::hci::CompletedPackets cp; cp.connection_handle_ = handle; cp.host_num_of_completed_packets_ = 1; completed_packets.push_back(cp); if (link_layer_controller_.GetScoFlowControlEnable()) { send_event_(bluetooth::hci::NumberOfCompletedPacketsBuilder::Create( completed_packets)); } return; } link_layer_controller_.SendScoToRemote(sco_packet); } void DualModeController::HandleIso( std::shared_ptr> packet) { bluetooth::hci::PacketView raw_packet(packet); auto iso = bluetooth::hci::IsoView::Create(raw_packet); ASSERT(iso.IsValid()); link_layer_controller_.HandleIso(iso); } void DualModeController::HandleCommand( std::shared_ptr> packet) { bluetooth::hci::PacketView raw_packet(packet); auto command_packet = bluetooth::hci::CommandView::Create(raw_packet); ASSERT(command_packet.IsValid()); auto op = command_packet.GetOpCode(); if (loopback_mode_ == LoopbackMode::ENABLE_LOCAL && // Loopback exceptions. op != OpCode::RESET && op != OpCode::SET_CONTROLLER_TO_HOST_FLOW_CONTROL && op != OpCode::HOST_BUFFER_SIZE && op != OpCode::HOST_NUM_COMPLETED_PACKETS && op != OpCode::READ_BUFFER_SIZE && op != OpCode::READ_LOOPBACK_MODE && op != OpCode::WRITE_LOOPBACK_MODE) { std::unique_ptr raw_builder_ptr = std::make_unique(255); raw_builder_ptr->AddOctets(*packet); send_event_(bluetooth::hci::LoopbackCommandBuilder::Create( std::move(raw_builder_ptr))); } else if (active_hci_commands_.count(op) > 0) { active_hci_commands_[op](command_packet); } else { uint16_t opcode = static_cast(op); SendCommandCompleteUnknownOpCodeEvent(opcode); LOG_INFO("Unknown command, opcode: 0x%04X, OGF: 0x%04X, OCF: 0x%04X", opcode, (opcode & 0xFC00) >> 10, opcode & 0x03FF); } } void DualModeController::RegisterEventChannel( const std::function>)>& callback) { send_event_ = [callback](std::shared_ptr event) { auto bytes = std::make_shared>(); bluetooth::packet::BitInserter bit_inserter(*bytes); bytes->reserve(event->size()); event->Serialize(bit_inserter); callback(std::move(bytes)); }; link_layer_controller_.RegisterEventChannel(send_event_); } void DualModeController::RegisterAclChannel( const std::function>)>& callback) { send_acl_ = [callback](std::shared_ptr acl_data) { auto bytes = std::make_shared>(); bluetooth::packet::BitInserter bit_inserter(*bytes); bytes->reserve(acl_data->size()); acl_data->Serialize(bit_inserter); callback(std::move(bytes)); }; link_layer_controller_.RegisterAclChannel(send_acl_); } void DualModeController::RegisterScoChannel( const std::function>)>& callback) { send_sco_ = [callback](std::shared_ptr sco_data) { auto bytes = std::make_shared>(); bluetooth::packet::BitInserter bit_inserter(*bytes); bytes->reserve(sco_data->size()); sco_data->Serialize(bit_inserter); callback(std::move(bytes)); }; link_layer_controller_.RegisterScoChannel(send_sco_); } void DualModeController::RegisterIsoChannel( const std::function>)>& callback) { send_iso_ = [callback](std::shared_ptr iso_data) { auto bytes = std::make_shared>(); bluetooth::packet::BitInserter bit_inserter(*bytes); bytes->reserve(iso_data->size()); iso_data->Serialize(bit_inserter); callback(std::move(bytes)); }; link_layer_controller_.RegisterIsoChannel(send_iso_); } void DualModeController::Reset(CommandView command) { auto command_view = gd_hci::ResetView::Create(command); ASSERT(command_view.IsValid()); link_layer_controller_.Reset(); if (loopback_mode_ == LoopbackMode::ENABLE_LOCAL) { loopback_mode_ = LoopbackMode::NO_LOOPBACK; } send_event_(bluetooth::hci::ResetCompleteBuilder::Create(kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadBufferSize(CommandView command) { auto command_view = gd_hci::ReadBufferSizeView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadBufferSizeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, properties_.acl_data_packet_length, properties_.sco_data_packet_length, properties_.total_num_acl_data_packets, properties_.total_num_sco_data_packets)); } void DualModeController::ReadEncryptionKeySize(CommandView command) { auto command_view = gd_hci::ReadEncryptionKeySizeView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadEncryptionKeySizeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, command_view.GetConnectionHandle(), link_layer_controller_.GetEncryptionKeySize())); } void DualModeController::HostBufferSize(CommandView command) { auto command_view = gd_hci::HostBufferSizeView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::HostBufferSizeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadLocalVersionInformation(CommandView command) { auto command_view = gd_hci::ReadLocalVersionInformationView::Create(command); ASSERT(command_view.IsValid()); bluetooth::hci::LocalVersionInformation local_version_information; local_version_information.hci_version_ = properties_.hci_version; local_version_information.lmp_version_ = properties_.lmp_version; local_version_information.hci_revision_ = properties_.hci_subversion; local_version_information.lmp_subversion_ = properties_.lmp_subversion; local_version_information.manufacturer_name_ = properties_.company_identifier; send_event_( bluetooth::hci::ReadLocalVersionInformationCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, local_version_information)); } void DualModeController::ReadRemoteVersionInformation(CommandView command) { auto command_view = gd_hci::ReadRemoteVersionInformationView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.SendCommandToRemoteByHandle( OpCode::READ_REMOTE_VERSION_INFORMATION, command.GetPayload(), command_view.GetConnectionHandle()); send_event_(bluetooth::hci::ReadRemoteVersionInformationStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::ReadBdAddr(CommandView command) { auto command_view = gd_hci::ReadBdAddrView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadBdAddrCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, GetAddress())); } void DualModeController::ReadLocalSupportedCommands(CommandView command) { auto command_view = gd_hci::ReadLocalSupportedCommandsView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadLocalSupportedCommandsCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, properties_.supported_commands)); } void DualModeController::ReadLocalSupportedFeatures(CommandView command) { auto command_view = gd_hci::ReadLocalSupportedFeaturesView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadLocalSupportedFeaturesCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, link_layer_controller_.GetLmpFeatures())); } void DualModeController::ReadLocalSupportedCodecs(CommandView command) { auto command_view = gd_hci::ReadLocalSupportedCodecsV1View::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadLocalSupportedCodecsV1CompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, properties_.supported_standard_codecs, properties_.supported_vendor_specific_codecs)); } void DualModeController::ReadLocalExtendedFeatures(CommandView command) { auto command_view = gd_hci::ReadLocalExtendedFeaturesView::Create(command); ASSERT(command_view.IsValid()); uint8_t page_number = command_view.GetPageNumber(); send_event_(bluetooth::hci::ReadLocalExtendedFeaturesCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, page_number, link_layer_controller_.GetMaxLmpFeaturesPageNumber(), link_layer_controller_.GetLmpFeatures(page_number))); } void DualModeController::ReadRemoteExtendedFeatures(CommandView command) { auto command_view = gd_hci::ReadRemoteExtendedFeaturesView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.SendCommandToRemoteByHandle( OpCode::READ_REMOTE_EXTENDED_FEATURES, command_view.GetPayload(), command_view.GetConnectionHandle()); send_event_(bluetooth::hci::ReadRemoteExtendedFeaturesStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::SwitchRole(CommandView command) { auto command_view = gd_hci::SwitchRoleView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.SwitchRole(command_view.GetBdAddr(), command_view.GetRole()); send_event_(bluetooth::hci::SwitchRoleStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::ReadRemoteSupportedFeatures(CommandView command) { auto command_view = gd_hci::ReadRemoteSupportedFeaturesView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.SendCommandToRemoteByHandle( OpCode::READ_REMOTE_SUPPORTED_FEATURES, command_view.GetPayload(), command_view.GetConnectionHandle()); send_event_(bluetooth::hci::ReadRemoteSupportedFeaturesStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::ReadClockOffset(CommandView command) { auto command_view = gd_hci::ReadClockOffsetView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); auto status = link_layer_controller_.SendCommandToRemoteByHandle( OpCode::READ_CLOCK_OFFSET, command_view.GetPayload(), handle); send_event_(bluetooth::hci::ReadClockOffsetStatusBuilder::Create( status, kNumCommandPackets)); } // Deprecated command, removed in v4.2. // Support is provided to satisfy PTS tester requirements. void DualModeController::AddScoConnection(CommandView command) { auto command_view = gd_hci::AddScoConnectionView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.AddScoConnection( command_view.GetConnectionHandle(), command_view.GetPacketType(), ScoDatapath::NORMAL); send_event_(bluetooth::hci::AddScoConnectionStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::SetupSynchronousConnection(CommandView command) { auto command_view = gd_hci::SetupSynchronousConnectionView::Create( gd_hci::ScoConnectionCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.SetupSynchronousConnection( command_view.GetConnectionHandle(), command_view.GetTransmitBandwidth(), command_view.GetReceiveBandwidth(), command_view.GetMaxLatency(), command_view.GetVoiceSetting(), static_cast(command_view.GetRetransmissionEffort()), command_view.GetPacketType(), ScoDatapath::NORMAL); send_event_(bluetooth::hci::SetupSynchronousConnectionStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::AcceptSynchronousConnection(CommandView command) { auto command_view = gd_hci::AcceptSynchronousConnectionView::Create( gd_hci::ScoConnectionCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.AcceptSynchronousConnection( command_view.GetBdAddr(), command_view.GetTransmitBandwidth(), command_view.GetReceiveBandwidth(), command_view.GetMaxLatency(), command_view.GetVoiceSetting(), static_cast(command_view.GetRetransmissionEffort()), command_view.GetPacketType()); send_event_(bluetooth::hci::AcceptSynchronousConnectionStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::EnhancedSetupSynchronousConnection( CommandView command) { auto command_view = gd_hci::EnhancedSetupSynchronousConnectionView::Create( gd_hci::ScoConnectionCommandView::Create( gd_hci::AclCommandView::Create(command))); auto status = ErrorCode::SUCCESS; ASSERT(command_view.IsValid()); // The Host shall set the Transmit_Coding_Format and Receive_Coding_Formats // to be equal. auto transmit_coding_format = command_view.GetTransmitCodingFormat(); auto receive_coding_format = command_view.GetReceiveCodingFormat(); if (transmit_coding_format.coding_format_ != receive_coding_format.coding_format_ || transmit_coding_format.company_id_ != receive_coding_format.company_id_ || transmit_coding_format.vendor_specific_codec_id_ != receive_coding_format.vendor_specific_codec_id_) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Transmit_Coding_Format " "(%s)" " and Receive_Coding_Format (%s) as they are not equal", transmit_coding_format.ToString().c_str(), receive_coding_format.ToString().c_str()); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // The Host shall either set the Input_Bandwidth and Output_Bandwidth // to be equal, or shall set one of them to be zero and the other non-zero. auto input_bandwidth = command_view.GetInputBandwidth(); auto output_bandwidth = command_view.GetOutputBandwidth(); if (input_bandwidth != output_bandwidth && input_bandwidth != 0 && output_bandwidth != 0) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Input_Bandwidth (%u)" " and Output_Bandwidth (%u) as they are not equal and different from 0", input_bandwidth, output_bandwidth); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // The Host shall set the Input_Coding_Format and Output_Coding_Format // to be equal. auto input_coding_format = command_view.GetInputCodingFormat(); auto output_coding_format = command_view.GetOutputCodingFormat(); if (input_coding_format.coding_format_ != output_coding_format.coding_format_ || input_coding_format.company_id_ != output_coding_format.company_id_ || input_coding_format.vendor_specific_codec_id_ != output_coding_format.vendor_specific_codec_id_) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Input_Coding_Format (%s)" " and Output_Coding_Format (%s) as they are not equal", input_coding_format.ToString().c_str(), output_coding_format.ToString().c_str()); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // Root-Canal does not implement audio data transport paths other than the // default HCI transport - other transports will receive spoofed data ScoDatapath datapath = ScoDatapath::NORMAL; if (command_view.GetInputDataPath() != bluetooth::hci::ScoDataPath::HCI || command_view.GetOutputDataPath() != bluetooth::hci::ScoDataPath::HCI) { LOG_WARN( "EnhancedSetupSynchronousConnection: Input_Data_Path (%u)" " and/or Output_Data_Path (%u) are not over HCI, so data will be " "spoofed", static_cast(command_view.GetInputDataPath()), static_cast(command_view.GetOutputDataPath())); datapath = ScoDatapath::SPOOFED; } // Either both the Transmit_Coding_Format and Input_Coding_Format shall be // “transparent” or neither shall be. If both are “transparent”, the // Transmit_Bandwidth and the Input_Bandwidth shall be the same and the // Controller shall not modify the data sent to the remote device. auto transmit_bandwidth = command_view.GetTransmitBandwidth(); auto receive_bandwidth = command_view.GetReceiveBandwidth(); if (transmit_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && input_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && transmit_bandwidth != input_bandwidth) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Transmit_Bandwidth (%u)" " and Input_Bandwidth (%u) as they are not equal", transmit_bandwidth, input_bandwidth); LOG_INFO( "EnhancedSetupSynchronousConnection: the Transmit_Bandwidth and " "Input_Bandwidth shall be equal when both Transmit_Coding_Format " "and Input_Coding_Format are 'transparent'"); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } if ((transmit_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT) != (input_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT)) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Transmit_Coding_Format " "(%s) and Input_Coding_Format (%s) as they are incompatible", transmit_coding_format.ToString().c_str(), input_coding_format.ToString().c_str()); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // Either both the Receive_Coding_Format and Output_Coding_Format shall // be “transparent” or neither shall be. If both are “transparent”, the // Receive_Bandwidth and the Output_Bandwidth shall be the same and the // Controller shall not modify the data sent to the Host. if (receive_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && output_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && receive_bandwidth != output_bandwidth) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Receive_Bandwidth (%u)" " and Output_Bandwidth (%u) as they are not equal", receive_bandwidth, output_bandwidth); LOG_INFO( "EnhancedSetupSynchronousConnection: the Receive_Bandwidth and " "Output_Bandwidth shall be equal when both Receive_Coding_Format " "and Output_Coding_Format are 'transparent'"); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } if ((receive_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT) != (output_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT)) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Receive_Coding_Format " "(%s) and Output_Coding_Format (%s) as they are incompatible", receive_coding_format.ToString().c_str(), output_coding_format.ToString().c_str()); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } if (status == ErrorCode::SUCCESS) { status = link_layer_controller_.SetupSynchronousConnection( command_view.GetConnectionHandle(), transmit_bandwidth, receive_bandwidth, command_view.GetMaxLatency(), link_layer_controller_.GetVoiceSetting(), static_cast(command_view.GetRetransmissionEffort()), command_view.GetPacketType(), datapath); } send_event_( bluetooth::hci::EnhancedSetupSynchronousConnectionStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::EnhancedAcceptSynchronousConnection( CommandView command) { auto command_view = gd_hci::EnhancedAcceptSynchronousConnectionView::Create( gd_hci::ScoConnectionCommandView::Create( gd_hci::AclCommandView::Create(command))); auto status = ErrorCode::SUCCESS; ASSERT(command_view.IsValid()); // The Host shall set the Transmit_Coding_Format and Receive_Coding_Formats // to be equal. auto transmit_coding_format = command_view.GetTransmitCodingFormat(); auto receive_coding_format = command_view.GetReceiveCodingFormat(); if (transmit_coding_format.coding_format_ != receive_coding_format.coding_format_ || transmit_coding_format.company_id_ != receive_coding_format.company_id_ || transmit_coding_format.vendor_specific_codec_id_ != receive_coding_format.vendor_specific_codec_id_) { LOG_INFO( "EnhancedAcceptSynchronousConnection: rejected Transmit_Coding_Format " "(%s)" " and Receive_Coding_Format (%s) as they are not equal", transmit_coding_format.ToString().c_str(), receive_coding_format.ToString().c_str()); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // The Host shall either set the Input_Bandwidth and Output_Bandwidth // to be equal, or shall set one of them to be zero and the other non-zero. auto input_bandwidth = command_view.GetInputBandwidth(); auto output_bandwidth = command_view.GetOutputBandwidth(); if (input_bandwidth != output_bandwidth && input_bandwidth != 0 && output_bandwidth != 0) { LOG_INFO( "EnhancedAcceptSynchronousConnection: rejected Input_Bandwidth (%u)" " and Output_Bandwidth (%u) as they are not equal and different from 0", input_bandwidth, output_bandwidth); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // The Host shall set the Input_Coding_Format and Output_Coding_Format // to be equal. auto input_coding_format = command_view.GetInputCodingFormat(); auto output_coding_format = command_view.GetOutputCodingFormat(); if (input_coding_format.coding_format_ != output_coding_format.coding_format_ || input_coding_format.company_id_ != output_coding_format.company_id_ || input_coding_format.vendor_specific_codec_id_ != output_coding_format.vendor_specific_codec_id_) { LOG_INFO( "EnhancedAcceptSynchronousConnection: rejected Input_Coding_Format (%s)" " and Output_Coding_Format (%s) as they are not equal", input_coding_format.ToString().c_str(), output_coding_format.ToString().c_str()); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // Root-Canal does not implement audio data transport paths other than the // default HCI transport. if (command_view.GetInputDataPath() != bluetooth::hci::ScoDataPath::HCI || command_view.GetOutputDataPath() != bluetooth::hci::ScoDataPath::HCI) { LOG_INFO( "EnhancedSetupSynchronousConnection: Input_Data_Path (%u)" " and/or Output_Data_Path (%u) are not over HCI, so data will be " "spoofed", static_cast(command_view.GetInputDataPath()), static_cast(command_view.GetOutputDataPath())); } // Either both the Transmit_Coding_Format and Input_Coding_Format shall be // “transparent” or neither shall be. If both are “transparent”, the // Transmit_Bandwidth and the Input_Bandwidth shall be the same and the // Controller shall not modify the data sent to the remote device. auto transmit_bandwidth = command_view.GetTransmitBandwidth(); auto receive_bandwidth = command_view.GetReceiveBandwidth(); if (transmit_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && input_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && transmit_bandwidth != input_bandwidth) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Transmit_Bandwidth (%u)" " and Input_Bandwidth (%u) as they are not equal", transmit_bandwidth, input_bandwidth); LOG_INFO( "EnhancedSetupSynchronousConnection: the Transmit_Bandwidth and " "Input_Bandwidth shall be equal when both Transmit_Coding_Format " "and Input_Coding_Format are 'transparent'"); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } if ((transmit_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT) != (input_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT)) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Transmit_Coding_Format " "(%s) and Input_Coding_Format (%s) as they are incompatible", transmit_coding_format.ToString().c_str(), input_coding_format.ToString().c_str()); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } // Either both the Receive_Coding_Format and Output_Coding_Format shall // be “transparent” or neither shall be. If both are “transparent”, the // Receive_Bandwidth and the Output_Bandwidth shall be the same and the // Controller shall not modify the data sent to the Host. if (receive_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && output_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT && receive_bandwidth != output_bandwidth) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Receive_Bandwidth (%u)" " and Output_Bandwidth (%u) as they are not equal", receive_bandwidth, output_bandwidth); LOG_INFO( "EnhancedSetupSynchronousConnection: the Receive_Bandwidth and " "Output_Bandwidth shall be equal when both Receive_Coding_Format " "and Output_Coding_Format are 'transparent'"); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } if ((receive_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT) != (output_coding_format.coding_format_ == bluetooth::hci::ScoCodingFormatValues::TRANSPARENT)) { LOG_INFO( "EnhancedSetupSynchronousConnection: rejected Receive_Coding_Format " "(%s) and Output_Coding_Format (%s) as they are incompatible", receive_coding_format.ToString().c_str(), output_coding_format.ToString().c_str()); status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } if (status == ErrorCode::SUCCESS) { status = link_layer_controller_.AcceptSynchronousConnection( command_view.GetBdAddr(), transmit_bandwidth, receive_bandwidth, command_view.GetMaxLatency(), link_layer_controller_.GetVoiceSetting(), static_cast(command_view.GetRetransmissionEffort()), command_view.GetPacketType()); } send_event_( bluetooth::hci::EnhancedAcceptSynchronousConnectionStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::RejectSynchronousConnection(CommandView command) { auto command_view = gd_hci::RejectSynchronousConnectionView::Create( gd_hci::ScoConnectionCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.RejectSynchronousConnection( command_view.GetBdAddr(), (uint16_t)command_view.GetReason()); send_event_(bluetooth::hci::RejectSynchronousConnectionStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::IoCapabilityRequestReply(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::IoCapabilityRequestReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address peer = command_view.GetBdAddr(); uint8_t io_capability = static_cast(command_view.GetIoCapability()); uint8_t oob_data_present_flag = static_cast(command_view.GetOobPresent()); uint8_t authentication_requirements = static_cast(command_view.GetAuthenticationRequirements()); auto status = link_layer_controller_.IoCapabilityRequestReply( peer, io_capability, oob_data_present_flag, authentication_requirements); send_event_(bluetooth::hci::IoCapabilityRequestReplyCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::UserConfirmationRequestReply(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::UserConfirmationRequestReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address peer = command_view.GetBdAddr(); auto status = link_layer_controller_.UserConfirmationRequestReply(peer); send_event_( bluetooth::hci::UserConfirmationRequestReplyCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::UserConfirmationRequestNegativeReply( CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::UserConfirmationRequestNegativeReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address peer = command_view.GetBdAddr(); auto status = link_layer_controller_.UserConfirmationRequestNegativeReply(peer); send_event_( bluetooth::hci::UserConfirmationRequestNegativeReplyCompleteBuilder:: Create(kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::PinCodeRequestReply(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::PinCodeRequestReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); LOG_INFO("%s", GetAddress().ToString().c_str()); Address peer = command_view.GetBdAddr(); uint8_t pin_length = command_view.GetPinCodeLength(); std::array pin = command_view.GetPinCode(); ErrorCode status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; if (pin_length >= 1 && pin_length <= 0x10) { status = link_layer_controller_.PinCodeRequestReply( peer, std::vector(pin.begin(), pin.begin() + pin_length)); } send_event_(bluetooth::hci::PinCodeRequestReplyCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::PinCodeRequestNegativeReply(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::PinCodeRequestNegativeReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); LOG_INFO("%s", GetAddress().ToString().c_str()); Address peer = command_view.GetBdAddr(); auto status = link_layer_controller_.PinCodeRequestNegativeReply(peer); send_event_( bluetooth::hci::PinCodeRequestNegativeReplyCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::UserPasskeyRequestReply(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::UserPasskeyRequestReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address peer = command_view.GetBdAddr(); uint32_t numeric_value = command_view.GetNumericValue(); auto status = link_layer_controller_.UserPasskeyRequestReply(peer, numeric_value); send_event_(bluetooth::hci::UserPasskeyRequestReplyCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::UserPasskeyRequestNegativeReply(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::UserPasskeyRequestNegativeReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address peer = command_view.GetBdAddr(); auto status = link_layer_controller_.UserPasskeyRequestNegativeReply(peer); send_event_( bluetooth::hci::UserPasskeyRequestNegativeReplyCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::RemoteOobDataRequestReply(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::RemoteOobDataRequestReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address peer = command_view.GetBdAddr(); auto status = link_layer_controller_.RemoteOobDataRequestReply( peer, command_view.GetC(), command_view.GetR()); send_event_(bluetooth::hci::RemoteOobDataRequestReplyCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::RemoteOobDataRequestNegativeReply( CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::RemoteOobDataRequestNegativeReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address peer = command_view.GetBdAddr(); auto status = link_layer_controller_.RemoteOobDataRequestNegativeReply(peer); send_event_( bluetooth::hci::RemoteOobDataRequestNegativeReplyCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::IoCapabilityRequestNegativeReply(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::IoCapabilityRequestNegativeReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address peer = command_view.GetBdAddr(); ErrorCode reason = command_view.GetReason(); auto status = link_layer_controller_.IoCapabilityRequestNegativeReply(peer, reason); send_event_( bluetooth::hci::IoCapabilityRequestNegativeReplyCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::RemoteOobExtendedDataRequestReply( CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::RemoteOobExtendedDataRequestReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address peer = command_view.GetBdAddr(); auto status = link_layer_controller_.RemoteOobExtendedDataRequestReply( peer, command_view.GetC192(), command_view.GetR192(), command_view.GetC256(), command_view.GetR256()); send_event_( bluetooth::hci::RemoteOobExtendedDataRequestReplyCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::ReadInquiryResponseTransmitPowerLevel( CommandView command) { auto command_view = gd_hci::ReadInquiryResponseTransmitPowerLevelView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); uint8_t tx_power = 20; // maximum send_event_( bluetooth::hci::ReadInquiryResponseTransmitPowerLevelCompleteBuilder:: Create(kNumCommandPackets, ErrorCode::SUCCESS, tx_power)); } void DualModeController::SendKeypressNotification(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::SendKeypressNotificationView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); auto peer = command_view.GetBdAddr(); auto status = link_layer_controller_.SendKeypressNotification( peer, command_view.GetNotificationType()); send_event_(bluetooth::hci::SendKeypressNotificationCompleteBuilder::Create( kNumCommandPackets, status, peer)); #endif /* ROOTCANAL_LMP */ } void DualModeController::EnhancedFlush(CommandView command) { auto command_view = bluetooth::hci::EnhancedFlushView::Create(command); ASSERT(command_view.IsValid()); auto handle = command_view.GetConnectionHandle(); send_event_(bluetooth::hci::EnhancedFlushStatusBuilder::Create( ErrorCode::SUCCESS, kNumCommandPackets)); // TODO: When adding a queue of ACL packets. // Send the Enhanced Flush Complete event after discarding // all L2CAP packets identified by the Packet Type. if (link_layer_controller_.IsEventUnmasked( gd_hci::EventCode::ENHANCED_FLUSH_COMPLETE)) { send_event_(bluetooth::hci::EnhancedFlushCompleteBuilder::Create(handle)); } } void DualModeController::SetEventMaskPage2(CommandView command) { auto command_view = bluetooth::hci::SetEventMaskPage2View::Create(command); ASSERT(command_view.IsValid()); link_layer_controller_.SetEventMaskPage2(command_view.GetEventMaskPage2()); send_event_(bluetooth::hci::SetEventMaskPage2CompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadLocalOobData(CommandView command) { auto command_view = gd_hci::ReadLocalOobDataView::Create( gd_hci::SecurityCommandView::Create(command)); link_layer_controller_.ReadLocalOobData(); } void DualModeController::ReadLocalOobExtendedData(CommandView command) { auto command_view = gd_hci::ReadLocalOobExtendedDataView::Create( gd_hci::SecurityCommandView::Create(command)); link_layer_controller_.ReadLocalOobExtendedData(); } void DualModeController::WriteSimplePairingMode(CommandView command) { auto command_view = gd_hci::WriteSimplePairingModeView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); auto enabled = command_view.GetSimplePairingMode() == gd_hci::Enable::ENABLED; link_layer_controller_.SetSecureSimplePairingSupport(enabled); send_event_(bluetooth::hci::WriteSimplePairingModeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ChangeConnectionPacketType(CommandView command) { auto command_view = gd_hci::ChangeConnectionPacketTypeView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); uint16_t packet_type = static_cast(command_view.GetPacketType()); auto status = link_layer_controller_.ChangeConnectionPacketType(handle, packet_type); send_event_(bluetooth::hci::ChangeConnectionPacketTypeStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::WriteLeHostSupport(CommandView command) { auto command_view = gd_hci::WriteLeHostSupportView::Create(command); ASSERT(command_view.IsValid()); auto le_support = command_view.GetLeSupportedHost() == gd_hci::Enable::ENABLED; link_layer_controller_.SetLeHostSupport(le_support); send_event_(bluetooth::hci::WriteLeHostSupportCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::WriteSecureConnectionsHostSupport( CommandView command) { auto command_view = gd_hci::WriteSecureConnectionsHostSupportView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.SetSecureConnectionsSupport( command_view.GetSecureConnectionsHostSupport() == bluetooth::hci::Enable::ENABLED); send_event_( bluetooth::hci::WriteSecureConnectionsHostSupportCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::SetEventMask(CommandView command) { auto command_view = gd_hci::SetEventMaskView::Create(command); ASSERT(command_view.IsValid()); link_layer_controller_.SetEventMask(command_view.GetEventMask()); send_event_(bluetooth::hci::SetEventMaskCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadInquiryMode(CommandView command) { auto command_view = gd_hci::ReadInquiryModeView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); gd_hci::InquiryMode inquiry_mode = gd_hci::InquiryMode::STANDARD; send_event_(bluetooth::hci::ReadInquiryModeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, inquiry_mode)); } void DualModeController::WriteInquiryMode(CommandView command) { auto command_view = gd_hci::WriteInquiryModeView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.SetInquiryMode( static_cast(command_view.GetInquiryMode())); send_event_(bluetooth::hci::WriteInquiryModeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadPageScanType(CommandView command) { auto command_view = gd_hci::ReadPageScanTypeView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); gd_hci::PageScanType page_scan_type = gd_hci::PageScanType::STANDARD; send_event_(bluetooth::hci::ReadPageScanTypeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, page_scan_type)); } void DualModeController::WritePageScanType(CommandView command) { auto command_view = gd_hci::WritePageScanTypeView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::WritePageScanTypeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadInquiryScanType(CommandView command) { auto command_view = gd_hci::ReadInquiryScanTypeView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); gd_hci::InquiryScanType inquiry_scan_type = gd_hci::InquiryScanType::STANDARD; send_event_(bluetooth::hci::ReadInquiryScanTypeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, inquiry_scan_type)); } void DualModeController::WriteInquiryScanType(CommandView command) { auto command_view = gd_hci::WriteInquiryScanTypeView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::WriteInquiryScanTypeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::AuthenticationRequested(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::AuthenticationRequestedView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); auto status = link_layer_controller_.AuthenticationRequested(handle); send_event_(bluetooth::hci::AuthenticationRequestedStatusBuilder::Create( status, kNumCommandPackets)); #endif /* ROOTCANAL_LMP */ } void DualModeController::SetConnectionEncryption(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::SetConnectionEncryptionView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); uint8_t encryption_enable = static_cast(command_view.GetEncryptionEnable()); auto status = link_layer_controller_.SetConnectionEncryption(handle, encryption_enable); send_event_(bluetooth::hci::SetConnectionEncryptionStatusBuilder::Create( status, kNumCommandPackets)); #endif /* ROOTCANAL_LMP */ } void DualModeController::ChangeConnectionLinkKey(CommandView command) { auto command_view = gd_hci::ChangeConnectionLinkKeyView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); auto status = link_layer_controller_.ChangeConnectionLinkKey(handle); send_event_(bluetooth::hci::ChangeConnectionLinkKeyStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::CentralLinkKey(CommandView command) { auto command_view = gd_hci::CentralLinkKeyView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint8_t key_flag = static_cast(command_view.GetKeyFlag()); auto status = link_layer_controller_.CentralLinkKey(key_flag); send_event_(bluetooth::hci::CentralLinkKeyStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::WriteAuthenticationEnable(CommandView command) { auto command_view = gd_hci::WriteAuthenticationEnableView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.SetAuthenticationEnable( command_view.GetAuthenticationEnable()); send_event_(bluetooth::hci::WriteAuthenticationEnableCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadAuthenticationEnable(CommandView command) { auto command_view = gd_hci::ReadAuthenticationEnableView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadAuthenticationEnableCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, static_cast( link_layer_controller_.GetAuthenticationEnable()))); } void DualModeController::WriteClassOfDevice(CommandView command) { auto command_view = gd_hci::WriteClassOfDeviceView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.SetClassOfDevice(command_view.GetClassOfDevice()); send_event_(bluetooth::hci::WriteClassOfDeviceCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadPageTimeout(CommandView command) { auto command_view = gd_hci::ReadPageTimeoutView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); uint16_t page_timeout = link_layer_controller_.GetPageTimeout(); send_event_(bluetooth::hci::ReadPageTimeoutCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, page_timeout)); } void DualModeController::WritePageTimeout(CommandView command) { auto command_view = gd_hci::WritePageTimeoutView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.SetPageTimeout(command_view.GetPageTimeout()); send_event_(bluetooth::hci::WritePageTimeoutCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::HoldMode(CommandView command) { auto command_view = gd_hci::HoldModeView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); uint16_t hold_mode_max_interval = command_view.GetHoldModeMaxInterval(); uint16_t hold_mode_min_interval = command_view.GetHoldModeMinInterval(); auto status = link_layer_controller_.HoldMode(handle, hold_mode_max_interval, hold_mode_min_interval); send_event_(bluetooth::hci::HoldModeStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::SniffMode(CommandView command) { auto command_view = gd_hci::SniffModeView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); uint16_t sniff_max_interval = command_view.GetSniffMaxInterval(); uint16_t sniff_min_interval = command_view.GetSniffMinInterval(); uint16_t sniff_attempt = command_view.GetSniffAttempt(); uint16_t sniff_timeout = command_view.GetSniffTimeout(); auto status = link_layer_controller_.SniffMode(handle, sniff_max_interval, sniff_min_interval, sniff_attempt, sniff_timeout); send_event_(bluetooth::hci::SniffModeStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::ExitSniffMode(CommandView command) { auto command_view = gd_hci::ExitSniffModeView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.ExitSniffMode(command_view.GetConnectionHandle()); send_event_(bluetooth::hci::ExitSniffModeStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::QosSetup(CommandView command) { auto command_view = gd_hci::QosSetupView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); uint8_t service_type = static_cast(command_view.GetServiceType()); uint32_t token_rate = command_view.GetTokenRate(); uint32_t peak_bandwidth = command_view.GetPeakBandwidth(); uint32_t latency = command_view.GetLatency(); uint32_t delay_variation = command_view.GetDelayVariation(); auto status = link_layer_controller_.QosSetup(handle, service_type, token_rate, peak_bandwidth, latency, delay_variation); send_event_(bluetooth::hci::QosSetupStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::RoleDiscovery(CommandView command) { auto command_view = gd_hci::RoleDiscoveryView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); auto role = bluetooth::hci::Role::CENTRAL; auto status = link_layer_controller_.RoleDiscovery(handle, &role); send_event_(bluetooth::hci::RoleDiscoveryCompleteBuilder::Create( kNumCommandPackets, status, handle, role)); } void DualModeController::ReadDefaultLinkPolicySettings(CommandView command) { auto command_view = gd_hci::ReadDefaultLinkPolicySettingsView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t settings = link_layer_controller_.ReadDefaultLinkPolicySettings(); send_event_( bluetooth::hci::ReadDefaultLinkPolicySettingsCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, settings)); } void DualModeController::WriteDefaultLinkPolicySettings(CommandView command) { auto command_view = gd_hci::WriteDefaultLinkPolicySettingsView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.WriteDefaultLinkPolicySettings( command_view.GetDefaultLinkPolicySettings()); send_event_( bluetooth::hci::WriteDefaultLinkPolicySettingsCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::FlowSpecification(CommandView command) { auto command_view = gd_hci::FlowSpecificationView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); uint8_t flow_direction = static_cast(command_view.GetFlowDirection()); uint8_t service_type = static_cast(command_view.GetServiceType()); uint32_t token_rate = command_view.GetTokenRate(); uint32_t token_bucket_size = command_view.GetTokenBucketSize(); uint32_t peak_bandwidth = command_view.GetPeakBandwidth(); uint32_t access_latency = command_view.GetAccessLatency(); auto status = link_layer_controller_.FlowSpecification( handle, flow_direction, service_type, token_rate, token_bucket_size, peak_bandwidth, access_latency); send_event_(bluetooth::hci::FlowSpecificationStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::ReadLinkPolicySettings(CommandView command) { auto command_view = gd_hci::ReadLinkPolicySettingsView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); uint16_t settings; auto status = link_layer_controller_.ReadLinkPolicySettings(handle, &settings); send_event_(bluetooth::hci::ReadLinkPolicySettingsCompleteBuilder::Create( kNumCommandPackets, status, handle, settings)); } void DualModeController::WriteLinkPolicySettings(CommandView command) { auto command_view = gd_hci::WriteLinkPolicySettingsView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); uint16_t settings = command_view.GetLinkPolicySettings(); auto status = link_layer_controller_.WriteLinkPolicySettings(handle, settings); send_event_(bluetooth::hci::WriteLinkPolicySettingsCompleteBuilder::Create( kNumCommandPackets, status, handle)); } void DualModeController::WriteLinkSupervisionTimeout(CommandView command) { auto command_view = gd_hci::WriteLinkSupervisionTimeoutView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); uint16_t timeout = command_view.GetLinkSupervisionTimeout(); auto status = link_layer_controller_.WriteLinkSupervisionTimeout(handle, timeout); send_event_( bluetooth::hci::WriteLinkSupervisionTimeoutCompleteBuilder::Create( kNumCommandPackets, status, handle)); } void DualModeController::ReadLocalName(CommandView command) { auto command_view = gd_hci::ReadLocalNameView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadLocalNameCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, link_layer_controller_.GetLocalName())); } void DualModeController::WriteLocalName(CommandView command) { auto command_view = gd_hci::WriteLocalNameView::Create(command); ASSERT(command_view.IsValid()); link_layer_controller_.SetLocalName(command_view.GetLocalName()); send_event_(bluetooth::hci::WriteLocalNameCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::WriteExtendedInquiryResponse(CommandView command) { auto command_view = gd_hci::WriteExtendedInquiryResponseView::Create(command); ASSERT(command_view.IsValid()); link_layer_controller_.SetExtendedInquiryResponse(std::vector( command_view.GetPayload().begin() + 1, command_view.GetPayload().end())); send_event_( bluetooth::hci::WriteExtendedInquiryResponseCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::RefreshEncryptionKey(CommandView command) { auto command_view = gd_hci::RefreshEncryptionKeyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); send_event_(bluetooth::hci::RefreshEncryptionKeyStatusBuilder::Create( ErrorCode::SUCCESS, kNumCommandPackets)); // TODO: Support this in the link layer send_event_(bluetooth::hci::EncryptionKeyRefreshCompleteBuilder::Create( ErrorCode::SUCCESS, handle)); } void DualModeController::WriteVoiceSetting(CommandView command) { auto command_view = gd_hci::WriteVoiceSettingView::Create(command); ASSERT(command_view.IsValid()); link_layer_controller_.SetVoiceSetting(command_view.GetVoiceSetting()); send_event_(bluetooth::hci::WriteVoiceSettingCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadNumberOfSupportedIac(CommandView command) { auto command_view = gd_hci::ReadNumberOfSupportedIacView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadNumberOfSupportedIacCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, properties_.num_supported_iac)); } void DualModeController::ReadCurrentIacLap(CommandView command) { auto command_view = gd_hci::ReadCurrentIacLapView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadCurrentIacLapCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, link_layer_controller_.ReadCurrentIacLap())); } void DualModeController::WriteCurrentIacLap(CommandView command) { auto command_view = gd_hci::WriteCurrentIacLapView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.WriteCurrentIacLap(command_view.GetLapsToWrite()); send_event_(bluetooth::hci::WriteCurrentIacLapCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadPageScanActivity(CommandView command) { auto command_view = gd_hci::ReadPageScanActivityView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); uint16_t interval = 0x1000; uint16_t window = 0x0012; send_event_(bluetooth::hci::ReadPageScanActivityCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, interval, window)); } void DualModeController::WritePageScanActivity(CommandView command) { auto command_view = gd_hci::WritePageScanActivityView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::WritePageScanActivityCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadInquiryScanActivity(CommandView command) { auto command_view = gd_hci::ReadInquiryScanActivityView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); uint16_t interval = 0x1000; uint16_t window = 0x0012; send_event_(bluetooth::hci::ReadInquiryScanActivityCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, interval, window)); } void DualModeController::WriteInquiryScanActivity(CommandView command) { auto command_view = gd_hci::WriteInquiryScanActivityView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::WriteInquiryScanActivityCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadScanEnable(CommandView command) { auto command_view = gd_hci::ReadScanEnableView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); bool inquiry_scan = link_layer_controller_.GetInquiryScanEnable(); bool page_scan = link_layer_controller_.GetPageScanEnable(); bluetooth::hci::ScanEnable scan_enable = inquiry_scan && page_scan ? bluetooth::hci::ScanEnable::INQUIRY_AND_PAGE_SCAN : inquiry_scan ? bluetooth::hci::ScanEnable::INQUIRY_SCAN_ONLY : page_scan ? bluetooth::hci::ScanEnable::PAGE_SCAN_ONLY : bluetooth::hci::ScanEnable::NO_SCANS; send_event_(bluetooth::hci::ReadScanEnableCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, scan_enable)); } void DualModeController::WriteScanEnable(CommandView command) { auto command_view = gd_hci::WriteScanEnableView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); gd_hci::ScanEnable scan_enable = command_view.GetScanEnable(); bool inquiry_scan = scan_enable == gd_hci::ScanEnable::INQUIRY_AND_PAGE_SCAN || scan_enable == gd_hci::ScanEnable::INQUIRY_SCAN_ONLY; bool page_scan = scan_enable == gd_hci::ScanEnable::INQUIRY_AND_PAGE_SCAN || scan_enable == gd_hci::ScanEnable::PAGE_SCAN_ONLY; LOG_INFO("%s | WriteScanEnable %s", GetAddress().ToString().c_str(), gd_hci::ScanEnableText(scan_enable).c_str()); link_layer_controller_.SetInquiryScanEnable(inquiry_scan); link_layer_controller_.SetPageScanEnable(page_scan); send_event_(bluetooth::hci::WriteScanEnableCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadSynchronousFlowControlEnable(CommandView command) { auto command_view = gd_hci::ReadSynchronousFlowControlEnableView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); auto enabled = bluetooth::hci::Enable::DISABLED; if (link_layer_controller_.GetScoFlowControlEnable()) { enabled = bluetooth::hci::Enable::ENABLED; } send_event_( bluetooth::hci::ReadSynchronousFlowControlEnableCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, enabled)); } void DualModeController::WriteSynchronousFlowControlEnable( CommandView command) { auto command_view = gd_hci::WriteSynchronousFlowControlEnableView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); auto enabled = command_view.GetEnable() == bluetooth::hci::Enable::ENABLED; link_layer_controller_.SetScoFlowControlEnable(enabled); send_event_( bluetooth::hci::WriteSynchronousFlowControlEnableCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::SetEventFilter(CommandView command) { auto command_view = gd_hci::SetEventFilterView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::SetEventFilterCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::Inquiry(CommandView command) { auto command_view = gd_hci::InquiryView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); auto max_responses = command_view.GetNumResponses(); auto length = command_view.GetInquiryLength(); if (max_responses > 0xff || length < 1 || length > 0x30) { send_event_(bluetooth::hci::InquiryStatusBuilder::Create( ErrorCode::INVALID_HCI_COMMAND_PARAMETERS, kNumCommandPackets)); return; } link_layer_controller_.SetInquiryLAP(command_view.GetLap().lap_); link_layer_controller_.SetInquiryMaxResponses(max_responses); link_layer_controller_.StartInquiry(std::chrono::milliseconds(length * 1280)); send_event_(bluetooth::hci::InquiryStatusBuilder::Create(ErrorCode::SUCCESS, kNumCommandPackets)); } void DualModeController::InquiryCancel(CommandView command) { auto command_view = gd_hci::InquiryCancelView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.InquiryCancel(); send_event_(bluetooth::hci::InquiryCancelCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::AcceptConnectionRequest(CommandView command) { auto command_view = gd_hci::AcceptConnectionRequestView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); Address addr = command_view.GetBdAddr(); bool try_role_switch = command_view.GetRole() == gd_hci::AcceptConnectionRequestRole::BECOME_CENTRAL; auto status = link_layer_controller_.AcceptConnectionRequest(addr, try_role_switch); send_event_(bluetooth::hci::AcceptConnectionRequestStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::RejectConnectionRequest(CommandView command) { auto command_view = gd_hci::RejectConnectionRequestView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); Address addr = command_view.GetBdAddr(); uint8_t reason = static_cast(command_view.GetReason()); auto status = link_layer_controller_.RejectConnectionRequest(addr, reason); send_event_(bluetooth::hci::RejectConnectionRequestStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LinkKeyRequestReply(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::LinkKeyRequestReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address addr = command_view.GetBdAddr(); auto key = command_view.GetLinkKey(); auto status = link_layer_controller_.LinkKeyRequestReply(addr, key); send_event_(bluetooth::hci::LinkKeyRequestReplyCompleteBuilder::Create( kNumCommandPackets, status, addr)); #endif /* ROOTCANAL_LMP */ } void DualModeController::LinkKeyRequestNegativeReply(CommandView command) { #ifdef ROOTCANAL_LMP link_layer_controller_.ForwardToLm(command); #else auto command_view = gd_hci::LinkKeyRequestNegativeReplyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); Address addr = command_view.GetBdAddr(); auto status = link_layer_controller_.LinkKeyRequestNegativeReply(addr); send_event_( bluetooth::hci::LinkKeyRequestNegativeReplyCompleteBuilder::Create( kNumCommandPackets, status, addr)); #endif /* ROOTCANAL_LMP */ } void DualModeController::DeleteStoredLinkKey(CommandView command) { auto command_view = gd_hci::DeleteStoredLinkKeyView::Create( gd_hci::SecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); uint16_t deleted_keys = 0; auto flag = command_view.GetDeleteAllFlag(); if (flag == gd_hci::DeleteStoredLinkKeyDeleteAllFlag::SPECIFIED_BD_ADDR) { Address addr = command_view.GetBdAddr(); #ifndef ROOTCANAL_LMP deleted_keys = security_manager_.DeleteKey(addr); #endif /* !ROOTCANAL_LMP */ } if (flag == gd_hci::DeleteStoredLinkKeyDeleteAllFlag::ALL) { #ifndef ROOTCANAL_LMP security_manager_.DeleteAllKeys(); #endif /* !ROOTCANAL_LMP */ } send_event_(bluetooth::hci::DeleteStoredLinkKeyCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, deleted_keys)); } void DualModeController::RemoteNameRequest(CommandView command) { auto command_view = gd_hci::RemoteNameRequestView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); Address remote_addr = command_view.GetBdAddr(); auto status = link_layer_controller_.SendCommandToRemoteByAddress( OpCode::REMOTE_NAME_REQUEST, command_view.GetPayload(), GetAddress(), remote_addr); send_event_(bluetooth::hci::RemoteNameRequestStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeSetEventMask(CommandView command) { auto command_view = gd_hci::LeSetEventMaskView::Create(command); ASSERT(command_view.IsValid()); link_layer_controller_.SetLeEventMask(command_view.GetLeEventMask()); send_event_(bluetooth::hci::LeSetEventMaskCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::LeSetHostFeature(CommandView command) { auto command_view = gd_hci::LeSetHostFeatureView::Create(command); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetHostFeature( static_cast(command_view.GetBitNumber()), static_cast(command_view.GetBitValue())); send_event_(bluetooth::hci::LeSetHostFeatureCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeReadBufferSize(CommandView command) { auto command_view = gd_hci::LeReadBufferSizeV1View::Create(command); ASSERT(command_view.IsValid()); bluetooth::hci::LeBufferSize le_buffer_size; le_buffer_size.le_data_packet_length_ = properties_.le_acl_data_packet_length; le_buffer_size.total_num_le_packets_ = properties_.total_num_le_acl_data_packets; send_event_(bluetooth::hci::LeReadBufferSizeV1CompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, le_buffer_size)); } void DualModeController::LeReadBufferSizeV2(CommandView command) { auto command_view = gd_hci::LeReadBufferSizeV2View::Create(command); ASSERT(command_view.IsValid()); bluetooth::hci::LeBufferSize le_buffer_size; le_buffer_size.le_data_packet_length_ = properties_.le_acl_data_packet_length; le_buffer_size.total_num_le_packets_ = properties_.total_num_le_acl_data_packets; bluetooth::hci::LeBufferSize iso_buffer_size; iso_buffer_size.le_data_packet_length_ = properties_.iso_data_packet_length; iso_buffer_size.total_num_le_packets_ = properties_.total_num_iso_data_packets; send_event_(bluetooth::hci::LeReadBufferSizeV2CompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, le_buffer_size, iso_buffer_size)); } void DualModeController::LeSetAddressResolutionEnable(CommandView command) { auto command_view = gd_hci::LeSetAddressResolutionEnableView::Create( gd_hci::LeSecurityCommandView::Create( gd_hci::SecurityCommandView::Create(command))); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetAddressResolutionEnable( command_view.GetAddressResolutionEnable() == bluetooth::hci::Enable::ENABLED); send_event_( bluetooth::hci::LeSetAddressResolutionEnableCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetResolvablePrivateAddressTimeout( CommandView command) { auto command_view = bluetooth::hci::LeSetResolvablePrivateAddressTimeoutView::Create( bluetooth::hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetResolvablePrivateAddressTimeout( command_view.GetRpaTimeout()); send_event_( bluetooth::hci::LeSetResolvablePrivateAddressTimeoutCompleteBuilder:: Create(kNumCommandPackets, status)); } void DualModeController::LeReadLocalSupportedFeatures(CommandView command) { auto command_view = gd_hci::LeReadLocalSupportedFeaturesView::Create(command); ASSERT(command_view.IsValid()); LOG_INFO("%s | LeReadLocalSupportedFeatures (%016llx)", GetAddress().ToString().c_str(), static_cast(properties_.le_features)); send_event_( bluetooth::hci::LeReadLocalSupportedFeaturesCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, properties_.le_features)); } void DualModeController::LeSetRandomAddress(CommandView command) { auto command_view = gd_hci::LeSetRandomAddressView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetRandomAddress( command_view.GetRandomAddress()); send_event_(bluetooth::hci::LeSetRandomAddressCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetAdvertisingParameters(CommandView command) { auto command_view = gd_hci::LeSetAdvertisingParametersView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetAdvertisingParameters( command_view.GetAdvertisingIntervalMin(), command_view.GetAdvertisingIntervalMax(), command_view.GetAdvertisingType(), command_view.GetOwnAddressType(), command_view.GetPeerAddressType(), command_view.GetPeerAddress(), command_view.GetAdvertisingChannelMap(), command_view.GetAdvertisingFilterPolicy()); send_event_(bluetooth::hci::LeSetAdvertisingParametersCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeReadAdvertisingPhysicalChannelTxPower( CommandView command) { auto command_view = gd_hci::LeReadAdvertisingPhysicalChannelTxPowerView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_( bluetooth::hci::LeReadAdvertisingPhysicalChannelTxPowerCompleteBuilder:: Create(kNumCommandPackets, ErrorCode::SUCCESS, properties_.le_advertising_physical_channel_tx_power)); } void DualModeController::LeSetAdvertisingData(CommandView command) { auto command_view = gd_hci::LeSetAdvertisingDataView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); auto payload = command.GetPayload(); auto data_size = *payload.begin(); auto first_data = payload.begin() + 1; std::vector advertising_data{first_data, first_data + data_size}; ASSERT_LOG(command_view.IsValid(), "%s command.size() = %zu", gd_hci::OpCodeText(command.GetOpCode()).c_str(), command.size()); ASSERT(command_view.GetPayload().size() == 32); ErrorCode status = link_layer_controller_.LeSetAdvertisingData(advertising_data); send_event_(bluetooth::hci::LeSetAdvertisingDataCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetScanResponseData(CommandView command) { auto command_view = gd_hci::LeSetScanResponseDataView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ASSERT(command_view.GetPayload().size() == 32); ErrorCode status = link_layer_controller_.LeSetScanResponseData( std::vector(command_view.GetPayload().begin() + 1, command_view.GetPayload().end())); send_event_(bluetooth::hci::LeSetScanResponseDataCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetAdvertisingEnable(CommandView command) { auto command_view = gd_hci::LeSetAdvertisingEnableView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); LOG_INFO("%s | LeSetAdvertisingEnable (%d)", GetAddress().ToString().c_str(), command_view.GetAdvertisingEnable() == gd_hci::Enable::ENABLED); ErrorCode status = link_layer_controller_.LeSetAdvertisingEnable( command_view.GetAdvertisingEnable() == gd_hci::Enable::ENABLED); send_event_(bluetooth::hci::LeSetAdvertisingEnableCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetScanParameters(CommandView command) { auto command_view = gd_hci::LeSetScanParametersView::Create( gd_hci::LeScanningCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetScanParameters( command_view.GetLeScanType(), command_view.GetLeScanInterval(), command_view.GetLeScanWindow(), command_view.GetOwnAddressType(), command_view.GetScanningFilterPolicy()); send_event_(bluetooth::hci::LeSetScanParametersCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetScanEnable(CommandView command) { auto command_view = gd_hci::LeSetScanEnableView::Create( gd_hci::LeScanningCommandView::Create(command)); ASSERT(command_view.IsValid()); LOG_INFO("%s | LeSetScanEnable (%d)", GetAddress().ToString().c_str(), command_view.GetLeScanEnable() == gd_hci::Enable::ENABLED); ErrorCode status = link_layer_controller_.LeSetScanEnable( command_view.GetLeScanEnable() == gd_hci::Enable::ENABLED, command_view.GetFilterDuplicates() == gd_hci::Enable::ENABLED); send_event_(bluetooth::hci::LeSetScanEnableCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeCreateConnection(CommandView command) { auto command_view = gd_hci::LeCreateConnectionView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeCreateConnection( command_view.GetLeScanInterval(), command_view.GetLeScanWindow(), command_view.GetInitiatorFilterPolicy(), AddressWithType{ command_view.GetPeerAddress(), command_view.GetPeerAddressType(), }, command_view.GetOwnAddressType(), command_view.GetConnIntervalMin(), command_view.GetConnIntervalMax(), command_view.GetConnLatency(), command_view.GetSupervisionTimeout(), command_view.GetMinimumCeLength(), command_view.GetMaximumCeLength()); send_event_(bluetooth::hci::LeCreateConnectionStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeCreateConnectionCancel(CommandView command) { auto command_view = gd_hci::LeCreateConnectionCancelView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeCreateConnectionCancel(); send_event_(bluetooth::hci::LeCreateConnectionCancelCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeConnectionUpdate(CommandView command) { auto command_view = gd_hci::LeConnectionUpdateView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeConnectionUpdate( command_view.GetConnectionHandle(), command_view.GetConnIntervalMin(), command_view.GetConnIntervalMax(), command_view.GetConnLatency(), command_view.GetSupervisionTimeout()); send_event_(bluetooth::hci::LeConnectionUpdateStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::CreateConnection(CommandView command) { auto command_view = gd_hci::CreateConnectionView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); Address address = command_view.GetBdAddr(); uint16_t packet_type = command_view.GetPacketType(); uint8_t page_scan_mode = static_cast(command_view.GetPageScanRepetitionMode()); uint16_t clock_offset = (command_view.GetClockOffsetValid() == gd_hci::ClockOffsetValid::VALID ? command_view.GetClockOffset() : 0); uint8_t allow_role_switch = static_cast(command_view.GetAllowRoleSwitch()); auto status = link_layer_controller_.CreateConnection( address, packet_type, page_scan_mode, clock_offset, allow_role_switch); send_event_(bluetooth::hci::CreateConnectionStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::CreateConnectionCancel(CommandView command) { auto command_view = gd_hci::CreateConnectionCancelView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); Address address = command_view.GetBdAddr(); auto status = link_layer_controller_.CreateConnectionCancel(address); send_event_(bluetooth::hci::CreateConnectionCancelCompleteBuilder::Create( kNumCommandPackets, status, address)); } void DualModeController::Disconnect(CommandView command) { auto command_view = gd_hci::DisconnectView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); auto status = link_layer_controller_.Disconnect( handle, ErrorCode(command_view.GetReason())); send_event_(bluetooth::hci::DisconnectStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeReadFilterAcceptListSize(CommandView command) { auto command_view = gd_hci::LeReadFilterAcceptListSizeView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::LeReadFilterAcceptListSizeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, properties_.le_filter_accept_list_size)); } void DualModeController::LeClearFilterAcceptList(CommandView command) { auto command_view = gd_hci::LeClearFilterAcceptListView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeClearFilterAcceptList(); send_event_(bluetooth::hci::LeClearFilterAcceptListCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeAddDeviceToFilterAcceptList(CommandView command) { auto command_view = gd_hci::LeAddDeviceToFilterAcceptListView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeAddDeviceToFilterAcceptList( command_view.GetAddressType(), command_view.GetAddress()); send_event_( bluetooth::hci::LeAddDeviceToFilterAcceptListCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeRemoveDeviceFromFilterAcceptList( CommandView command) { auto command_view = gd_hci::LeRemoveDeviceFromFilterAcceptListView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeRemoveDeviceFromFilterAcceptList( command_view.GetAddressType(), command_view.GetAddress()); send_event_( bluetooth::hci::LeRemoveDeviceFromFilterAcceptListCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeClearResolvingList(CommandView command) { auto command_view = gd_hci::LeClearResolvingListView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeClearResolvingList(); send_event_(bluetooth::hci::LeClearResolvingListCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeReadResolvingListSize(CommandView command) { auto command_view = gd_hci::LeReadResolvingListSizeView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::LeReadResolvingListSizeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, properties_.le_resolving_list_size)); } void DualModeController::LeReadMaximumDataLength(CommandView command) { auto command_view = gd_hci::LeReadMaximumDataLengthView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); bluetooth::hci::LeMaximumDataLength data_length; data_length.supported_max_rx_octets_ = kLeMaximumDataLength; data_length.supported_max_rx_time_ = kLeMaximumDataTime; data_length.supported_max_tx_octets_ = kLeMaximumDataLength + 10; data_length.supported_max_tx_time_ = kLeMaximumDataTime + 10; send_event_(bluetooth::hci::LeReadMaximumDataLengthCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, data_length)); } void DualModeController::LeReadSuggestedDefaultDataLength(CommandView command) { auto command_view = gd_hci::LeReadSuggestedDefaultDataLengthView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); send_event_( bluetooth::hci::LeReadSuggestedDefaultDataLengthCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, link_layer_controller_.GetLeSuggestedMaxTxOctets(), link_layer_controller_.GetLeSuggestedMaxTxTime())); } void DualModeController::LeWriteSuggestedDefaultDataLength( CommandView command) { auto command_view = gd_hci::LeWriteSuggestedDefaultDataLengthView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t max_tx_octets = command_view.GetTxOctets(); uint16_t max_tx_time = command_view.GetTxTime(); ErrorCode status = ErrorCode::SUCCESS; if (max_tx_octets > 0xFB || max_tx_octets < 0x1B || max_tx_time < 0x148 || max_tx_time > 0x4290) { status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS; } else { link_layer_controller_.SetLeSuggestedMaxTxOctets(max_tx_octets); link_layer_controller_.SetLeSuggestedMaxTxTime(max_tx_time); } send_event_( bluetooth::hci::LeWriteSuggestedDefaultDataLengthCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeAddDeviceToResolvingList(CommandView command) { auto command_view = gd_hci::LeAddDeviceToResolvingListView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeAddDeviceToResolvingList( command_view.GetPeerIdentityAddressType(), command_view.GetPeerIdentityAddress(), command_view.GetPeerIrk(), command_view.GetLocalIrk()); send_event_(bluetooth::hci::LeAddDeviceToResolvingListCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeRemoveDeviceFromResolvingList(CommandView command) { auto command_view = gd_hci::LeRemoveDeviceFromResolvingListView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeRemoveDeviceFromResolvingList( command_view.GetPeerIdentityAddressType(), command_view.GetPeerIdentityAddress()); send_event_( bluetooth::hci::LeRemoveDeviceFromResolvingListCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetExtendedScanParameters(CommandView command) { auto command_view = gd_hci::LeSetExtendedScanParametersView::Create( gd_hci::LeScanningCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetExtendedScanParameters( command_view.GetOwnAddressType(), command_view.GetScanningFilterPolicy(), command_view.GetScanningPhys(), command_view.GetParameters()); send_event_( bluetooth::hci::LeSetExtendedScanParametersCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetExtendedScanEnable(CommandView command) { auto command_view = gd_hci::LeSetExtendedScanEnableView::Create( gd_hci::LeScanningCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetExtendedScanEnable( command_view.GetEnable() == gd_hci::Enable::ENABLED, command_view.GetFilterDuplicates(), command_view.GetDuration(), command_view.GetPeriod()); send_event_(bluetooth::hci::LeSetExtendedScanEnableCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeExtendedCreateConnection(CommandView command) { auto command_view = gd_hci::LeExtendedCreateConnectionView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeExtendedCreateConnection( command_view.GetInitiatorFilterPolicy(), command_view.GetOwnAddressType(), AddressWithType{ command_view.GetPeerAddress(), command_view.GetPeerAddressType(), }, command_view.GetInitiatingPhys(), command_view.GetPhyScanParameters()); send_event_(bluetooth::hci::LeExtendedCreateConnectionStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeSetPrivacyMode(CommandView command) { auto command_view = gd_hci::LeSetPrivacyModeView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetPrivacyMode( command_view.GetPeerIdentityAddressType(), command_view.GetPeerIdentityAddress(), command_view.GetPrivacyMode()); send_event_(bluetooth::hci::LeSetPrivacyModeCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeReadIsoTxSync(CommandView command) { auto command_view = gd_hci::LeReadIsoTxSyncView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.LeReadIsoTxSync(command_view.GetConnectionHandle()); } void DualModeController::LeSetCigParameters(CommandView command) { auto command_view = gd_hci::LeSetCigParametersView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.LeSetCigParameters( command_view.GetCigId(), command_view.GetSduIntervalMToS(), command_view.GetSduIntervalSToM(), command_view.GetPeripheralsClockAccuracy(), command_view.GetPacking(), command_view.GetFraming(), command_view.GetMaxTransportLatencyMToS(), command_view.GetMaxTransportLatencySToM(), command_view.GetCisConfig()); } void DualModeController::LeCreateCis(CommandView command) { auto command_view = gd_hci::LeCreateCisView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeCreateCis(command_view.GetCisConfig()); send_event_(bluetooth::hci::LeCreateCisStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeRemoveCig(CommandView command) { auto command_view = gd_hci::LeRemoveCigView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); uint8_t cig = command_view.GetCigId(); ErrorCode status = link_layer_controller_.LeRemoveCig(cig); send_event_(bluetooth::hci::LeRemoveCigCompleteBuilder::Create( kNumCommandPackets, status, cig)); } void DualModeController::LeAcceptCisRequest(CommandView command) { auto command_view = gd_hci::LeAcceptCisRequestView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeAcceptCisRequest( command_view.GetConnectionHandle()); send_event_(bluetooth::hci::LeAcceptCisRequestStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeRejectCisRequest(CommandView command) { auto command_view = gd_hci::LeRejectCisRequestView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.LeRejectCisRequest(command_view.GetConnectionHandle(), command_view.GetReason()); } void DualModeController::LeCreateBig(CommandView command) { auto command_view = gd_hci::LeCreateBigView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeCreateBig( command_view.GetBigHandle(), command_view.GetAdvertisingHandle(), command_view.GetNumBis(), command_view.GetSduInterval(), command_view.GetMaxSdu(), command_view.GetMaxTransportLatency(), command_view.GetRtn(), command_view.GetPhy(), command_view.GetPacking(), command_view.GetFraming(), command_view.GetEncryption(), command_view.GetBroadcastCode()); send_event_(bluetooth::hci::LeCreateBigStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeTerminateBig(CommandView command) { auto command_view = gd_hci::LeTerminateBigView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeTerminateBig( command_view.GetBigHandle(), command_view.GetReason()); send_event_(bluetooth::hci::LeTerminateBigStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeBigCreateSync(CommandView command) { auto command_view = gd_hci::LeBigCreateSyncView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeBigCreateSync( command_view.GetBigHandle(), command_view.GetSyncHandle(), command_view.GetEncryption(), command_view.GetBroadcastCode(), command_view.GetMse(), command_view.GetBigSyncTimeout(), command_view.GetBis()); send_event_(bluetooth::hci::LeBigCreateSyncStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeBigTerminateSync(CommandView command) { auto command_view = gd_hci::LeBigTerminateSyncView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.LeBigTerminateSync(command_view.GetBigHandle()); } void DualModeController::LeRequestPeerSca(CommandView command) { auto command_view = gd_hci::LeRequestPeerScaView::Create(command); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeRequestPeerSca( command_view.GetConnectionHandle()); send_event_(bluetooth::hci::LeRequestPeerScaStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeSetupIsoDataPath(CommandView command) { auto command_view = gd_hci::LeSetupIsoDataPathView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.LeSetupIsoDataPath( command_view.GetConnectionHandle(), command_view.GetDataPathDirection(), command_view.GetDataPathId(), command_view.GetCodecId(), command_view.GetControllerDelay(), command_view.GetCodecConfiguration()); } void DualModeController::LeRemoveIsoDataPath(CommandView command) { auto command_view = gd_hci::LeRemoveIsoDataPathView::Create( gd_hci::LeIsoCommandView::Create(command)); ASSERT(command_view.IsValid()); link_layer_controller_.LeRemoveIsoDataPath( command_view.GetConnectionHandle(), command_view.GetRemoveDataPathDirection()); } void DualModeController::LeReadRemoteFeatures(CommandView command) { auto command_view = gd_hci::LeReadRemoteFeaturesView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); auto status = link_layer_controller_.SendCommandToRemoteByHandle( OpCode::LE_READ_REMOTE_FEATURES, command_view.GetPayload(), handle); send_event_(bluetooth::hci::LeReadRemoteFeaturesStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeEncrypt(CommandView command) { auto command_view = gd_hci::LeEncryptView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); auto encrypted_data = bluetooth::crypto_toolbox::aes_128( command_view.GetKey(), command_view.GetPlaintextData()); send_event_(bluetooth::hci::LeEncryptCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, encrypted_data)); } static std::random_device rd{}; static std::mt19937_64 s_mt{rd()}; void DualModeController::LeRand(CommandView command) { auto command_view = gd_hci::LeRandView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); uint64_t random_val = s_mt(); send_event_(bluetooth::hci::LeRandCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, random_val)); } void DualModeController::LeReadSupportedStates(CommandView command) { auto command_view = gd_hci::LeReadSupportedStatesView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::LeReadSupportedStatesCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, properties_.le_supported_states)); } void DualModeController::LeRemoteConnectionParameterRequestReply( CommandView command) { auto command_view = gd_hci::LeRemoteConnectionParameterRequestReplyView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.LeRemoteConnectionParameterRequestReply( command_view.GetConnectionHandle(), command_view.GetIntervalMin(), command_view.GetIntervalMax(), command_view.GetTimeout(), command_view.GetLatency(), command_view.GetMinimumCeLength(), command_view.GetMaximumCeLength()); send_event_( gd_hci::LeRemoteConnectionParameterRequestReplyCompleteBuilder::Create( kNumCommandPackets, status, command_view.GetConnectionHandle())); } void DualModeController::LeRemoteConnectionParameterRequestNegativeReply( CommandView command) { auto command_view = gd_hci::LeRemoteConnectionParameterRequestNegativeReplyView::Create( gd_hci::LeConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.LeRemoteConnectionParameterRequestNegativeReply( command_view.GetConnectionHandle(), command_view.GetReason()); send_event_( gd_hci::LeRemoteConnectionParameterRequestNegativeReplyCompleteBuilder:: Create(kNumCommandPackets, status, command_view.GetConnectionHandle())); } void DualModeController::LeVendorCap(CommandView command) { auto command_view = gd_hci::LeGetVendorCapabilitiesView::Create( gd_hci::VendorCommandView::Create(command)); ASSERT(command_view.IsValid()); vector caps = properties_.le_vendor_capabilities; if (caps.size() == 0) { SendCommandCompleteUnknownOpCodeEvent( static_cast(OpCode::LE_GET_VENDOR_CAPABILITIES)); return; } std::unique_ptr raw_builder_ptr = std::make_unique(); raw_builder_ptr->AddOctets1(static_cast(ErrorCode::SUCCESS)); raw_builder_ptr->AddOctets(properties_.le_vendor_capabilities); send_event_(bluetooth::hci::CommandCompleteBuilder::Create( kNumCommandPackets, OpCode::LE_GET_VENDOR_CAPABILITIES, std::move(raw_builder_ptr))); } void DualModeController::LeVendorMultiAdv(CommandView command) { auto command_view = gd_hci::LeMultiAdvtView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); SendCommandCompleteUnknownOpCodeEvent( static_cast(OpCode::LE_MULTI_ADVT)); } void DualModeController::LeAdvertisingFilter(CommandView command) { auto command_view = gd_hci::LeAdvFilterView::Create( gd_hci::LeScanningCommandView::Create(command)); ASSERT(command_view.IsValid()); SendCommandCompleteUnknownOpCodeEvent( static_cast(OpCode::LE_ADV_FILTER)); } void DualModeController::LeEnergyInfo(CommandView command) { auto command_view = gd_hci::LeEnergyInfoView::Create( gd_hci::VendorCommandView::Create(command)); ASSERT(command_view.IsValid()); SendCommandCompleteUnknownOpCodeEvent( static_cast(OpCode::LE_ENERGY_INFO)); } // CSR vendor command. // Implement the command specific to the CSR controller // used specifically by the PTS tool to pass certification tests. void DualModeController::CsrVendorCommand(CommandView command) { // The byte order is little endian. // The command parameters are formatted as // // 00 | 0xc2 // 01 02 | action // read = 0 // write = 2 // 03 04 | (value length / 2) + 5 // 04 05 | sequence number // 06 07 | varid // 08 09 | 00 00 // 0a .. | value // // BlueZ has a reference implementation of the CSR vendor command. std::vector parameters(command.GetPayload().begin(), command.GetPayload().end()); uint16_t type = 0; uint16_t length = 0; uint16_t varid = 0; if (parameters.size() == 0) { LOG_INFO("Empty CSR vendor command"); goto complete; } if (parameters[0] != 0xc2 || parameters.size() < 11) { LOG_INFO( "Unsupported CSR vendor command with code %02x " "and parameter length %zu", static_cast(parameters[0]), parameters.size()); goto complete; } type = (uint16_t)parameters[1] | ((uint16_t)parameters[2] << 8); length = (uint16_t)parameters[3] | ((uint16_t)parameters[4] << 8); varid = (uint16_t)parameters[7] | ((uint16_t)parameters[8] << 8); length = 2 * (length - 5); if (parameters.size() < (11 + length) || (varid == CsrVarid::CSR_VARID_PS && length < 6)) { LOG_INFO("Invalid CSR vendor command parameter length %zu, expected %u", parameters.size(), 11 + length); goto complete; } if (varid == CsrVarid::CSR_VARID_PS) { // Subcommand to read or write PSKEY of the selected identifier // instead of VARID. uint16_t pskey = (uint16_t)parameters[11] | ((uint16_t)parameters[12] << 8); uint16_t length = (uint16_t)parameters[13] | ((uint16_t)parameters[14] << 8); length = 2 * length; if (parameters.size() < (17 + length)) { LOG_INFO("Invalid CSR vendor command parameter length %zu, expected %u", parameters.size(), 17 + length); goto complete; } std::vector value(parameters.begin() + 17, parameters.begin() + 17 + length); LOG_INFO("CSR vendor command type=%04x length=%04x pskey=%04x", type, length, pskey); if (type == 0) { CsrReadPskey(static_cast(pskey), value); std::copy(value.begin(), value.end(), parameters.begin() + 17); } else { CsrWritePskey(static_cast(pskey), value); } } else { // Subcommand to read or write VARID of the selected identifier. std::vector value(parameters.begin() + 11, parameters.begin() + 11 + length); LOG_INFO("CSR vendor command type=%04x length=%04x varid=%04x", type, length, varid); if (type == 0) { CsrReadVarid(static_cast(varid), value); std::copy(value.begin(), value.end(), parameters.begin() + 11); } else { CsrWriteVarid(static_cast(varid), value); } } complete: // Overwrite the command type. parameters[1] = 0x1; parameters[2] = 0x0; send_event_(bluetooth::hci::EventBuilder::Create( bluetooth::hci::EventCode::VENDOR_SPECIFIC, std::make_unique(std::move(parameters)))); } void DualModeController::CsrReadVarid(CsrVarid varid, std::vector& value) { switch (varid) { case CsrVarid::CSR_VARID_BUILDID: // Return the extact Build ID returned by the official PTS dongle. ASSERT(value.size() >= 2); value[0] = 0xe8; value[1] = 0x30; break; default: LOG_INFO("Unsupported read of CSR varid 0x%04x", varid); break; } } void DualModeController::CsrWriteVarid(CsrVarid varid, std::vector const& value) { LOG_INFO("Unsupported write of CSR varid 0x%04x", varid); } void DualModeController::CsrReadPskey(CsrPskey pskey, std::vector& value) { switch (pskey) { case CsrPskey::CSR_PSKEY_ENC_KEY_LMIN: ASSERT(value.size() >= 1); value[0] = 7; break; case CsrPskey::CSR_PSKEY_ENC_KEY_LMAX: ASSERT(value.size() >= 1); value[0] = 16; break; case CSR_PSKEY_HCI_LMP_LOCAL_VERSION: // Return the extact version returned by the official PTS dongle. ASSERT(value.size() >= 2); value[0] = 0x08; value[1] = 0x08; break; default: LOG_INFO("Unsupported read of CSR pskey 0x%04x", pskey); break; } } void DualModeController::CsrWritePskey(CsrPskey pskey, std::vector const& value) { switch (pskey) { case CsrPskey::CSR_PSKEY_LOCAL_SUPPORTED_FEATURES: ASSERT(value.size() >= 8); LOG_INFO("CSR Vendor updating the Local Supported Features"); properties_.lmp_features[0] = ((uint64_t)value[0] << 0) | ((uint64_t)value[1] << 8) | ((uint64_t)value[2] << 16) | ((uint64_t)value[3] << 24) | ((uint64_t)value[4] << 32) | ((uint64_t)value[5] << 40) | ((uint64_t)value[6] << 48) | ((uint64_t)value[7] << 56); break; default: LOG_INFO("Unsupported write of CSR pskey 0x%04x", pskey); break; } } void DualModeController::LeSetAdvertisingSetRandomAddress(CommandView command) { auto command_view = gd_hci::LeSetAdvertisingSetRandomAddressView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetAdvertisingSetRandomAddress( command_view.GetAdvertisingHandle(), command_view.GetRandomAddress()); send_event_( bluetooth::hci::LeSetAdvertisingSetRandomAddressCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetExtendedAdvertisingParameters( CommandView command) { auto command_view = gd_hci::LeSetExtendedAdvertisingParametersView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetExtendedAdvertisingParameters( command_view.GetAdvertisingHandle(), command_view.GetAdvertisingEventProperties(), command_view.GetPrimaryAdvertisingIntervalMin(), command_view.GetPrimaryAdvertisingIntervalMax(), command_view.GetPrimaryAdvertisingChannelMap(), command_view.GetOwnAddressType(), command_view.GetPeerAddressType(), command_view.GetPeerAddress(), command_view.GetAdvertisingFilterPolicy(), command_view.GetAdvertisingTxPower(), command_view.GetPrimaryAdvertisingPhy(), command_view.GetSecondaryAdvertisingMaxSkip(), command_view.GetSecondaryAdvertisingPhy(), command_view.GetAdvertisingSid(), command_view.GetScanRequestNotificationEnable() == Enable::ENABLED); // The selected TX power is always the requested TX power // at the moment. send_event_( bluetooth::hci::LeSetExtendedAdvertisingParametersCompleteBuilder::Create( kNumCommandPackets, status, command_view.GetAdvertisingTxPower())); } void DualModeController::LeSetExtendedAdvertisingData(CommandView command) { auto command_view = gd_hci::LeSetExtendedAdvertisingDataView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); auto raw_command_view = gd_hci::LeSetExtendedAdvertisingDataRawView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(raw_command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetExtendedAdvertisingData( command_view.GetAdvertisingHandle(), command_view.GetOperation(), command_view.GetFragmentPreference(), raw_command_view.GetAdvertisingData()); send_event_( bluetooth::hci::LeSetExtendedAdvertisingDataCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetExtendedScanResponseData(CommandView command) { auto command_view = gd_hci::LeSetExtendedScanResponseDataView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); auto raw_command_view = gd_hci::LeSetExtendedScanResponseDataRawView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(raw_command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetExtendedScanResponseData( command_view.GetAdvertisingHandle(), command_view.GetOperation(), command_view.GetFragmentPreference(), raw_command_view.GetScanResponseData()); send_event_( bluetooth::hci::LeSetExtendedScanResponseDataCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeSetExtendedAdvertisingEnable(CommandView command) { auto command_view = gd_hci::LeSetExtendedAdvertisingEnableView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeSetExtendedAdvertisingEnable( command_view.GetEnable() == bluetooth::hci::Enable::ENABLED, command_view.GetEnabledSets()); send_event_( bluetooth::hci::LeSetExtendedAdvertisingEnableCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeReadMaximumAdvertisingDataLength( CommandView command) { auto command_view = gd_hci::LeReadMaximumAdvertisingDataLengthView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_( bluetooth::hci::LeReadMaximumAdvertisingDataLengthCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, kLeMaximumAdvertisingDataLength)); } void DualModeController::LeReadNumberOfSupportedAdvertisingSets( CommandView command) { auto command_view = gd_hci::LeReadNumberOfSupportedAdvertisingSetsView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_( bluetooth::hci::LeReadNumberOfSupportedAdvertisingSetsCompleteBuilder:: Create(kNumCommandPackets, ErrorCode::SUCCESS, properties_.le_num_supported_advertising_sets)); } void DualModeController::LeRemoveAdvertisingSet(CommandView command) { auto command_view = gd_hci::LeRemoveAdvertisingSetView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.LeRemoveAdvertisingSet( command_view.GetAdvertisingHandle()); send_event_(bluetooth::hci::LeRemoveAdvertisingSetCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeClearAdvertisingSets(CommandView command) { auto command_view = gd_hci::LeClearAdvertisingSetsView::Create( gd_hci::LeAdvertisingCommandView::Create(command)); ASSERT(command_view.IsValid()); auto status = link_layer_controller_.LeClearAdvertisingSets(); send_event_(bluetooth::hci::LeClearAdvertisingSetsCompleteBuilder::Create( kNumCommandPackets, status)); } void DualModeController::LeExtendedScanParams(CommandView command) { auto command_view = gd_hci::LeExtendedScanParamsView::Create( gd_hci::LeScanningCommandView::Create(command)); ASSERT(command_view.IsValid()); SendCommandCompleteUnknownOpCodeEvent( static_cast(OpCode::LE_EXTENDED_SCAN_PARAMS)); } void DualModeController::LeStartEncryption(CommandView command) { auto command_view = gd_hci::LeStartEncryptionView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); ErrorCode status = link_layer_controller_.LeEnableEncryption( command_view.GetConnectionHandle(), command_view.GetRand(), command_view.GetEdiv(), command_view.GetLtk()); send_event_(bluetooth::hci::LeStartEncryptionStatusBuilder::Create( status, kNumCommandPackets)); } void DualModeController::LeLongTermKeyRequestReply(CommandView command) { auto command_view = gd_hci::LeLongTermKeyRequestReplyView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); ErrorCode status = link_layer_controller_.LeLongTermKeyRequestReply( handle, command_view.GetLongTermKey()); send_event_(bluetooth::hci::LeLongTermKeyRequestReplyCompleteBuilder::Create( kNumCommandPackets, status, handle)); } void DualModeController::LeLongTermKeyRequestNegativeReply( CommandView command) { auto command_view = gd_hci::LeLongTermKeyRequestNegativeReplyView::Create( gd_hci::LeSecurityCommandView::Create(command)); ASSERT(command_view.IsValid()); uint16_t handle = command_view.GetConnectionHandle(); ErrorCode status = link_layer_controller_.LeLongTermKeyRequestNegativeReply(handle); send_event_( bluetooth::hci::LeLongTermKeyRequestNegativeReplyCompleteBuilder::Create( kNumCommandPackets, status, handle)); } void DualModeController::ReadClassOfDevice(CommandView command) { auto command_view = gd_hci::ReadClassOfDeviceView::Create( gd_hci::DiscoveryCommandView::Create(command)); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadClassOfDeviceCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, link_layer_controller_.GetClassOfDevice())); } void DualModeController::ReadVoiceSetting(CommandView command) { auto command_view = gd_hci::ReadVoiceSettingView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadVoiceSettingCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, link_layer_controller_.GetVoiceSetting())); } void DualModeController::ReadConnectionAcceptTimeout(CommandView command) { auto command_view = gd_hci::ReadConnectionAcceptTimeoutView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); send_event_( bluetooth::hci::ReadConnectionAcceptTimeoutCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, link_layer_controller_.GetConnectionAcceptTimeout())); } void DualModeController::WriteConnectionAcceptTimeout(CommandView command) { auto command_view = gd_hci::WriteConnectionAcceptTimeoutView::Create( gd_hci::ConnectionManagementCommandView::Create( gd_hci::AclCommandView::Create(command))); ASSERT(command_view.IsValid()); link_layer_controller_.SetConnectionAcceptTimeout( command_view.GetConnAcceptTimeout()); send_event_( bluetooth::hci::WriteConnectionAcceptTimeoutCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } void DualModeController::ReadLoopbackMode(CommandView command) { auto command_view = gd_hci::ReadLoopbackModeView::Create(command); ASSERT(command_view.IsValid()); send_event_(bluetooth::hci::ReadLoopbackModeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, loopback_mode_)); } void DualModeController::WriteLoopbackMode(CommandView command) { auto command_view = gd_hci::WriteLoopbackModeView::Create(command); ASSERT(command_view.IsValid()); loopback_mode_ = command_view.GetLoopbackMode(); // ACL channel uint16_t acl_handle = 0x123; send_event_(bluetooth::hci::ConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, acl_handle, GetAddress(), bluetooth::hci::LinkType::ACL, bluetooth::hci::Enable::DISABLED)); // SCO channel uint16_t sco_handle = 0x345; send_event_(bluetooth::hci::ConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, sco_handle, GetAddress(), bluetooth::hci::LinkType::SCO, bluetooth::hci::Enable::DISABLED)); send_event_(bluetooth::hci::WriteLoopbackModeCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS)); } } // namespace rootcanal