// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "typecd/port_manager.h"

#include <string>

#include <base/threading/platform_thread.h>
#include <base/time/time.h>
#include <base/logging.h>
#include <dbus/typecd/dbus-constants.h>
#include <re2/re2.h>

namespace {

// Give enough time for the EC to complete the ExitMode command. Calculated as
// follows:
// (tVDMWaitModeExit (50ms) * 3 possible signalling types (SOP, SOP', SOP''))
// + 5 ms (typical ectool command)
//
// That gives us 155ms, so we double that to factor in scheduler and other
// delays.
constexpr uint32_t kExitModeWaitMs = 300;

// Helper function to print the TypeCMode.
std::string ModeToString(typecd::TypeCMode mode) {
  int val = static_cast<int>(mode);
  switch (val) {
    case 0:
      return "DP";
    case 1:
      return "TBT";
    case 2:
      return "USB4";
    default:
      return "none";
  }
}

}  // namespace

namespace typecd {

PortManager::PortManager()
    : mode_entry_supported_(true),
      notify_mgr_(nullptr),
      features_client_(nullptr),
      user_active_(false),
      peripheral_data_access_(true) {}

void PortManager::OnPortAddedOrRemoved(const base::FilePath& path,
                                       int port_num,
                                       bool added) {
  auto it = ports_.find(port_num);
  if (added) {
    if (it != ports_.end()) {
      LOG(WARNING) << "Attempting to add an already added port.";
      return;
    }

    ports_.emplace(port_num, std::make_unique<Port>(path, port_num));
  } else {
    if (it == ports_.end()) {
      LOG(WARNING) << "Attempting to remove a non-existent port.";
      return;
    }

    ports_.erase(it);
  }
}

void PortManager::OnPartnerAddedOrRemoved(const base::FilePath& path,
                                          int port_num,
                                          bool added) {
  auto it = ports_.find(port_num);
  if (it == ports_.end()) {
    LOG(WARNING) << "Partner add/remove attempted for non-existent port "
                 << port_num;
    return;
  }

  auto port = it->second.get();
  if (added) {
    port->AddPartner(path);
    RunModeEntry(port_num);
  } else {
    port->RemovePartner();
    port->SetCurrentMode(TypeCMode::kNone);
  }
}

void PortManager::OnPartnerAltModeAddedOrRemoved(const base::FilePath& path,
                                                 int port_num,
                                                 bool added) {
  auto it = ports_.find(port_num);
  if (it == ports_.end()) {
    LOG(WARNING)
        << "Partner alt mode add/remove attempted for non-existent port "
        << port_num;
    return;
  }

  auto port = it->second.get();
  port->AddRemovePartnerAltMode(path, added);
  if (added)
    RunModeEntry(port_num);
}

void PortManager::OnCableAddedOrRemoved(const base::FilePath& path,
                                        int port_num,
                                        bool added) {
  auto it = ports_.find(port_num);
  if (it == ports_.end()) {
    LOG(WARNING) << "Cable add/remove attempted for non-existent port "
                 << port_num;
    return;
  }

  auto port = it->second.get();
  if (added) {
    port->AddCable(path);
  } else {
    port->RemoveCable();
  }
}

void PortManager::OnCablePlugAdded(const base::FilePath& path, int port_num) {
  auto it = ports_.find(port_num);
  if (it == ports_.end()) {
    LOG(WARNING) << "Cable plug (SOP') add attempted for non-existent port "
                 << port_num;
    return;
  }

  auto port = it->second.get();
  port->AddCablePlug(path);
  RunModeEntry(port_num);
}

void PortManager::OnCableAltModeAdded(const base::FilePath& path,
                                      int port_num) {
  auto it = ports_.find(port_num);
  if (it == ports_.end()) {
    LOG(WARNING) << "Cable alt mode add attempted for non-existent port "
                 << port_num;
    return;
  }

  auto port = it->second.get();
  port->AddCableAltMode(path);
  RunModeEntry(port_num);
}

void PortManager::OnPartnerChanged(int port_num) {
  auto it = ports_.find(port_num);
  if (it == ports_.end()) {
    LOG(WARNING) << "Partner change detected for non-existent port "
                 << port_num;
    return;
  }

  auto port = it->second.get();
  port->PartnerChanged();
  RunModeEntry(port_num);
}

void PortManager::OnPortChanged(int port_num) {
  auto it = ports_.find(port_num);
  if (it == ports_.end()) {
    LOG(WARNING) << "Port change detected for non-existent port " << port_num;
    return;
  }

  auto port = it->second.get();
  port->PortChanged();
}

void PortManager::OnScreenIsLocked() {
  SetUserActive(false);
}

void PortManager::OnScreenIsUnlocked() {
  HandleUnlock();
}

void PortManager::OnSessionStarted() {
  // Session started is handled similarly to "screen unlocked".
  HandleUnlock();
}

void PortManager::OnSessionStopped() {
  HandleSessionStopped();
}

void PortManager::HandleSessionStopped() {
  if (!GetModeEntrySupported())
    return;

  SetUserActive(false);
  for (auto const& x : ports_) {
    Port* port = x.second.get();
    int port_num = x.first;

    // Since we've logged out, we can reset all expectations about active
    // state during mode entry.
    port->SetActiveStateOnModeEntry(GetUserActive());

    // If the current mode is anything other than kTBT, we don't care about
    // changing modes.
    if (port->GetCurrentMode() != TypeCMode::kTBT)
      continue;

    // If DP mode entry isn't supported, there is nothing left to do.
    if (!port->CanEnterDPAltMode())
      continue;

    // First try exiting the alt mode.
    if (ec_util_->ExitMode(port_num)) {
      port->SetCurrentMode(TypeCMode::kNone);
      LOG(INFO) << "Exited TBT mode on port " << port_num;
    } else {
      LOG(ERROR) << "Attempt to call ExitMode failed for port " << port_num;
      continue;
    }

    base::PlatformThread::Sleep(
        base::TimeDelta::FromMilliseconds(kExitModeWaitMs));

    // Now run mode entry again.
    RunModeEntry(port_num);
  }
}

void PortManager::HandleUnlock() {
  if (!GetModeEntrySupported())
    return;

  if (features_client_)
    SetPeripheralDataAccess(features_client_->IsPeripheralDataAccessEnabled());

  SetUserActive(true);
  for (auto const& x : ports_) {
    Port* port = x.second.get();
    int port_num = x.first;
    // If the current mode is anything other than DP, we don't care about
    // changing modes.
    if (port->GetCurrentMode() != TypeCMode::kDP)
      continue;

    // If TBT mode entry isn't supported, there is nothing left to do.
    if (port->CanEnterTBTCompatibilityMode() != ModeEntryResult::kSuccess)
      continue;

    // If peripheral data access is disabled, we shouldn't switch modes at all.
    if (!GetPeripheralDataAccess())
      continue;

    // If the port had initially entered the mode during an unlocked state,
    // we shouldn't change modes now. Doing so will abruptly kick storage
    // devices off the peripheral without a safe unmount.
    if (port->GetActiveStateOnModeEntry())
      continue;

    // First try exiting the alt mode.
    if (ec_util_->ExitMode(port_num)) {
      port->SetCurrentMode(TypeCMode::kNone);
      LOG(INFO) << "Exited DP mode on port " << port_num;
    } else {
      LOG(ERROR) << "Attempt to call ExitMode failed for port " << port_num;
      continue;
    }

    base::PlatformThread::Sleep(
        base::TimeDelta::FromMilliseconds(kExitModeWaitMs));

    // Now run mode entry again.
    RunModeEntry(port_num);
  }
}

void PortManager::ReportMetrics(int port_num) {
  if (!metrics_)
    return;

  auto it = ports_.find(port_num);
  if (it == ports_.end()) {
    LOG(WARNING) << "Metrics reporting attempted for non-existent port "
                 << port_num;
    return;
  }

  auto port = it->second.get();
  if (port->IsPartnerDiscoveryComplete()) {
    port->ReportPartnerMetrics(metrics_);
  }

  if (port->IsCableDiscoveryComplete()) {
    port->ReportCableMetrics(metrics_);
  }

  // The only Port metric we are reporting is cable misconfiguration; we only
  // need to report that if we're on a system supporting USB4/TBT.
  if (GetModeEntrySupported())
    port->ReportPortMetrics(metrics_);
}

void PortManager::RunModeEntry(int port_num) {
  // Since RunModeEntry() executes after any Type C change, we can just run the
  // metrics reporting before executing the mode entry logic.
  ReportMetrics(port_num);

  if (!ec_util_) {
    LOG(ERROR) << "No EC Util implementation registered, mode entry aborted.";
    return;
  }

  if (!GetModeEntrySupported())
    return;

  auto it = ports_.find(port_num);
  if (it == ports_.end()) {
    LOG(WARNING) << "Mode entry attempted for non-existent port " << port_num;
    return;
  }

  auto port = it->second.get();

  if (port->GetDataRole() != "host") {
    LOG(WARNING) << "Can't enter mode; data role is not DFP on port "
                 << port_num;
    return;
  }

  if (!port->IsPartnerDiscoveryComplete()) {
    LOG(INFO) << "Can't enter mode; partner discovery not complete for port "
              << port_num;
    return;
  }

  if (!port->IsCableDiscoveryComplete()) {
    LOG(INFO) << "Can't enter mode; cable discovery not complete for port "
              << port_num;
    return;
  }

  if (port->GetCurrentMode() != TypeCMode::kNone) {
    LOG(INFO) << "Mode entry already executed for port " << port_num
              << ", mode: " << ModeToString(port->GetCurrentMode());
    return;
  }

  // Send TBT device-connected notification.
  // While we can probably optimize this to avoid the repeat CanEnter* calls, we
  // handle the notification calls ahead, in order to prevent the logic from
  // becoming difficult to follow.
  if (notify_mgr_) {
    if (port->CanEnterTBTCompatibilityMode() == ModeEntryResult::kSuccess) {
      auto notif = port->CanEnterDPAltMode()
                       ? DeviceConnectedType::kThunderboltDp
                       : DeviceConnectedType::kThunderboltOnly;
      notify_mgr_->NotifyConnected(notif);
    }
  }

  port->SetActiveStateOnModeEntry(GetUserActive());

  if (features_client_)
    SetPeripheralDataAccess(features_client_->IsPeripheralDataAccessEnabled());

  // If the host supports USB4 and we can enter USB4 in this partner, do so.
  if (port->CanEnterUSB4() == ModeEntryResult::kSuccess) {
    if (ec_util_->EnterMode(port_num, TypeCMode::kUSB4)) {
      port->SetCurrentMode(TypeCMode::kUSB4);
      LOG(INFO) << "Entered USB4 mode on port " << port_num;
    } else {
      LOG(ERROR) << "Attempt to call Enter USB4 failed for port " << port_num;
    }

    return;
  }

  if (port->CanEnterTBTCompatibilityMode() == ModeEntryResult::kSuccess) {
    // Check if DP alt mode can be entered. If so:
    // - If the user is not active: enter DP.
    // - If the user is active: if peripheral data access is disabled, enter DP,
    //   else enter TBT.
    //
    // If DP alt mode cannot be entered, proceed to enter TBT in all cases.
    TypeCMode cur_mode = TypeCMode::kTBT;
    if (port->CanEnterDPAltMode() &&
        (!GetUserActive() || (GetUserActive() && !GetPeripheralDataAccess()))) {
      cur_mode = TypeCMode::kDP;
      LOG(INFO) << "Not entering TBT compat mode since user_active: "
                << GetUserActive()
                << ", peripheral data access: " << GetPeripheralDataAccess()
                << ", port " << port_num;
    }

    if (ec_util_->EnterMode(port_num, cur_mode)) {
      port->SetCurrentMode(cur_mode);
      LOG(INFO) << "Entered " << ModeToString(cur_mode) << " mode on port "
                << port_num;
    } else {
      LOG(ERROR) << "Attempt to call enter " << ModeToString(cur_mode)
                 << " failed for port " << port_num;
    }

    return;
  }

  if (port->CanEnterDPAltMode()) {
    if (ec_util_->EnterMode(port_num, TypeCMode::kDP)) {
      port->SetCurrentMode(TypeCMode::kDP);
      LOG(INFO) << "Entered DP mode on port " << port_num;
    } else {
      LOG(ERROR) << "Attempt to call Enter DP failed for port " << port_num;
    }

    return;
  }
}

}  // namespace typecd
