Loading system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc +24 −4 Original line number Diff line number Diff line Loading @@ -31,8 +31,12 @@ bool AclConnectionHandler::HasHandle(uint16_t handle) const { return acl_connections_.count(handle) != 0; } bool AclConnectionHandler::HasScoHandle(uint16_t handle) const { return sco_connections_.count(handle) != 0; } uint16_t AclConnectionHandler::GetUnusedHandle() { while (HasHandle(last_handle_) || while (HasHandle(last_handle_) || HasScoHandle(last_handle_) || isochronous_connection_handler_.HasHandle(last_handle_)) { last_handle_ = (last_handle_ + 1) % kReservedHandle; } Loading Loading @@ -131,7 +135,18 @@ uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr, } bool AclConnectionHandler::Disconnect(uint16_t handle) { return acl_connections_.erase(handle) > 0; if (HasScoHandle(handle)) { sco_connections_.erase(handle); return true; } if (HasHandle(handle)) { // It is the responsibility of the caller to remove SCO connections // with connected peer first. ASSERT(GetScoHandle(GetAddress(handle).GetAddress()) == 0); acl_connections_.erase(handle); return true; } return false; } uint16_t AclConnectionHandler::GetHandle(AddressWithType addr) const { Loading @@ -154,12 +169,17 @@ uint16_t AclConnectionHandler::GetHandleOnlyAddress( } AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const { ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle); ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle); return acl_connections_.at(handle).GetAddress(); } Address AclConnectionHandler::GetScoAddress(uint16_t handle) const { ASSERT_LOG(HasScoHandle(handle), "Unknown SCO handle %hd", handle); return sco_connections_.at(handle).GetAddress(); } AddressWithType AclConnectionHandler::GetOwnAddress(uint16_t handle) const { ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle); ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle); return acl_connections_.at(handle).GetOwnAddress(); } Loading system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h +2 −0 Original line number Diff line number Diff line Loading @@ -63,10 +63,12 @@ class AclConnectionHandler { bluetooth::hci::AddressWithType own_addr); bool Disconnect(uint16_t handle); bool HasHandle(uint16_t handle) const; bool HasScoHandle(uint16_t handle) const; uint16_t GetHandle(bluetooth::hci::AddressWithType addr) const; uint16_t GetHandleOnlyAddress(bluetooth::hci::Address addr) const; bluetooth::hci::AddressWithType GetAddress(uint16_t handle) const; bluetooth::hci::Address GetScoAddress(uint16_t handle) const; bluetooth::hci::AddressWithType GetOwnAddress(uint16_t handle) const; void Encrypt(uint16_t handle); Loading system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc +1 −0 Original line number Diff line number Diff line Loading @@ -568,6 +568,7 @@ void DualModeController::ReadLocalSupportedCommands(CommandView command) { void DualModeController::ReadLocalSupportedFeatures(CommandView command) { auto command_view = gd_hci::ReadLocalSupportedFeaturesView::Create(command); ASSERT(command_view.IsValid()); auto packet = bluetooth::hci::ReadLocalSupportedFeaturesCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, Loading system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc +140 −69 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "link_layer_controller.h" #include <cinttypes> #include <hci/hci_packets.h> #include "crypto_toolbox/crypto_toolbox.h" Loading Loading @@ -390,6 +391,9 @@ void LinkLayerController::IncomingPacket( case model::packets::PacketType::ESCO_CONNECTION_RESPONSE: IncomingEScoConnectionResponse(incoming); break; case model::packets::PacketType::ESCO_DISCONNECT: IncomingEScoDisconnect(incoming); break; default: LOG_WARN("Dropping unhandled packet of type %s", Loading Loading @@ -627,8 +631,7 @@ void LinkLayerController::IncomingDisconnectPacket( "GetHandle() returned invalid handle %hx", handle); uint8_t reason = disconnect.GetReason(); ScheduleTask(kShortDelayMs, [this, handle, reason]() { DisconnectCleanup(handle, reason); }); SendDisconnectionCompleteEvent(handle, reason); } void LinkLayerController::IncomingEncryptConnection( Loading Loading @@ -1370,23 +1373,37 @@ void LinkLayerController::IncomingEScoConnectionRequest( Address address = incoming.GetSourceAddress(); auto request = model::packets::EScoConnectionRequestView::Create(incoming); ASSERT(request.IsValid()); LOG_INFO("Received eSCO connection request from %s", address.ToString().c_str()); // Automatically reject if connection request was already sent // from the current device. if (connections_.HasPendingScoConnection(address)) { auto packet = model::packets::EScoConnectionResponseBuilder::Create( LOG_INFO("Rejecting eSCO connection request from %s, " "an eSCO connection already exist with this device", address.ToString().c_str()); SendLinkLayerPacket(model::packets::EScoConnectionResponseBuilder::Create( properties_.GetLeAddress(), address, (uint8_t)ErrorCode::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED, 0, 0, 0, 0, 0); SendLinkLayerPacket(std::move(packet)); (uint8_t)ErrorCode::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED, 0, 0, 0, 0, 0)); return; } // Send connection request event to use and wait for Accept or Reject // command. auto packet = bluetooth::hci::ConnectionRequestBuilder::Create( // Create local connection context. ScoConnectionParameters connection_parameters = { request.GetTransmitBandwidth(), request.GetReceiveBandwidth(), request.GetMaxLatency(), request.GetVoiceSetting(), request.GetRetransmissionEffort(), request.GetPacketType() }; connections_.CreatePendingScoConnection(address, connection_parameters); // Send connection request event and wait for Accept or Reject command. send_event_(bluetooth::hci::ConnectionRequestBuilder::Create( address, ClassOfDevice(), bluetooth::hci::ConnectionRequestLinkType::ESCO); send_event_(std::move(packet)); bluetooth::hci::ConnectionRequestLinkType::ESCO)); } void LinkLayerController::IncomingEScoConnectionResponse( Loading @@ -1394,8 +1411,12 @@ void LinkLayerController::IncomingEScoConnectionResponse( Address address = incoming.GetSourceAddress(); auto response = model::packets::EScoConnectionResponseView::Create(incoming); ASSERT(response.IsValid()); auto status = response.GetStatus(); LOG_INFO("Received eSCO connection response with status %" PRIx8 " from %s", status, incoming.GetSourceAddress().ToString().c_str()); if (status == (uint8_t)ErrorCode::SUCCESS) { ScoLinkParameters link_parameters = { response.GetTransmissionInterval(), Loading @@ -1405,23 +1426,38 @@ void LinkLayerController::IncomingEScoConnectionResponse( response.GetAirMode(), }; connections_.AcceptPendingScoConnection(address, link_parameters); auto packet = bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( send_event_(bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( ErrorCode(status), connections_.GetScoHandle(address), address, bluetooth::hci::ScoLinkType::ESCO, response.GetTransmissionInterval(), response.GetRetransmissionWindow(), response.GetRxPacketLength(), response.GetTxPacketLength(), bluetooth::hci::ScoAirMode(response.GetAirMode())); send_event_(std::move(packet)); bluetooth::hci::ScoAirMode(response.GetAirMode()))); } else { connections_.CancelPendingScoConnection(address); auto packet = bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( send_event_(bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( ErrorCode(status), 0, address, bluetooth::hci::ScoLinkType::ESCO, 0, 0, 0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT); 0, 0, 0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT)); } } void LinkLayerController::IncomingEScoDisconnect( model::packets::LinkLayerPacketView incoming) { Address address = incoming.GetSourceAddress(); auto request = model::packets::EScoDisconnectView::Create(incoming); ASSERT(request.IsValid()); auto reason = request.GetReason(); uint16_t handle = connections_.GetScoHandle(address); send_event_(std::move(packet)); LOG_INFO("Received eSCO disconnection request with" " reason 0x%" PRIx8 " from %s", reason, incoming.GetSourceAddress().ToString().c_str()); if (handle != 0) { connections_.Disconnect(handle); SendDisconnectionCompleteEvent(handle, reason); } } Loading Loading @@ -2546,39 +2582,67 @@ ErrorCode LinkLayerController::CreateConnectionCancel(const Address& addr) { return ErrorCode::SUCCESS; } void LinkLayerController::SendDisconnectionCompleteEvent( uint16_t handle, uint8_t reason) { if (properties_.IsUnmasked(EventCode::DISCONNECTION_COMPLETE)) { ScheduleTask(kShortDelayMs, [this, handle, reason]() { send_event_(bluetooth::hci::DisconnectionCompleteBuilder::Create( ErrorCode::SUCCESS, handle, ErrorCode(reason))); }); } } ErrorCode LinkLayerController::Disconnect(uint16_t handle, uint8_t reason) { if (connections_.HasScoHandle(handle)) { const Address remote = connections_.GetScoAddress(handle); LOG_INFO("Disconnecting eSCO connection with %s", remote.ToString().c_str()); SendLinkLayerPacket(model::packets::EScoDisconnectBuilder::Create( properties_.GetAddress(), remote, reason)); connections_.Disconnect(handle); SendDisconnectionCompleteEvent(handle, reason); return ErrorCode::SUCCESS; } if (!connections_.HasHandle(handle)) { return ErrorCode::UNKNOWN_CONNECTION; } const AddressWithType remote = connections_.GetAddress(handle); if (connections_.GetPhyType(handle) == Phy::Type::BR_EDR) { LOG_INFO("Disconnecting ACL connection with %s", remote.ToString().c_str()); uint16_t sco_handle = connections_.GetScoHandle(remote.GetAddress()); if (sco_handle != 0) { SendLinkLayerPacket(model::packets::EScoDisconnectBuilder::Create( properties_.GetAddress(), remote.GetAddress(), reason)); connections_.Disconnect(sco_handle); SendDisconnectionCompleteEvent(sco_handle, reason); } SendLinkLayerPacket(model::packets::DisconnectBuilder::Create( properties_.GetAddress(), remote.GetAddress(), reason)); } else { LOG_INFO("Disconnecting LE connection with %s", remote.ToString().c_str()); SendLeLinkLayerPacket(model::packets::DisconnectBuilder::Create( connections_.GetOwnAddress(handle).GetAddress(), remote.GetAddress(), reason)); } ASSERT_LOG(connections_.Disconnect(handle), "Disconnecting %hx", handle); ScheduleTask(kShortDelayMs, [this, handle]() { DisconnectCleanup( handle, static_cast<uint8_t>(ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST)); }); connections_.Disconnect(handle); SendDisconnectionCompleteEvent(handle, reason); return ErrorCode::SUCCESS; } void LinkLayerController::DisconnectCleanup(uint16_t handle, uint8_t reason) { // TODO: Clean up other connection state. if (properties_.IsUnmasked(EventCode::DISCONNECTION_COMPLETE)) { send_event_(bluetooth::hci::DisconnectionCompleteBuilder::Create( ErrorCode::SUCCESS, handle, static_cast<ErrorCode>(reason))); } } ErrorCode LinkLayerController::ChangeConnectionPacketType(uint16_t handle, uint16_t types) { if (!connections_.HasHandle(handle)) { Loading Loading @@ -3515,6 +3579,7 @@ ErrorCode LinkLayerController::SetupSynchronousConnection( if (!connections_.HasHandle(connection_handle)) { return ErrorCode::UNKNOWN_CONNECTION; } Address bd_addr = connections_.GetAddress(connection_handle).GetAddress(); if (connections_.HasPendingScoConnection(bd_addr)) { // This command may be used to modify an exising eSCO link. Loading @@ -3523,6 +3588,8 @@ ErrorCode LinkLayerController::SetupSynchronousConnection( return ErrorCode::COMMAND_DISALLOWED; } LOG_INFO("Creating eSCO connection with %s", bd_addr.ToString().c_str()); // Save connection parameters. ScoConnectionParameters connection_parameters = { transmit_bandwidth, receive_bandwidth, max_latency, Loading @@ -3533,11 +3600,10 @@ ErrorCode LinkLayerController::SetupSynchronousConnection( connection_parameters); // Send eSCO connection request to peer. auto packet = model::packets::EScoConnectionRequestBuilder::Create( SendLinkLayerPacket(model::packets::EScoConnectionRequestBuilder::Create( properties_.GetAddress(), bd_addr, transmit_bandwidth, receive_bandwidth, max_latency, voice_setting, retransmission_effort, packet_types); SendLinkLayerPacket(std::move(packet)); voice_setting, retransmission_effort, packet_types)); return ErrorCode::SUCCESS; } Loading @@ -3550,7 +3616,12 @@ ErrorCode LinkLayerController::AcceptSynchronousConnection( uint8_t retransmission_effort, uint16_t packet_types) { LOG_INFO("Accepting eSCO connection request from %s", bd_addr.ToString().c_str()); if (!connections_.HasPendingScoConnection(bd_addr)) { LOG_INFO("No pending eSCO connection for %s", bd_addr.ToString().c_str()); return ErrorCode::COMMAND_DISALLOWED; } Loading @@ -3571,27 +3642,26 @@ ErrorCode LinkLayerController::AcceptSynchronousConnection( } // Send eSCO connection response to peer. auto packet = model::packets::EScoConnectionResponseBuilder::Create( SendLinkLayerPacket(model::packets::EScoConnectionResponseBuilder::Create( properties_.GetAddress(), bd_addr, (uint8_t)status, link_parameters.transmission_interval, link_parameters.retransmission_window, link_parameters.rx_packet_length, link_parameters.tx_packet_length, link_parameters.air_mode); SendLinkLayerPacket(std::move(packet)); link_parameters.air_mode)); // Schedule HCI Synchronous Connection Complete event. ScheduleTask(kShortDelayMs, [this, status, sco_handle, bd_addr, link_parameters]() { auto packet = bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( send_event_( bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( ErrorCode(status), sco_handle, bd_addr, bluetooth::hci::ScoLinkType::ESCO, link_parameters.transmission_interval, link_parameters.retransmission_window, link_parameters.rx_packet_length, link_parameters.tx_packet_length, bluetooth::hci::ScoAirMode(link_parameters.air_mode)); send_event_(std::move(packet)); bluetooth::hci::ScoAirMode(link_parameters.air_mode))); }); return ErrorCode::SUCCESS; Loading @@ -3601,6 +3671,9 @@ ErrorCode LinkLayerController::RejectSynchronousConnection( Address bd_addr, uint16_t reason) { LOG_INFO("Rejecting eSCO connection request from %s", bd_addr.ToString().c_str()); if (reason == (uint8_t)ErrorCode::SUCCESS) { reason = (uint8_t)ErrorCode::REMOTE_USER_TERMINATED_CONNECTION; } Loading @@ -3611,16 +3684,14 @@ ErrorCode LinkLayerController::RejectSynchronousConnection( connections_.CancelPendingScoConnection(bd_addr); // Send eSCO connection response to peer. auto packet = model::packets::EScoConnectionResponseBuilder::Create( properties_.GetAddress(), bd_addr, reason, 0, 0, 0, 0, 0); SendLinkLayerPacket(std::move(packet)); SendLinkLayerPacket(model::packets::EScoConnectionResponseBuilder::Create( properties_.GetAddress(), bd_addr, reason, 0, 0, 0, 0, 0)); // Schedule HCI Synchronous Connection Complete event. ScheduleTask(kShortDelayMs, [this, reason, bd_addr]() { auto packet = bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( send_event_(bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( ErrorCode(reason), 0, bd_addr, bluetooth::hci::ScoLinkType::ESCO, 0, 0, 0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT); send_event_(std::move(packet)); 0, 0, 0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT)); }); return ErrorCode::SUCCESS; Loading system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h +2 −1 Original line number Diff line number Diff line Loading @@ -95,7 +95,7 @@ class LinkLayerController { ErrorCode Disconnect(uint16_t handle, uint8_t reason); private: void DisconnectCleanup(uint16_t handle, uint8_t reason); void SendDisconnectionCompleteEvent(uint16_t handle, uint8_t reason); public: void IncomingPacket(model::packets::LinkLayerPacketView incoming); Loading Loading @@ -446,6 +446,7 @@ class LinkLayerController { model::packets::LinkLayerPacketView packet); void IncomingEScoConnectionResponse( model::packets::LinkLayerPacketView packet); void IncomingEScoDisconnect(model::packets::LinkLayerPacketView packet); private: const DeviceProperties& properties_; Loading Loading
system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc +24 −4 Original line number Diff line number Diff line Loading @@ -31,8 +31,12 @@ bool AclConnectionHandler::HasHandle(uint16_t handle) const { return acl_connections_.count(handle) != 0; } bool AclConnectionHandler::HasScoHandle(uint16_t handle) const { return sco_connections_.count(handle) != 0; } uint16_t AclConnectionHandler::GetUnusedHandle() { while (HasHandle(last_handle_) || while (HasHandle(last_handle_) || HasScoHandle(last_handle_) || isochronous_connection_handler_.HasHandle(last_handle_)) { last_handle_ = (last_handle_ + 1) % kReservedHandle; } Loading Loading @@ -131,7 +135,18 @@ uint16_t AclConnectionHandler::CreateLeConnection(AddressWithType addr, } bool AclConnectionHandler::Disconnect(uint16_t handle) { return acl_connections_.erase(handle) > 0; if (HasScoHandle(handle)) { sco_connections_.erase(handle); return true; } if (HasHandle(handle)) { // It is the responsibility of the caller to remove SCO connections // with connected peer first. ASSERT(GetScoHandle(GetAddress(handle).GetAddress()) == 0); acl_connections_.erase(handle); return true; } return false; } uint16_t AclConnectionHandler::GetHandle(AddressWithType addr) const { Loading @@ -154,12 +169,17 @@ uint16_t AclConnectionHandler::GetHandleOnlyAddress( } AddressWithType AclConnectionHandler::GetAddress(uint16_t handle) const { ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle); ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle); return acl_connections_.at(handle).GetAddress(); } Address AclConnectionHandler::GetScoAddress(uint16_t handle) const { ASSERT_LOG(HasScoHandle(handle), "Unknown SCO handle %hd", handle); return sco_connections_.at(handle).GetAddress(); } AddressWithType AclConnectionHandler::GetOwnAddress(uint16_t handle) const { ASSERT_LOG(HasHandle(handle), "Handle unknown %hd", handle); ASSERT_LOG(HasHandle(handle), "Unknown handle %hd", handle); return acl_connections_.at(handle).GetOwnAddress(); } Loading
system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h +2 −0 Original line number Diff line number Diff line Loading @@ -63,10 +63,12 @@ class AclConnectionHandler { bluetooth::hci::AddressWithType own_addr); bool Disconnect(uint16_t handle); bool HasHandle(uint16_t handle) const; bool HasScoHandle(uint16_t handle) const; uint16_t GetHandle(bluetooth::hci::AddressWithType addr) const; uint16_t GetHandleOnlyAddress(bluetooth::hci::Address addr) const; bluetooth::hci::AddressWithType GetAddress(uint16_t handle) const; bluetooth::hci::Address GetScoAddress(uint16_t handle) const; bluetooth::hci::AddressWithType GetOwnAddress(uint16_t handle) const; void Encrypt(uint16_t handle); Loading
system/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc +1 −0 Original line number Diff line number Diff line Loading @@ -568,6 +568,7 @@ void DualModeController::ReadLocalSupportedCommands(CommandView command) { void DualModeController::ReadLocalSupportedFeatures(CommandView command) { auto command_view = gd_hci::ReadLocalSupportedFeaturesView::Create(command); ASSERT(command_view.IsValid()); auto packet = bluetooth::hci::ReadLocalSupportedFeaturesCompleteBuilder::Create( kNumCommandPackets, ErrorCode::SUCCESS, Loading
system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc +140 −69 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "link_layer_controller.h" #include <cinttypes> #include <hci/hci_packets.h> #include "crypto_toolbox/crypto_toolbox.h" Loading Loading @@ -390,6 +391,9 @@ void LinkLayerController::IncomingPacket( case model::packets::PacketType::ESCO_CONNECTION_RESPONSE: IncomingEScoConnectionResponse(incoming); break; case model::packets::PacketType::ESCO_DISCONNECT: IncomingEScoDisconnect(incoming); break; default: LOG_WARN("Dropping unhandled packet of type %s", Loading Loading @@ -627,8 +631,7 @@ void LinkLayerController::IncomingDisconnectPacket( "GetHandle() returned invalid handle %hx", handle); uint8_t reason = disconnect.GetReason(); ScheduleTask(kShortDelayMs, [this, handle, reason]() { DisconnectCleanup(handle, reason); }); SendDisconnectionCompleteEvent(handle, reason); } void LinkLayerController::IncomingEncryptConnection( Loading Loading @@ -1370,23 +1373,37 @@ void LinkLayerController::IncomingEScoConnectionRequest( Address address = incoming.GetSourceAddress(); auto request = model::packets::EScoConnectionRequestView::Create(incoming); ASSERT(request.IsValid()); LOG_INFO("Received eSCO connection request from %s", address.ToString().c_str()); // Automatically reject if connection request was already sent // from the current device. if (connections_.HasPendingScoConnection(address)) { auto packet = model::packets::EScoConnectionResponseBuilder::Create( LOG_INFO("Rejecting eSCO connection request from %s, " "an eSCO connection already exist with this device", address.ToString().c_str()); SendLinkLayerPacket(model::packets::EScoConnectionResponseBuilder::Create( properties_.GetLeAddress(), address, (uint8_t)ErrorCode::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED, 0, 0, 0, 0, 0); SendLinkLayerPacket(std::move(packet)); (uint8_t)ErrorCode::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED, 0, 0, 0, 0, 0)); return; } // Send connection request event to use and wait for Accept or Reject // command. auto packet = bluetooth::hci::ConnectionRequestBuilder::Create( // Create local connection context. ScoConnectionParameters connection_parameters = { request.GetTransmitBandwidth(), request.GetReceiveBandwidth(), request.GetMaxLatency(), request.GetVoiceSetting(), request.GetRetransmissionEffort(), request.GetPacketType() }; connections_.CreatePendingScoConnection(address, connection_parameters); // Send connection request event and wait for Accept or Reject command. send_event_(bluetooth::hci::ConnectionRequestBuilder::Create( address, ClassOfDevice(), bluetooth::hci::ConnectionRequestLinkType::ESCO); send_event_(std::move(packet)); bluetooth::hci::ConnectionRequestLinkType::ESCO)); } void LinkLayerController::IncomingEScoConnectionResponse( Loading @@ -1394,8 +1411,12 @@ void LinkLayerController::IncomingEScoConnectionResponse( Address address = incoming.GetSourceAddress(); auto response = model::packets::EScoConnectionResponseView::Create(incoming); ASSERT(response.IsValid()); auto status = response.GetStatus(); LOG_INFO("Received eSCO connection response with status %" PRIx8 " from %s", status, incoming.GetSourceAddress().ToString().c_str()); if (status == (uint8_t)ErrorCode::SUCCESS) { ScoLinkParameters link_parameters = { response.GetTransmissionInterval(), Loading @@ -1405,23 +1426,38 @@ void LinkLayerController::IncomingEScoConnectionResponse( response.GetAirMode(), }; connections_.AcceptPendingScoConnection(address, link_parameters); auto packet = bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( send_event_(bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( ErrorCode(status), connections_.GetScoHandle(address), address, bluetooth::hci::ScoLinkType::ESCO, response.GetTransmissionInterval(), response.GetRetransmissionWindow(), response.GetRxPacketLength(), response.GetTxPacketLength(), bluetooth::hci::ScoAirMode(response.GetAirMode())); send_event_(std::move(packet)); bluetooth::hci::ScoAirMode(response.GetAirMode()))); } else { connections_.CancelPendingScoConnection(address); auto packet = bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( send_event_(bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( ErrorCode(status), 0, address, bluetooth::hci::ScoLinkType::ESCO, 0, 0, 0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT); 0, 0, 0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT)); } } void LinkLayerController::IncomingEScoDisconnect( model::packets::LinkLayerPacketView incoming) { Address address = incoming.GetSourceAddress(); auto request = model::packets::EScoDisconnectView::Create(incoming); ASSERT(request.IsValid()); auto reason = request.GetReason(); uint16_t handle = connections_.GetScoHandle(address); send_event_(std::move(packet)); LOG_INFO("Received eSCO disconnection request with" " reason 0x%" PRIx8 " from %s", reason, incoming.GetSourceAddress().ToString().c_str()); if (handle != 0) { connections_.Disconnect(handle); SendDisconnectionCompleteEvent(handle, reason); } } Loading Loading @@ -2546,39 +2582,67 @@ ErrorCode LinkLayerController::CreateConnectionCancel(const Address& addr) { return ErrorCode::SUCCESS; } void LinkLayerController::SendDisconnectionCompleteEvent( uint16_t handle, uint8_t reason) { if (properties_.IsUnmasked(EventCode::DISCONNECTION_COMPLETE)) { ScheduleTask(kShortDelayMs, [this, handle, reason]() { send_event_(bluetooth::hci::DisconnectionCompleteBuilder::Create( ErrorCode::SUCCESS, handle, ErrorCode(reason))); }); } } ErrorCode LinkLayerController::Disconnect(uint16_t handle, uint8_t reason) { if (connections_.HasScoHandle(handle)) { const Address remote = connections_.GetScoAddress(handle); LOG_INFO("Disconnecting eSCO connection with %s", remote.ToString().c_str()); SendLinkLayerPacket(model::packets::EScoDisconnectBuilder::Create( properties_.GetAddress(), remote, reason)); connections_.Disconnect(handle); SendDisconnectionCompleteEvent(handle, reason); return ErrorCode::SUCCESS; } if (!connections_.HasHandle(handle)) { return ErrorCode::UNKNOWN_CONNECTION; } const AddressWithType remote = connections_.GetAddress(handle); if (connections_.GetPhyType(handle) == Phy::Type::BR_EDR) { LOG_INFO("Disconnecting ACL connection with %s", remote.ToString().c_str()); uint16_t sco_handle = connections_.GetScoHandle(remote.GetAddress()); if (sco_handle != 0) { SendLinkLayerPacket(model::packets::EScoDisconnectBuilder::Create( properties_.GetAddress(), remote.GetAddress(), reason)); connections_.Disconnect(sco_handle); SendDisconnectionCompleteEvent(sco_handle, reason); } SendLinkLayerPacket(model::packets::DisconnectBuilder::Create( properties_.GetAddress(), remote.GetAddress(), reason)); } else { LOG_INFO("Disconnecting LE connection with %s", remote.ToString().c_str()); SendLeLinkLayerPacket(model::packets::DisconnectBuilder::Create( connections_.GetOwnAddress(handle).GetAddress(), remote.GetAddress(), reason)); } ASSERT_LOG(connections_.Disconnect(handle), "Disconnecting %hx", handle); ScheduleTask(kShortDelayMs, [this, handle]() { DisconnectCleanup( handle, static_cast<uint8_t>(ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST)); }); connections_.Disconnect(handle); SendDisconnectionCompleteEvent(handle, reason); return ErrorCode::SUCCESS; } void LinkLayerController::DisconnectCleanup(uint16_t handle, uint8_t reason) { // TODO: Clean up other connection state. if (properties_.IsUnmasked(EventCode::DISCONNECTION_COMPLETE)) { send_event_(bluetooth::hci::DisconnectionCompleteBuilder::Create( ErrorCode::SUCCESS, handle, static_cast<ErrorCode>(reason))); } } ErrorCode LinkLayerController::ChangeConnectionPacketType(uint16_t handle, uint16_t types) { if (!connections_.HasHandle(handle)) { Loading Loading @@ -3515,6 +3579,7 @@ ErrorCode LinkLayerController::SetupSynchronousConnection( if (!connections_.HasHandle(connection_handle)) { return ErrorCode::UNKNOWN_CONNECTION; } Address bd_addr = connections_.GetAddress(connection_handle).GetAddress(); if (connections_.HasPendingScoConnection(bd_addr)) { // This command may be used to modify an exising eSCO link. Loading @@ -3523,6 +3588,8 @@ ErrorCode LinkLayerController::SetupSynchronousConnection( return ErrorCode::COMMAND_DISALLOWED; } LOG_INFO("Creating eSCO connection with %s", bd_addr.ToString().c_str()); // Save connection parameters. ScoConnectionParameters connection_parameters = { transmit_bandwidth, receive_bandwidth, max_latency, Loading @@ -3533,11 +3600,10 @@ ErrorCode LinkLayerController::SetupSynchronousConnection( connection_parameters); // Send eSCO connection request to peer. auto packet = model::packets::EScoConnectionRequestBuilder::Create( SendLinkLayerPacket(model::packets::EScoConnectionRequestBuilder::Create( properties_.GetAddress(), bd_addr, transmit_bandwidth, receive_bandwidth, max_latency, voice_setting, retransmission_effort, packet_types); SendLinkLayerPacket(std::move(packet)); voice_setting, retransmission_effort, packet_types)); return ErrorCode::SUCCESS; } Loading @@ -3550,7 +3616,12 @@ ErrorCode LinkLayerController::AcceptSynchronousConnection( uint8_t retransmission_effort, uint16_t packet_types) { LOG_INFO("Accepting eSCO connection request from %s", bd_addr.ToString().c_str()); if (!connections_.HasPendingScoConnection(bd_addr)) { LOG_INFO("No pending eSCO connection for %s", bd_addr.ToString().c_str()); return ErrorCode::COMMAND_DISALLOWED; } Loading @@ -3571,27 +3642,26 @@ ErrorCode LinkLayerController::AcceptSynchronousConnection( } // Send eSCO connection response to peer. auto packet = model::packets::EScoConnectionResponseBuilder::Create( SendLinkLayerPacket(model::packets::EScoConnectionResponseBuilder::Create( properties_.GetAddress(), bd_addr, (uint8_t)status, link_parameters.transmission_interval, link_parameters.retransmission_window, link_parameters.rx_packet_length, link_parameters.tx_packet_length, link_parameters.air_mode); SendLinkLayerPacket(std::move(packet)); link_parameters.air_mode)); // Schedule HCI Synchronous Connection Complete event. ScheduleTask(kShortDelayMs, [this, status, sco_handle, bd_addr, link_parameters]() { auto packet = bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( send_event_( bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( ErrorCode(status), sco_handle, bd_addr, bluetooth::hci::ScoLinkType::ESCO, link_parameters.transmission_interval, link_parameters.retransmission_window, link_parameters.rx_packet_length, link_parameters.tx_packet_length, bluetooth::hci::ScoAirMode(link_parameters.air_mode)); send_event_(std::move(packet)); bluetooth::hci::ScoAirMode(link_parameters.air_mode))); }); return ErrorCode::SUCCESS; Loading @@ -3601,6 +3671,9 @@ ErrorCode LinkLayerController::RejectSynchronousConnection( Address bd_addr, uint16_t reason) { LOG_INFO("Rejecting eSCO connection request from %s", bd_addr.ToString().c_str()); if (reason == (uint8_t)ErrorCode::SUCCESS) { reason = (uint8_t)ErrorCode::REMOTE_USER_TERMINATED_CONNECTION; } Loading @@ -3611,16 +3684,14 @@ ErrorCode LinkLayerController::RejectSynchronousConnection( connections_.CancelPendingScoConnection(bd_addr); // Send eSCO connection response to peer. auto packet = model::packets::EScoConnectionResponseBuilder::Create( properties_.GetAddress(), bd_addr, reason, 0, 0, 0, 0, 0); SendLinkLayerPacket(std::move(packet)); SendLinkLayerPacket(model::packets::EScoConnectionResponseBuilder::Create( properties_.GetAddress(), bd_addr, reason, 0, 0, 0, 0, 0)); // Schedule HCI Synchronous Connection Complete event. ScheduleTask(kShortDelayMs, [this, reason, bd_addr]() { auto packet = bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( send_event_(bluetooth::hci::SynchronousConnectionCompleteBuilder::Create( ErrorCode(reason), 0, bd_addr, bluetooth::hci::ScoLinkType::ESCO, 0, 0, 0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT); send_event_(std::move(packet)); 0, 0, 0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT)); }); return ErrorCode::SUCCESS; Loading
system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h +2 −1 Original line number Diff line number Diff line Loading @@ -95,7 +95,7 @@ class LinkLayerController { ErrorCode Disconnect(uint16_t handle, uint8_t reason); private: void DisconnectCleanup(uint16_t handle, uint8_t reason); void SendDisconnectionCompleteEvent(uint16_t handle, uint8_t reason); public: void IncomingPacket(model::packets::LinkLayerPacketView incoming); Loading Loading @@ -446,6 +446,7 @@ class LinkLayerController { model::packets::LinkLayerPacketView packet); void IncomingEScoConnectionResponse( model::packets::LinkLayerPacketView packet); void IncomingEScoDisconnect(model::packets::LinkLayerPacketView packet); private: const DeviceProperties& properties_; Loading