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

Commit 12f51315 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

L2CAP: Save remote supported features in link

Save extended_features_supported. Don't send ERTM in initial config
request if remote doesn't support.

Test: run_cert.sh
Bug: 144770885
Change-Id: I17ee89855b0a05bd3265295f909b28787da355e9
parent a9b1a8b6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -209,7 +209,7 @@ class L2capModuleCertService : public L2capModuleCert::Service {
    switch (request->type()) {
      case InformationRequestType::CONNECTIONLESS_MTU: {
        auto builder = InformationResponseConnectionlessMtuBuilder::Create(request->signal_id(),
                                                                           InformationRequestResult::NOT_SUPPORTED, 0);
                                                                           InformationRequestResult::SUCCESS, 100);
        auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
        outgoing_packet_queue_.push(std::move(l2cap_builder));
        send_packet_from_queue();
@@ -217,7 +217,7 @@ class L2capModuleCertService : public L2capModuleCert::Service {
      }
      case InformationRequestType::EXTENDED_FEATURES: {
        auto builder = InformationResponseExtendedFeaturesBuilder::Create(
            request->signal_id(), InformationRequestResult::NOT_SUPPORTED, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
            request->signal_id(), InformationRequestResult::SUCCESS, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0);
        auto l2cap_builder = BasicFrameBuilder::Create(kClassicSignallingCid, std::move(builder));
        outgoing_packet_queue_.push(std::move(l2cap_builder));
        send_packet_from_queue();
+24 −0
Original line number Diff line number Diff line
@@ -157,6 +157,30 @@ void Link::NotifyChannelFail(Cid cid) {
  local_cid_to_pending_dynamic_channel_connection_map_.erase(cid);
}

void Link::SetRemoteConnectionlessMtu(Mtu mtu) {
  remote_mtu_ = mtu;
}

Mtu Link::GetRemoteConnectionlessMtu() const {
  return remote_mtu_;
}

void Link::SetRemoteSupportsErtm(bool supported) {
  remote_supports_ertm_ = supported;
}

bool Link::GetRemoteSupportsErtm() const {
  return remote_supports_ertm_;
}

void Link::SetRemoteSupportsFcs(bool supported) {
  remote_supports_fcs_ = supported;
}

bool Link::GetRemoteSupportsFcs() const {
  return remote_supports_fcs_;
}

}  // namespace internal
}  // namespace classic
}  // namespace l2cap
+11 −0
Original line number Diff line number Diff line
@@ -99,6 +99,14 @@ class Link {
  virtual void NotifyChannelCreation(Cid cid, std::unique_ptr<DynamicChannel> channel);
  virtual void NotifyChannelFail(Cid cid);

  // Information received from signalling channel
  virtual void SetRemoteConnectionlessMtu(Mtu mtu);
  virtual Mtu GetRemoteConnectionlessMtu() const;
  virtual void SetRemoteSupportsErtm(bool supported);
  virtual bool GetRemoteSupportsErtm() const;
  virtual void SetRemoteSupportsFcs(bool supported);
  virtual bool GetRemoteSupportsFcs() const;

 private:
  os::Handler* l2cap_handler_;
  l2cap::internal::FixedChannelAllocator<FixedChannelImpl, Link> fixed_channel_allocator_{this, l2cap_handler_};
@@ -112,6 +120,9 @@ class Link {
  ClassicSignallingManager signalling_manager_;
  std::unordered_map<Cid, PendingDynamicChannelConnection> local_cid_to_pending_dynamic_channel_connection_map_;
  os::Alarm link_idle_disconnect_alarm_{l2cap_handler_};
  Mtu remote_mtu_ = kMinimumClassicMtu;
  bool remote_supports_ertm_ = false;
  bool remote_supports_fcs_ = false;
  DISALLOW_COPY_AND_ASSIGN(Link);
};

+41 −2
Original line number Diff line number Diff line
@@ -149,6 +149,9 @@ void ClassicSignallingManager::OnConnectionRequest(SignalId signal_id, Psm psm,
                           ConnectionResponseStatus::NO_FURTHER_INFORMATION_AVAILABLE);
  auto* service = dynamic_service_manager_->GetService(psm);
  auto initial_config = service->GetConfigOption();
  if (!link_->GetRemoteSupportsErtm()) {
    initial_config.channel_mode = DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC;
  }
  auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
  mtu_configuration->mtu_ = initial_config.incoming_mtu;
  auto fcs_option = std::make_unique<FrameCheckSequenceOption>();
@@ -209,6 +212,9 @@ void ClassicSignallingManager::OnConnectionResponse(SignalId signal_id, Cid remo
  }
  alarm_.Cancel();
  auto initial_config = link_->GetConfigurationForInitialConfiguration(new_channel->GetCid());
  if (!link_->GetRemoteSupportsErtm()) {
    initial_config.channel_mode = DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode::L2CAP_BASIC;
  }
  auto mtu_configuration = std::make_unique<MtuConfigurationOption>();
  mtu_configuration->mtu_ = initial_config.incoming_mtu;
  auto retransmission_flow_control_configuration = std::make_unique<RetransmissionAndFlowControlConfigurationOption>();
@@ -407,7 +413,7 @@ void ClassicSignallingManager::OnInformationRequest(SignalId signal_id, Informat
  }
}

void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& view) {
void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const InformationResponseView& response) {
  if (pending_commands_.empty()) {
    LOG_WARN("Unexpected response: no pending request");
    return;
@@ -419,7 +425,40 @@ void ClassicSignallingManager::OnInformationResponse(SignalId signal_id, const I
      last_sent_command.command_code_ != CommandCode::INFORMATION_REQUEST) {
    return;
  }
  // TODO (hsz): Store the information response

  auto type = response.GetInfoType();
  switch (type) {
    case InformationRequestInfoType::CONNECTIONLESS_MTU: {
      auto view = InformationResponseConnectionlessMtuView::Create(response);
      if (!view.IsValid()) {
        LOG_WARN("Invalid InformationResponseConnectionlessMtu received");
        return;
      }
      link_->SetRemoteConnectionlessMtu(view.GetConnectionlessMtu());
      break;
    }
    case InformationRequestInfoType::EXTENDED_FEATURES_SUPPORTED: {
      auto view = InformationResponseExtendedFeaturesView::Create(response);
      if (!view.IsValid()) {
        LOG_WARN("Invalid InformationResponseExtendedFeatures received");
        return;
      }
      link_->SetRemoteSupportsErtm((view.GetEnhancedRetransmissionMode()));
      link_->SetRemoteSupportsFcs(view.GetFcsOption());
      // We don't care about other parameters
      break;
    }
    case InformationRequestInfoType::FIXED_CHANNELS_SUPPORTED: {
      auto view = InformationResponseFixedChannelsView::Create(response);
      if (!view.IsValid()) {
        LOG_WARN("Invalid InformationResponseFixedChannel received");
        return;
      }
      // We don't use fixed channels (connectionless or BR/EDR security) for now so we don't care
      break;
    }
  }

  alarm_.Cancel();
  handle_send_next_command();
}
+1 −1
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ class ClassicSignallingManager {

  void OnInformationRequest(SignalId signal_id, InformationRequestInfoType type);

  void OnInformationResponse(SignalId signal_id, const InformationResponseView& view);
  void OnInformationResponse(SignalId signal_id, const InformationResponseView& response);

 private:
  void on_incoming_packet();