// Copyright 2022 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/usb_monitor.h"

#include <utility>

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

namespace {
constexpr char kInterfaceFilePathRegex[] =
    R"((\d+)-(\d+)(\.(\d+))*:(\d+)\.(\d+))";
constexpr char kTypecPortUeventRegex[] = R"(TYPEC_PORT=port(\d+))";

typecd::UsbSpeed ConvertToUsbSpeed(std::string speed) {
  if (speed == "1.5")
    return typecd::UsbSpeed::k1_5;
  else if (speed == "12")
    return typecd::UsbSpeed::k12;
  else if (speed == "480")
    return typecd::UsbSpeed::k480;
  else if (speed == "5000")
    return typecd::UsbSpeed::k5000;
  else if (speed == "10000")
    return typecd::UsbSpeed::k10000;
  else if (speed == "20000")
    return typecd::UsbSpeed::k20000;
  else
    return typecd::UsbSpeed::kOther;
}

typecd::UsbDeviceClass ConvertToUsbClass(std::string device_class) {
  if (device_class == "00")
    return typecd::UsbDeviceClass::kNone;
  else if (device_class == "09")
    return typecd::UsbDeviceClass::kHub;
  else
    return typecd::UsbDeviceClass::kOther;
}

// Convert version string parsed from USB device sysfs to UsbVersion enum to
// store in UsbDevice.
typecd::UsbVersion ConvertToUsbVersion(std::string version) {
  if (version == "1.00")
    return typecd::UsbVersion::k1_0;
  else if (version == "1.10")
    return typecd::UsbVersion::k1_1;
  else if (version == "2.00")
    return typecd::UsbVersion::k2_0;
  else if (version == "2.10")
    return typecd::UsbVersion::k2_1;
  else if (version == "3.00")
    return typecd::UsbVersion::k3_0;
  else if (version == "3.10")
    return typecd::UsbVersion::k3_1;
  else if (version == "3.20")
    return typecd::UsbVersion::k3_2;
  else
    return typecd::UsbVersion::kOther;
}

}  // namespace

namespace typecd {

UsbMonitor::UsbMonitor() : metrics_(nullptr) {}

void UsbMonitor::OnDeviceAddedOrRemoved(const base::FilePath& path,
                                        bool added) {
  auto key = path.BaseName().value();
  if (RE2::FullMatch(key, kInterfaceFilePathRegex)) {
    return;
  }

  auto it = devices_.find(key);
  if (added) {
    if (it != devices_.end()) {
      LOG(WARNING) << "Attempting to add an already added usb device in "
                   << path;
      return;
    }

    std::string busnum;
    std::string devnum;
    if (!base::ReadFileToString(path.Append("busnum"), &busnum)) {
      PLOG(ERROR) << "Failed to find busnum in " << path;
      return;
    }
    if (!base::ReadFileToString(path.Append("devnum"), &devnum)) {
      PLOG(ERROR) << "Failed to find devnum in " << path;
      return;
    }
    base::TrimWhitespaceASCII(busnum, base::TRIM_TRAILING, &busnum);
    base::TrimWhitespaceASCII(devnum, base::TRIM_TRAILING, &devnum);

    int busnum_int;
    int devnum_int;
    if (!base::StringToInt(busnum, &busnum_int) ||
        !base::StringToInt(devnum, &devnum_int)) {
      PLOG(ERROR) << "Failed to parse integer value from busnum and devnum in "
                  << path;
      return;
    }
    devices_.emplace(key,
                     std::make_unique<UsbDevice>(busnum_int, devnum_int, key));

    std::string typec_port_uevent;
    int typec_port_num;
    if (base::ReadFileToString(path.Append("port/connector/uevent"),
                               &typec_port_uevent) &&
        RE2::PartialMatch(typec_port_uevent, kTypecPortUeventRegex,
                          &typec_port_num)) {
      GetDevice(key)->SetTypecPortNum(typec_port_num);
    } else {
      // Parent USB hub device's sysfs directory name.
      // e.g. Parent sysfs of 2-1.5.4 would be 2-1
      auto parent_key = key.substr(0, key.find("."));

      // If parent USB hub device is present and has a Type C port associated,
      // use the parent's Type C port number.
      if (GetDevice(parent_key) != nullptr)
        GetDevice(key)->SetTypecPortNum(
            GetDevice(parent_key)->GetTypecPortNum());
    }

    std::string speed;
    if (base::ReadFileToString(path.Append("speed"), &speed)) {
      base::TrimWhitespaceASCII(speed, base::TRIM_TRAILING, &speed);
      GetDevice(key)->SetSpeed(ConvertToUsbSpeed(speed));
    }

    std::string device_class;
    if (base::ReadFileToString(path.Append("bDeviceClass"), &device_class)) {
      base::TrimWhitespaceASCII(device_class, base::TRIM_TRAILING,
                                &device_class);
      GetDevice(key)->SetDeviceClass(ConvertToUsbClass(device_class));
    }

    std::string version;
    if (base::ReadFileToString(path.Append("version"), &version)) {
      base::TrimWhitespaceASCII(version, base::TRIM_ALL, &version);
      GetDevice(key)->SetVersion(ConvertToUsbVersion(version));
    }

    ReportMetrics(path, key);

  } else {
    if (it == devices_.end()) {
      LOG(WARNING) << "Attempting to remove a non-existent usb device in "
                   << path;
      return;
    }

    devices_.erase(key);
  }
}

UsbDevice* UsbMonitor::GetDevice(std::string key) {
  auto it = devices_.find(key);
  if (it == devices_.end())
    return nullptr;

  return it->second.get();
}

void UsbMonitor::ReportMetrics(const base::FilePath& path, std::string key) {
  if (!metrics_)
    return;

  UsbDevice* device = GetDevice(key);
  if (!device) {
    LOG(WARNING)
        << "Metrics reporting attempted for non-existent usb device in "
        << path;
    return;
  }

  device->ReportMetrics(metrics_);
}

}  // namespace typecd
