Root-Canal: Fix SCO / eSCO connection bringup
- Recognize HCI command Accept Connection Request for
accepting SCO connections
- Correct usage of negative packet type bits
Bug: 209800014
Tag: #feature
Test: cert/run
Change-Id: If9703aa2ce2aca858040798ca9dc03badbbb3bfc
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
index 8da3f28..e70a8c8 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
+++ b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
@@ -431,7 +431,7 @@
}
bool AclConnectionHandler::HasPendingScoConnection(bluetooth::hci::Address addr) const {
- for (auto pair : sco_connections_) {
+ for (const auto& pair : sco_connections_) {
if (std::get<ScoConnection>(pair).GetAddress() == addr) {
ScoState state = std::get<ScoConnection>(pair).GetState();
return state == SCO_STATE_PENDING ||
@@ -443,7 +443,7 @@
}
ScoState AclConnectionHandler::GetScoConnectionState(bluetooth::hci::Address addr) const {
- for (auto pair : sco_connections_) {
+ for (const auto& pair : sco_connections_) {
if (std::get<ScoConnection>(pair).GetAddress() == addr) {
return std::get<ScoConnection>(pair).GetState();
}
@@ -452,7 +452,7 @@
}
bool AclConnectionHandler::IsLegacyScoConnection(bluetooth::hci::Address addr) const {
- for (auto pair : sco_connections_) {
+ for (const auto& pair : sco_connections_) {
if (std::get<ScoConnection>(pair).GetAddress() == addr) {
return std::get<ScoConnection>(pair).IsLegacy();
}
@@ -471,8 +471,7 @@
bool AclConnectionHandler::AcceptPendingScoConnection(bluetooth::hci::Address addr,
ScoLinkParameters const ¶meters) {
-
- for (auto pair : sco_connections_) {
+ for (auto& pair : sco_connections_) {
if (std::get<ScoConnection>(pair).GetAddress() == addr) {
std::get<ScoConnection>(pair).SetLinkParameters(parameters);
std::get<ScoConnection>(pair).SetState(ScoState::SCO_STATE_OPENED);
@@ -484,8 +483,7 @@
bool AclConnectionHandler::AcceptPendingScoConnection(bluetooth::hci::Address addr,
ScoConnectionParameters const ¶meters) {
-
- for (auto pair : sco_connections_) {
+ for (auto& pair : sco_connections_) {
if (std::get<ScoConnection>(pair).GetAddress() == addr) {
bool ok = std::get<ScoConnection>(pair).NegotiateLinkParameters(parameters);
std::get<ScoConnection>(pair).SetState(
@@ -497,7 +495,7 @@
}
uint16_t AclConnectionHandler::GetScoHandle(bluetooth::hci::Address addr) const {
- for (auto pair : sco_connections_) {
+ for (const auto& pair : sco_connections_) {
if (std::get<ScoConnection>(pair).GetAddress() == addr) {
return std::get<0>(pair);
}
@@ -505,8 +503,18 @@
return 0;
}
+ScoConnectionParameters AclConnectionHandler::GetScoConnectionParameters(
+ bluetooth::hci::Address addr) const {
+ for (const auto& pair : sco_connections_) {
+ if (std::get<ScoConnection>(pair).GetAddress() == addr) {
+ return std::get<ScoConnection>(pair).GetConnectionParameters();
+ }
+ }
+ return {};
+}
+
ScoLinkParameters AclConnectionHandler::GetScoLinkParameters(bluetooth::hci::Address addr) const {
- for (auto pair : sco_connections_) {
+ for (const auto& pair : sco_connections_) {
if (std::get<ScoConnection>(pair).GetAddress() == addr) {
return std::get<ScoConnection>(pair).GetLinkParameters();
}
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
index 58f8f50..0199609 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
+++ b/system/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
@@ -53,6 +53,8 @@
bool AcceptPendingScoConnection(bluetooth::hci::Address addr,
ScoConnectionParameters const ¶meters);
uint16_t GetScoHandle(bluetooth::hci::Address addr) const;
+ ScoConnectionParameters GetScoConnectionParameters(
+ bluetooth::hci::Address addr) const;
ScoLinkParameters GetScoLinkParameters(bluetooth::hci::Address addr) const;
bool CreatePendingLeConnection(bluetooth::hci::AddressWithType addr);
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
index b965428..f65219d 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
+++ b/system/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
@@ -1505,9 +1505,11 @@
bluetooth::hci::LinkType::SCO,
bluetooth::hci::Enable::DISABLED));
} else {
+ ScoConnectionParameters connection_parameters =
+ connections_.GetScoConnectionParameters(address);
send_event_(bluetooth::hci::SynchronousConnectionCompleteBuilder::Create(
status, 0, address,
- response.GetExtended() ?
+ connection_parameters.IsExtended() ?
bluetooth::hci::ScoLinkType::ESCO :
bluetooth::hci::ScoLinkType::SCO,
0, 0, 0, 0, bluetooth::hci::ScoAirMode::TRANSPARENT));
@@ -2571,20 +2573,59 @@
return ErrorCode::SUCCESS;
}
-ErrorCode LinkLayerController::AcceptConnectionRequest(const Address& addr,
+ErrorCode LinkLayerController::AcceptConnectionRequest(const Address& bd_addr,
bool try_role_switch) {
- if (!connections_.HasPendingConnection(addr)) {
- LOG_INFO("No pending connection for %s", addr.ToString().c_str());
- return ErrorCode::UNKNOWN_CONNECTION;
+ if (connections_.HasPendingConnection(bd_addr)) {
+ LOG_INFO("Accepting connection request from %s",
+ bd_addr.ToString().c_str());
+ ScheduleTask(kLongDelayMs, [this, bd_addr, try_role_switch]() {
+ LOG_INFO("Accepted connection from %s", bd_addr.ToString().c_str());
+ MakePeripheralConnection(bd_addr, try_role_switch);
+ });
+
+ return ErrorCode::SUCCESS;
}
- LOG_INFO("Accept in 200ms");
- ScheduleTask(kLongDelayMs, [this, addr, try_role_switch]() {
- LOG_INFO("Accepted");
- MakePeripheralConnection(addr, try_role_switch);
- });
+ // The HCI command Accept Connection may be used to accept incoming SCO
+ // connection requests.
+ if (connections_.HasPendingScoConnection(bd_addr)) {
+ ErrorCode status = ErrorCode::SUCCESS;
+ uint16_t sco_handle = 0;
+ ScoLinkParameters link_parameters = {};
+ ScoConnectionParameters connection_parameters =
+ connections_.GetScoConnectionParameters(bd_addr);
- return ErrorCode::SUCCESS;
+ if (!connections_.AcceptPendingScoConnection(
+ bd_addr, connection_parameters)) {
+ connections_.CancelPendingScoConnection(bd_addr);
+ status = ErrorCode::SCO_INTERVAL_REJECTED; // TODO: proper status code
+ } else {
+ sco_handle = connections_.GetScoHandle(bd_addr);
+ link_parameters = connections_.GetScoLinkParameters(bd_addr);
+ }
+
+ // Send eSCO connection response to peer.
+ SendLinkLayerPacket(model::packets::ScoConnectionResponseBuilder::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,
+ link_parameters.extended));
+
+ // Schedule HCI Connection Complete event.
+ ScheduleTask(kShortDelayMs, [this, status, sco_handle, bd_addr]() {
+ send_event_(bluetooth::hci::ConnectionCompleteBuilder::Create(
+ ErrorCode(status), sco_handle, bd_addr, bluetooth::hci::LinkType::SCO,
+ bluetooth::hci::Enable::DISABLED));
+ });
+
+ return ErrorCode::SUCCESS;
+ }
+
+ LOG_INFO("No pending connection for %s", bd_addr.ToString().c_str());
+ return ErrorCode::UNKNOWN_CONNECTION;
}
void LinkLayerController::MakePeripheralConnection(const Address& addr,
@@ -3658,9 +3699,14 @@
// Save connection parameters.
ScoConnectionParameters connection_parameters = {
- 8000, 8000, 0xffff, 0x60 /* 16bit CVSD */,
- (uint8_t)bluetooth::hci::RetransmissionEffort::NO_RETRANSMISSION,
- (uint16_t)((packet_type >> 5) & 0x7u)
+ 8000, 8000, 0xffff, 0x60 /* 16bit CVSD */,
+ (uint8_t)bluetooth::hci::RetransmissionEffort::NO_RETRANSMISSION,
+ (uint16_t)(
+ (uint16_t)((packet_type >> 5) & 0x7u) |
+ (uint16_t)bluetooth::hci::SynchronousPacketTypeBits::NO_2_EV3_ALLOWED |
+ (uint16_t)bluetooth::hci::SynchronousPacketTypeBits::NO_3_EV3_ALLOWED |
+ (uint16_t)bluetooth::hci::SynchronousPacketTypeBits::NO_2_EV5_ALLOWED |
+ (uint16_t)bluetooth::hci::SynchronousPacketTypeBits::NO_3_EV5_ALLOWED)
};
connections_.CreateScoConnection(
connections_.GetAddress(connection_handle).GetAddress(),
@@ -3746,7 +3792,7 @@
if (!connections_.AcceptPendingScoConnection(bd_addr, connection_parameters)) {
connections_.CancelPendingScoConnection(bd_addr);
- status = ErrorCode::SCO_INTERVAL_REJECTED; // TODO: proper status code
+ status = ErrorCode::STATUS_UNKNOWN; // TODO: proper status code
} else {
sco_handle = connections_.GetScoHandle(bd_addr);
link_parameters = connections_.GetScoLinkParameters(bd_addr);
diff --git a/system/vendor_libs/test_vendor_lib/model/controller/sco_connection.cc b/system/vendor_libs/test_vendor_lib/model/controller/sco_connection.cc
index 86efd71..6f577ef 100644
--- a/system/vendor_libs/test_vendor_lib/model/controller/sco_connection.cc
+++ b/system/vendor_libs/test_vendor_lib/model/controller/sco_connection.cc
@@ -29,7 +29,12 @@
(uint16_t)SynchronousPacketTypeBits::HV1_ALLOWED |
(uint16_t)SynchronousPacketTypeBits::HV2_ALLOWED |
(uint16_t)SynchronousPacketTypeBits::HV3_ALLOWED;
- return (packet_type & ~legacy) != 0;
+ uint16_t edr =
+ (uint16_t)SynchronousPacketTypeBits::NO_2_EV3_ALLOWED |
+ (uint16_t)SynchronousPacketTypeBits::NO_3_EV3_ALLOWED |
+ (uint16_t)SynchronousPacketTypeBits::NO_2_EV5_ALLOWED |
+ (uint16_t)SynchronousPacketTypeBits::NO_3_EV5_ALLOWED;
+ return ((packet_type ^ edr) & ~legacy) != 0;
}
std::optional<ScoLinkParameters> ScoConnectionParameters::GetLinkParameters() {
@@ -165,6 +170,7 @@
if (retransmission_effort == (uint8_t)RetransmissionEffort::OPTIMIZED_FOR_POWER ||
retransmission_effort == (uint8_t)RetransmissionEffort::OPTIMIZED_FOR_LINK_QUALITY) {
+ LOG_WARN("SCO Retransmission effort must be None or Don't care");
return {};
}
@@ -174,6 +180,7 @@
uint8_t air_coding = voice_setting & 0x3;
if (max_latency != 0xffff && max_latency < latency) {
+ LOG_WARN("SCO Max latency must be less than 1250 us");
return {};
}
@@ -183,10 +190,11 @@
} else if (packet_type & (uint16_t)SynchronousPacketTypeBits::HV2_ALLOWED) {
transmission_interval = 4;
packet_length = 20;
- } else if (packet_type & (uint16_t)SynchronousPacketTypeBits::HV3_ALLOWED) {
+ } else if (packet_type & (uint16_t)SynchronousPacketTypeBits::HV1_ALLOWED) {
transmission_interval = 2;
packet_length = 10;
} else {
+ LOG_WARN("No SCO packet type enabled");
return {};
}
@@ -225,7 +233,7 @@
uint16_t packet_type = (peer.packet_type & parameters_.packet_type) & 0x3f;
packet_type |= (peer.packet_type | parameters_.packet_type) & 0x3c0;
- if (packet_type == 0) {
+ if (packet_type == 0x3c0) {
LOG_WARN("Packet type requirements cannot be met");
LOG_WARN("Remote packet type: 0x%04x",
static_cast<unsigned>(parameters_.packet_type));