// 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/cable.h"

#include <string>

#include <base/files/file_enumerator.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <re2/re2.h>

#include "typecd/pd_vdo_constants.h"

namespace {

constexpr char kSOPPrimeAltModeRegex[] = R"(port(\d+)-plug0.(\d+))";

}  // namespace

namespace typecd {

void Cable::RegisterCablePlug(const base::FilePath& syspath) {
  // Search for all alt modes which were already registered prior to daemon
  // init.
  base::FileEnumerator iter(syspath, false, base::FileEnumerator::DIRECTORIES);
  for (auto path = iter.Next(); !path.empty(); path = iter.Next())
    AddAltMode(path);

  if (GetNumAltModes() != -1)
    return;

  auto num_altmodes_path = syspath.Append("number_of_alternate_modes");

  std::string val_str;
  if (!base::ReadFileToString(num_altmodes_path, &val_str)) {
    LOG(WARNING) << "Number of alternate modes not available for syspath "
                 << syspath;
    return;
  }

  base::TrimWhitespaceASCII(val_str, base::TRIM_TRAILING, &val_str);

  int num_altmodes;
  if (!base::StringToInt(val_str, &num_altmodes)) {
    LOG(ERROR) << "Couldn't parse num_altmodes from string: " << val_str;
    return;
  }

  SetNumAltModes(num_altmodes);
}

bool Cable::AddAltMode(const base::FilePath& mode_syspath) {
  int port, index;
  if (!RE2::FullMatch(mode_syspath.BaseName().value(), kSOPPrimeAltModeRegex,
                      &port, &index))
    return false;

  if (IsAltModePresent(index)) {
    LOG(INFO) << "Alt mode already registered for syspath "
              << mode_syspath.BaseName();
    return true;
  }

  auto alt_mode = AltMode::CreateAltMode(mode_syspath);
  if (!alt_mode) {
    LOG(ERROR) << "Error creating alt mode for syspath " << mode_syspath;
    return false;
  }

  alt_modes_.emplace(index, std::move(alt_mode));
  LOG(INFO) << "Added SOP' alt mode for port " << port << " index " << index;

  return true;
}

void Cable::RemoveAltMode(const base::FilePath& mode_syspath) {
  int port, index;
  if (!RE2::FullMatch(mode_syspath.BaseName().value(), kSOPPrimeAltModeRegex,
                      &port, &index)) {
    LOG(ERROR) << "Couldn't parse alt mode index from syspath " << mode_syspath;
    return;
  }

  auto it = alt_modes_.find(index);
  if (it == alt_modes_.end()) {
    LOG(INFO) << "Trying to delete non-existent SOP' alt mode " << index;
    return;
  }

  alt_modes_.erase(it);

  LOG(INFO) << "Removed SOP' alt mode for port " << port << " index " << index;
}

bool Cable::IsAltModePresent(int index) {
  auto it = alt_modes_.find(index);
  if (it != alt_modes_.end()) {
    return true;
  }

  LOG(INFO) << "SOP' Alt mode not found at index " << index;
  return false;
}

bool Cable::IsAltModeSVIDPresent(uint16_t altmode_sid) {
  for (const auto& [index, mode] : alt_modes_) {
    if (mode->GetSVID() == altmode_sid)
      return true;
  }

  return false;
}

AltMode* Cable::GetAltMode(int index) {
  if (!IsAltModePresent(index))
    return nullptr;

  return alt_modes_.find(index)->second.get();
}

// Ref:
//   USB Type-C Connector Spec, release 2.0
//   Figure F-1.
bool Cable::TBT3PDIdentityCheck() {
  // If the cable is active, we don't need to check for speed.
  auto product_type = GetIdHeaderVDO() >> kIDHeaderVDOProductTypeBitOffset &
                      kIDHeaderVDOProductTypeMask;
  if (product_type & kIDHeaderVDOProductTypeCableActive) {
    if (IsAltModeSVIDPresent(kTBTAltModeVID)) {
      LOG(INFO) << "Active cable detected, TBT3 supported.";
      return true;
    }
    LOG(INFO) << "Active cable detected, TBT3 not supported.";
    return false;
  }

  if (!(product_type & kIDHeaderVDOProductTypeCablePassive)) {
    LOG(ERROR) << "Cable has unsupported product type.";
    return false;
  }

  auto usb_speed = GetProductTypeVDO1() & kUSBSpeedBitMask;
  if (GetPDRevision() == PDRevision::k30) {
    return usb_speed == kUSBSuperSpeed32Gen1 ||
           usb_speed == kUSBSuperSpeed32Or40Gen2 ||
           usb_speed == kUSB40SuperSpeedGen3;
  }

  // For PD 2.0 the check is similar, but let's make it explicit.
  return usb_speed == kUSBSuperSpeed31Gen1 || usb_speed == kUSBSuperSpeed31Gen2;
}

bool Cable::DiscoveryComplete() {
  return num_alt_modes_ == alt_modes_.size();
}

CableSpeedMetric Cable::GetCableSpeedMetric() {
  CableSpeedMetric ret = CableSpeedMetric::kOther;

  // If we can't identify a valid cable in the ID Header, return early.
  auto cable_type = (GetIdHeaderVDO() >> kIDHeaderVDOProductTypeBitOffset) &
                    kIDHeaderVDOProductTypeMask;
  if (!(cable_type == kIDHeaderVDOProductTypeCableActive ||
        cable_type == kIDHeaderVDOProductTypeCablePassive))
    return ret;

  // Parse the speed field in the Cable VDO.
  auto cable_vdo = GetProductTypeVDO1();
  uint32_t speed = cable_vdo & kUSBSpeedBitMask;
  switch (speed) {
    case kUSBSpeed20:
      ret = CableSpeedMetric::kUSB2_0;
      break;
    case kUSBSuperSpeed32Gen1:
      ret = CableSpeedMetric::kUSB3_2Gen1;
      break;
    case kUSBSuperSpeed32Or40Gen2:
      ret = CableSpeedMetric::kUSB3_2USB4Gen2;
      break;
    case kUSB40SuperSpeedGen3:
      ret = CableSpeedMetric::kUSB4Gen3;
      break;
  }

  // Add special handling for the PD 2.0 Cable VDO speed.
  if (GetPDRevision() == PDRevision::k20) {
    if (speed == kUSBSuperSpeed31Gen1) {
      ret = CableSpeedMetric::kUSB3_1Gen1;
    } else if (speed == kUSBSuperSpeed31Gen2) {
      ret = CableSpeedMetric::kUSB3_1Gen1Gen2;
    }
  }

  if (ret != CableSpeedMetric::kUSB2_0)
    return ret;

  // Finally, handle TBT-only cables (only if the VDOs claim to only
  // support USB 2.0 speeds).
  for (const auto& [index, mode] : alt_modes_) {
    if (mode->GetSVID() != kTBTAltModeVID)
      continue;

    uint32_t tbt_vdo = mode->GetVDO();

    // If rounded support is there, we should continue.
    auto rounded_support =
        (tbt_vdo >> kTBT3CableDiscModeVDORoundedSupportOffset) &
        kTBT3CableDiscModeVDORoundedSupportMask;
    if (rounded_support == kTBT3CableDiscModeVDO_3_4_Gen_Rounded_Non_Rounded)
      continue;

    auto speed = (tbt_vdo >> kTBT3CableDiscModeVDOSpeedOffset) &
                 kTBT3CableDiscModeVDOSpeedMask;
    if (speed == kTBT3CableDiscModeVDOSpeed10G20G)
      ret = CableSpeedMetric::kTBTOnly10G20G;
  }

  return ret;
}

void Cable::ReportMetrics(Metrics* metrics) {
  if (!metrics || metrics_reported_)
    return;

  metrics->ReportCableSpeed(GetCableSpeedMetric());

  metrics_reported_ = true;
}

}  // namespace typecd
