Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03df18fa authored by Henri Chataing's avatar Henri Chataing Committed by Thomas Girardier
Browse files

RootCanal: Implement support for enhanced synchronous link commands

- Implement ENHANCED_SETUP_SYNCHRONOUS_CONNECTION and
  ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION

- Homogenize the definitions of the synchronous link commands
  in the HCI PDL source specification

Bug: 245578454
Test: None
Ignore-AOSP-First: Cherry-picked from AOSP
Merged-In: I8aade082b4dcf9ad42965c598bb4bfb0ce24e62b
Change-Id: I8aade082b4dcf9ad42965c598bb4bfb0ce24e62b
parent e1e4894e
Loading
Loading
Loading
Loading
+47 −31
Original line number Original line Diff line number Diff line
@@ -1168,6 +1168,26 @@ packet ReadLmpHandleComplete : CommandComplete (command_op_code = READ_LMP_HANDL
  _reserved_ : 32,
  _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) {
packet SetupSynchronousConnection : ScoConnectionCommand (op_code = SETUP_SYNCHRONOUS_CONNECTION) {
  connection_handle : 12,
  connection_handle : 12,
  _reserved_ : 4,
  _reserved_ : 4,
@@ -1176,8 +1196,8 @@ packet SetupSynchronousConnection : ScoConnectionCommand (op_code = SETUP_SYNCHR
  max_latency : 16, // 0-3 reserved, 0xFFFF = don't care
  max_latency : 16, // 0-3 reserved, 0xFFFF = don't care
  voice_setting : 10,
  voice_setting : 10,
  _reserved_ : 6,
  _reserved_ : 6,
  retransmission_effort : 8,
  retransmission_effort : RetransmissionEffort,
  packet_type : 16,
  packet_type : 16, // See SynchronousPacketTypeBits
}
}


packet SetupSynchronousConnectionStatus : CommandStatus (command_op_code = SETUP_SYNCHRONOUS_CONNECTION) {
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
  max_latency : 16, // 0-3 reserved, 0xFFFF = don't care
  voice_setting : 10,
  voice_setting : 10,
  _reserved_ : 6,
  _reserved_ : 6,
  retransmission_effort : 8,
  retransmission_effort : RetransmissionEffort,
  packet_type : 16,
  packet_type : 16, // See SynchronousPacketTypeBits
}
}


packet AcceptSynchronousConnectionStatus : CommandStatus (command_op_code = ACCEPT_SYNCHRONOUS_CONNECTION) {
packet AcceptSynchronousConnectionStatus : CommandStatus (command_op_code = ACCEPT_SYNCHRONOUS_CONNECTION) {
@@ -1342,34 +1362,14 @@ enum ScoDataPath : 8 {
  AUDIO_TEST_MODE = 0xFF,
  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) {
packet EnhancedSetupSynchronousConnection : ScoConnectionCommand (op_code = ENHANCED_SETUP_SYNCHRONOUS_CONNECTION) {
  connection_handle: 12,
  connection_handle: 12,
  _reserved_ : 4,
  _reserved_ : 4,
  // Next two items
  // Next two items
  // [0x00000000, 0xFFFFFFFE] Bandwidth in octets per second.
  // [0x00000000, 0xFFFFFFFE] Bandwidth in octets per second.
  // [0xFFFFFFFF]: Don't care
  // [0xFFFFFFFF]: Don't care
  transmit_bandwidth_octets_per_second : 32,
  transmit_bandwidth : 32,
  receive_bandwidth_octets_per_second : 32,
  receive_bandwidth : 32,
  transmit_coding_format : ScoCodingFormat,
  transmit_coding_format : ScoCodingFormat,
  receive_coding_format : ScoCodingFormat,
  receive_coding_format : ScoCodingFormat,
  // Next two items
  // Next two items
@@ -1379,8 +1379,8 @@ packet EnhancedSetupSynchronousConnection : ScoConnectionCommand (op_code = ENHA
  receive_codec_frame_size : 16,
  receive_codec_frame_size : 16,
  // Next two items
  // Next two items
  // Host to Controller nominal data rate in octets per second.
  // Host to Controller nominal data rate in octets per second.
  input_bandwidth_octets_per_second : 32,
  input_bandwidth : 32,
  output_bandwidth_octets_per_second : 32,
  output_bandwidth : 32,
  input_coding_format : ScoCodingFormat,
  input_coding_format : ScoCodingFormat,
  output_coding_format : ScoCodingFormat,
  output_coding_format : ScoCodingFormat,
  // Next two items
  // 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
  //     of the eSCO window, where the eSCO window is reserved slots plus the
  //     retransmission window
  //     retransmission window
  // [0xFFFF]: don't care
  // [0xFFFF]: don't care
  max_latency_ms: 16,
  max_latency: 16,
  packet_type : 16, // Or together SynchronousPacketTypeBits
  packet_type : 16, // See SynchronousPacketTypeBits
  retransmission_effort : RetransmissionEffort,
  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) {
packet EnhancedSetupSynchronousConnectionStatus : CommandStatus (command_op_code = ENHANCED_SETUP_SYNCHRONOUS_CONNECTION) {
}
}


@@ -1460,7 +1464,7 @@ packet EnhancedAcceptSynchronousConnection : ScoConnectionCommand (op_code = ENH
  //     retransmission window
  //     retransmission window
  // [0xFFFF]: don't care
  // [0xFFFF]: don't care
  max_latency : 16,
  max_latency : 16,
  packet_type : 16, // Or together SynchronousPacketTypeBits
  packet_type : 16, // See SynchronousPacketTypeBits
  retransmission_effort : RetransmissionEffort,
  retransmission_effort : RetransmissionEffort,
}
}


@@ -5351,6 +5355,10 @@ packet SynchronousConnectionComplete : Event (event_code = SYNCHRONOUS_CONNECTIO
  air_mode : ScoAirMode,
  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) {
packet SynchronousConnectionChanged : Event (event_code = SYNCHRONOUS_CONNECTION_CHANGED) {
  status : ErrorCode,
  status : ErrorCode,
  connection_handle : 12,
  connection_handle : 12,
@@ -5444,6 +5452,10 @@ packet EnhancedFlush : Command (op_code = ENHANCED_FLUSH) {
  packet_type : FlushablePacketType,
  packet_type : FlushablePacketType,
}
}


test EnhancedFlush {
  "\x5f\x0c\x03\x02\x00\x00",
}

packet EnhancedFlushStatus : CommandStatus (command_op_code = ENHANCED_FLUSH) {
packet EnhancedFlushStatus : CommandStatus (command_op_code = ENHANCED_FLUSH) {
}
}


@@ -5452,6 +5464,10 @@ packet EnhancedFlushComplete : Event (event_code = ENHANCED_FLUSH_COMPLETE) {
  _reserved_ : 4,
  _reserved_ : 4,
}
}


test EnhancedFlushComplete {
  "\x39\x02\x02\x00",
}

packet UserPasskeyNotification : Event (event_code = USER_PASSKEY_NOTIFICATION) {
packet UserPasskeyNotification : Event (event_code = USER_PASSKEY_NOTIFICATION) {
  bd_addr : Address,
  bd_addr : Address,
  passkey : 20, // 0x00000-0xF423F (000000 - 999999)
  passkey : 20, // 0x00000-0xF423F (000000 - 999999)
+315 −2
Original line number Original line Diff line number Diff line
@@ -126,6 +126,10 @@ DualModeController::DualModeController(const std::string& properties_filename,
  SET_SUPPORTED(SETUP_SYNCHRONOUS_CONNECTION, SetupSynchronousConnection);
  SET_SUPPORTED(SETUP_SYNCHRONOUS_CONNECTION, SetupSynchronousConnection);
  SET_SUPPORTED(ACCEPT_SYNCHRONOUS_CONNECTION, AcceptSynchronousConnection);
  SET_SUPPORTED(ACCEPT_SYNCHRONOUS_CONNECTION, AcceptSynchronousConnection);
  SET_SUPPORTED(REJECT_SYNCHRONOUS_CONNECTION, RejectSynchronousConnection);
  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(IO_CAPABILITY_REQUEST_REPLY, IoCapabilityRequestReply);
  SET_SUPPORTED(USER_CONFIRMATION_REQUEST_REPLY, UserConfirmationRequestReply);
  SET_SUPPORTED(USER_CONFIRMATION_REQUEST_REPLY, UserConfirmationRequestReply);
  SET_SUPPORTED(USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY,
  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,
  SET_SUPPORTED(READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL,
                ReadInquiryResponseTransmitPowerLevel);
                ReadInquiryResponseTransmitPowerLevel);
  SET_SUPPORTED(SEND_KEYPRESS_NOTIFICATION, SendKeypressNotification);
  SET_SUPPORTED(SEND_KEYPRESS_NOTIFICATION, SendKeypressNotification);
  SET_SUPPORTED(ENHANCED_FLUSH, EnhancedFlush);
  SET_HANDLER(SET_EVENT_MASK_PAGE_2, SetEventMaskPage2);
  SET_HANDLER(SET_EVENT_MASK_PAGE_2, SetEventMaskPage2);
  SET_SUPPORTED(READ_LOCAL_OOB_DATA, ReadLocalOobData);
  SET_SUPPORTED(READ_LOCAL_OOB_DATA, ReadLocalOobData);
  SET_SUPPORTED(READ_LOCAL_OOB_EXTENDED_DATA, ReadLocalOobExtendedData);
  SET_SUPPORTED(READ_LOCAL_OOB_EXTENDED_DATA, ReadLocalOobExtendedData);
@@ -684,7 +689,8 @@ void DualModeController::SetupSynchronousConnection(CommandView command) {
  auto status = link_layer_controller_.SetupSynchronousConnection(
  auto status = link_layer_controller_.SetupSynchronousConnection(
      command_view.GetConnectionHandle(), command_view.GetTransmitBandwidth(),
      command_view.GetConnectionHandle(), command_view.GetTransmitBandwidth(),
      command_view.GetReceiveBandwidth(), command_view.GetMaxLatency(),
      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());
      command_view.GetPacketType());


  send_event_(bluetooth::hci::SetupSynchronousConnectionStatusBuilder::Create(
  send_event_(bluetooth::hci::SetupSynchronousConnectionStatusBuilder::Create(
@@ -700,13 +706,304 @@ void DualModeController::AcceptSynchronousConnection(CommandView command) {
  auto status = link_layer_controller_.AcceptSynchronousConnection(
  auto status = link_layer_controller_.AcceptSynchronousConnection(
      command_view.GetBdAddr(), command_view.GetTransmitBandwidth(),
      command_view.GetBdAddr(), command_view.GetTransmitBandwidth(),
      command_view.GetReceiveBandwidth(), command_view.GetMaxLatency(),
      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());
      command_view.GetPacketType());


  send_event_(bluetooth::hci::AcceptSynchronousConnectionStatusBuilder::Create(
  send_event_(bluetooth::hci::AcceptSynchronousConnectionStatusBuilder::Create(
      status, kNumCommandPackets));
      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) {
void DualModeController::RejectSynchronousConnection(CommandView command) {
  auto command_view = gd_hci::RejectSynchronousConnectionView::Create(
  auto command_view = gd_hci::RejectSynchronousConnectionView::Create(
      gd_hci::ScoConnectionCommandView::Create(
      gd_hci::ScoConnectionCommandView::Create(
@@ -959,6 +1256,22 @@ void DualModeController::SendKeypressNotification(CommandView command) {
#endif /* ROOTCANAL_LMP */
#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) {
void DualModeController::SetEventMaskPage2(CommandView command) {
  auto payload =
  auto payload =
      std::make_unique<bluetooth::packet::RawBuilder>(std::vector<uint8_t>(
      std::make_unique<bluetooth::packet::RawBuilder>(std::vector<uint8_t>(
+9 −0
Original line number Original line Diff line number Diff line
@@ -222,6 +222,12 @@ class DualModeController : public Device {
  // 7.1.36
  // 7.1.36
  void IoCapabilityRequestNegativeReply(CommandView args);
  void IoCapabilityRequestNegativeReply(CommandView args);


  // 7.1.45
  void EnhancedSetupSynchronousConnection(CommandView args);

  // 7.1.46
  void EnhancedAcceptSynchronousConnection(CommandView args);

  // 7.1.53
  // 7.1.53
  void RemoteOobExtendedDataRequestReply(CommandView args);
  void RemoteOobExtendedDataRequestReply(CommandView args);


@@ -372,6 +378,9 @@ class DualModeController : public Device {
  // 7.3.63
  // 7.3.63
  void SendKeypressNotification(CommandView args);
  void SendKeypressNotification(CommandView args);


  // 7.3.66
  void EnhancedFlush(CommandView args);

  // 7.3.69
  // 7.3.69
  void SetEventMaskPage2(CommandView args);
  void SetEventMaskPage2(CommandView args);