summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Henri Chataing <henrichataing@google.com> 2022-08-22 21:06:44 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2022-08-22 21:06:44 +0000
commit640e18c4d130e68abd36b972cd502906df9da7cc (patch)
tree67a3f61926708bbf0dff05ff9a3f8edf7aaf5362
parent73b96272ba5f9b5b36789e1728dba6c669829713 (diff)
parent78e858b62a0cbb6760f67bad3f4a40bd63cc9e07 (diff)
Merge "RootCanal: Implement support for enhanced synchronous link commands"
-rw-r--r--system/gd/hci/hci_packets.pdl78
-rw-r--r--tools/rootcanal/model/controller/dual_mode_controller.cc317
-rw-r--r--tools/rootcanal/model/controller/dual_mode_controller.h9
3 files changed, 371 insertions, 33 deletions
diff --git a/system/gd/hci/hci_packets.pdl b/system/gd/hci/hci_packets.pdl
index 5cc475ae7e..cadc0c696c 100644
--- a/system/gd/hci/hci_packets.pdl
+++ b/system/gd/hci/hci_packets.pdl
@@ -1168,6 +1168,26 @@ packet ReadLmpHandleComplete : CommandComplete (command_op_code = READ_LMP_HANDL
_reserved_ : 32,
}
+enum SynchronousPacketTypeBits : 16 {
+ HV1_ALLOWED = 0x0001,
+ HV2_ALLOWED = 0x0002,
+ HV3_ALLOWED = 0x0004,
+ EV3_ALLOWED = 0x0008,
+ EV4_ALLOWED = 0x0010,
+ EV5_ALLOWED = 0x0020,
+ NO_2_EV3_ALLOWED = 0x0040,
+ NO_3_EV3_ALLOWED = 0x0080,
+ NO_2_EV5_ALLOWED = 0x0100,
+ NO_3_EV5_ALLOWED = 0x0200,
+}
+
+enum RetransmissionEffort : 8 {
+ NO_RETRANSMISSION = 0x00,
+ OPTIMIZED_FOR_POWER = 0x01,
+ OPTIMIZED_FOR_LINK_QUALITY = 0x02,
+ DO_NOT_CARE = 0xFF,
+}
+
packet SetupSynchronousConnection : ScoConnectionCommand (op_code = SETUP_SYNCHRONOUS_CONNECTION) {
connection_handle : 12,
_reserved_ : 4,
@@ -1176,8 +1196,8 @@ packet SetupSynchronousConnection : ScoConnectionCommand (op_code = SETUP_SYNCHR
max_latency : 16, // 0-3 reserved, 0xFFFF = don't care
voice_setting : 10,
_reserved_ : 6,
- retransmission_effort : 8,
- packet_type : 16,
+ retransmission_effort : RetransmissionEffort,
+ packet_type : 16, // See SynchronousPacketTypeBits
}
packet SetupSynchronousConnectionStatus : CommandStatus (command_op_code = SETUP_SYNCHRONOUS_CONNECTION) {
@@ -1190,8 +1210,8 @@ packet AcceptSynchronousConnection : ScoConnectionCommand (op_code = ACCEPT_SYNC
max_latency : 16, // 0-3 reserved, 0xFFFF = don't care
voice_setting : 10,
_reserved_ : 6,
- retransmission_effort : 8,
- packet_type : 16,
+ retransmission_effort : RetransmissionEffort,
+ packet_type : 16, // See SynchronousPacketTypeBits
}
packet AcceptSynchronousConnectionStatus : CommandStatus (command_op_code = ACCEPT_SYNCHRONOUS_CONNECTION) {
@@ -1342,34 +1362,14 @@ enum ScoDataPath : 8 {
AUDIO_TEST_MODE = 0xFF,
}
-enum SynchronousPacketTypeBits : 16 {
- HV1_ALLOWED = 0x0001,
- HV2_ALLOWED = 0x0002,
- HV3_ALLOWED = 0x0004,
- EV3_ALLOWED = 0x0008,
- EV4_ALLOWED = 0x0010,
- EV5_ALLOWED = 0x0020,
- NO_2_EV3_ALLOWED = 0x0040,
- NO_3_EV3_ALLOWED = 0x0080,
- NO_2_EV5_ALLOWED = 0x0100,
- NO_3_EV5_ALLOWED = 0x0200,
-}
-
-enum RetransmissionEffort : 8 {
- NO_RETRANSMISSION = 0x00,
- OPTIMIZED_FOR_POWER = 0x01,
- OPTIMIZED_FOR_LINK_QUALITY = 0x02,
- DO_NOT_CARE = 0xFF,
-}
-
packet EnhancedSetupSynchronousConnection : ScoConnectionCommand (op_code = ENHANCED_SETUP_SYNCHRONOUS_CONNECTION) {
connection_handle: 12,
_reserved_ : 4,
// Next two items
// [0x00000000, 0xFFFFFFFE] Bandwidth in octets per second.
// [0xFFFFFFFF]: Don't care
- transmit_bandwidth_octets_per_second : 32,
- receive_bandwidth_octets_per_second : 32,
+ transmit_bandwidth : 32,
+ receive_bandwidth : 32,
transmit_coding_format : ScoCodingFormat,
receive_coding_format : ScoCodingFormat,
// Next two items
@@ -1379,8 +1379,8 @@ packet EnhancedSetupSynchronousConnection : ScoConnectionCommand (op_code = ENHA
receive_codec_frame_size : 16,
// Next two items
// Host to Controller nominal data rate in octets per second.
- input_bandwidth_octets_per_second : 32,
- output_bandwidth_octets_per_second : 32,
+ input_bandwidth : 32,
+ output_bandwidth : 32,
input_coding_format : ScoCodingFormat,
output_coding_format : ScoCodingFormat,
// Next two items
@@ -1407,11 +1407,15 @@ packet EnhancedSetupSynchronousConnection : ScoConnectionCommand (op_code = ENHA
// of the eSCO window, where the eSCO window is reserved slots plus the
// retransmission window
// [0xFFFF]: don't care
- max_latency_ms: 16,
- packet_type : 16, // Or together SynchronousPacketTypeBits
+ max_latency: 16,
+ packet_type : 16, // See SynchronousPacketTypeBits
retransmission_effort : RetransmissionEffort,
}
+test EnhancedSetupSynchronousConnection {
+ "\x3d\x04\x3b\x02\x00\x40\x1f\x00\x00\x40\x1f\x00\x00\x05\x00\x00\x00\x00\x05\x00\x00\x00\x00\x3c\x00\x3c\x00\x00\x7d\x00\x00\x00\x7d\x00\x00\x04\x00\x00\x00\x00\x04\x00\x00\x00\x00\x10\x00\x10\x00\x02\x02\x00\x00\x01\x01\x00\x00\x0d\x00\x88\x03\x02",
+}
+
packet EnhancedSetupSynchronousConnectionStatus : CommandStatus (command_op_code = ENHANCED_SETUP_SYNCHRONOUS_CONNECTION) {
}
@@ -1460,7 +1464,7 @@ packet EnhancedAcceptSynchronousConnection : ScoConnectionCommand (op_code = ENH
// retransmission window
// [0xFFFF]: don't care
max_latency : 16,
- packet_type : 16, // Or together SynchronousPacketTypeBits
+ packet_type : 16, // See SynchronousPacketTypeBits
retransmission_effort : RetransmissionEffort,
}
@@ -5342,6 +5346,10 @@ packet SynchronousConnectionComplete : Event (event_code = SYNCHRONOUS_CONNECTIO
air_mode : ScoAirMode,
}
+test SynchronousConnectionComplete {
+ "\x2c\x11\x00\x03\x00\x1d\xdf\xed\x2b\x1a\xf8\x02\x0c\x04\x3c\x00\x3c\x00\x03",
+}
+
packet SynchronousConnectionChanged : Event (event_code = SYNCHRONOUS_CONNECTION_CHANGED) {
status : ErrorCode,
connection_handle : 12,
@@ -5435,6 +5443,10 @@ packet EnhancedFlush : Command (op_code = ENHANCED_FLUSH) {
packet_type : FlushablePacketType,
}
+test EnhancedFlush {
+ "\x5f\x0c\x03\x02\x00\x00",
+}
+
packet EnhancedFlushStatus : CommandStatus (command_op_code = ENHANCED_FLUSH) {
}
@@ -5443,6 +5455,10 @@ packet EnhancedFlushComplete : Event (event_code = ENHANCED_FLUSH_COMPLETE) {
_reserved_ : 4,
}
+test EnhancedFlushComplete {
+ "\x39\x02\x02\x00",
+}
+
packet UserPasskeyNotification : Event (event_code = USER_PASSKEY_NOTIFICATION) {
bd_addr : Address,
passkey : 20, // 0x00000-0xF423F (000000 - 999999)
diff --git a/tools/rootcanal/model/controller/dual_mode_controller.cc b/tools/rootcanal/model/controller/dual_mode_controller.cc
index f0df052ce7..4e67077879 100644
--- a/tools/rootcanal/model/controller/dual_mode_controller.cc
+++ b/tools/rootcanal/model/controller/dual_mode_controller.cc
@@ -126,6 +126,10 @@ DualModeController::DualModeController(const std::string& properties_filename,
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,
@@ -145,6 +149,7 @@ DualModeController::DualModeController(const std::string& properties_filename,
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);
@@ -684,7 +689,8 @@ void DualModeController::SetupSynchronousConnection(CommandView command) {
auto status = link_layer_controller_.SetupSynchronousConnection(
command_view.GetConnectionHandle(), command_view.GetTransmitBandwidth(),
command_view.GetReceiveBandwidth(), command_view.GetMaxLatency(),
- command_view.GetVoiceSetting(), command_view.GetRetransmissionEffort(),
+ command_view.GetVoiceSetting(),
+ static_cast<uint8_t>(command_view.GetRetransmissionEffort()),
command_view.GetPacketType());
send_event_(bluetooth::hci::SetupSynchronousConnectionStatusBuilder::Create(
@@ -700,13 +706,304 @@ void DualModeController::AcceptSynchronousConnection(CommandView command) {
auto status = link_layer_controller_.AcceptSynchronousConnection(
command_view.GetBdAddr(), command_view.GetTransmitBandwidth(),
command_view.GetReceiveBandwidth(), command_view.GetMaxLatency(),
- command_view.GetVoiceSetting(), command_view.GetRetransmissionEffort(),
+ command_view.GetVoiceSetting(),
+ static_cast<uint8_t>(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.
+ if (command_view.GetInputDataPath() != bluetooth::hci::ScoDataPath::HCI ||
+ command_view.GetOutputDataPath() != bluetooth::hci::ScoDataPath::HCI) {
+ LOG_INFO(
+ "EnhancedSetupSynchronousConnection: rejected Input_Data_Path (%u)"
+ " and/or Output_Data_Path (%u) as they are un-implemented",
+ static_cast<unsigned>(command_view.GetInputDataPath()),
+ static_cast<unsigned>(command_view.GetOutputDataPath()));
+ status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
+ }
+
+ // 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 &&
+ transmit_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) !=
+ (transmit_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 &&
+ receive_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) !=
+ (receive_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(), 0 /* Voice_Setting */,
+ static_cast<uint8_t>(command_view.GetRetransmissionEffort()),
+ command_view.GetPacketType());
+ }
+
+ 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(
+ "EnhancedAcceptSynchronousConnection: rejected Input_Data_Path (%u)"
+ " and/or Output_Data_Path (%u) as they are un-implemented",
+ static_cast<unsigned>(command_view.GetInputDataPath()),
+ static_cast<unsigned>(command_view.GetOutputDataPath()));
+ status = ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
+ }
+
+ // 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 &&
+ transmit_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) !=
+ (transmit_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 &&
+ receive_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) !=
+ (receive_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(), 0 /* Voice_Setting */,
+ static_cast<uint8_t>(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(
@@ -959,6 +1256,22 @@ void DualModeController::SendKeypressNotification(CommandView command) {
#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 (properties_.IsUnmasked(EventCode::ENHANCED_FLUSH_COMPLETE)) {
+ send_event_(bluetooth::hci::EnhancedFlushCompleteBuilder::Create(handle));
+ }
+}
+
void DualModeController::SetEventMaskPage2(CommandView command) {
auto payload =
std::make_unique<bluetooth::packet::RawBuilder>(std::vector<uint8_t>(
diff --git a/tools/rootcanal/model/controller/dual_mode_controller.h b/tools/rootcanal/model/controller/dual_mode_controller.h
index 8b9dd6d6cc..45a5e36562 100644
--- a/tools/rootcanal/model/controller/dual_mode_controller.h
+++ b/tools/rootcanal/model/controller/dual_mode_controller.h
@@ -222,6 +222,12 @@ class DualModeController : public Device {
// 7.1.36
void IoCapabilityRequestNegativeReply(CommandView args);
+ // 7.1.45
+ void EnhancedSetupSynchronousConnection(CommandView args);
+
+ // 7.1.46
+ void EnhancedAcceptSynchronousConnection(CommandView args);
+
// 7.1.53
void RemoteOobExtendedDataRequestReply(CommandView args);
@@ -372,6 +378,9 @@ class DualModeController : public Device {
// 7.3.63
void SendKeypressNotification(CommandView args);
+ // 7.3.66
+ void EnhancedFlush(CommandView args);
+
// 7.3.69
void SetEventMaskPage2(CommandView args);