blob: d9e13a3eb616f7dce793ea40e90c3eb1c8bbd8ca [file] [log] [blame]
// 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 "runtime_probe/functions/tcpc.h"
#include <fcntl.h>
#include <memory>
#include <utility>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>
#include <base/values.h>
#include <libec/pd_chip_info_command.h>
namespace runtime_probe {
namespace {
// Times to retry the ec command if timeout.
const int kEcCmdNumAttempts = 10;
// The maximum port number of TCPC.
const uint8_t kMaxPortCount = 255;
uint32_t RunCommandRetry(const base::ScopedFD& ec_dev,
ec::PdChipInfoCommandV0* cmd) {
for (int i = 0; i < kEcCmdNumAttempts; ++i) {
// We expected the command runs successfully or returns invalid param error.
if (cmd->Run(ec_dev.get()) || cmd->Result() == EC_RES_INVALID_PARAM)
return cmd->Result();
}
LOG(ERROR) << "Failed to run ec command, error code: " << cmd->Result();
return cmd->Result();
}
} // namespace
std::unique_ptr<ec::PdChipInfoCommandV0> TcpcFunction::GetPdChipInfoCommandV0(
uint8_t port) const {
// Set |live| to 1 to read live chip values instead of hard-coded values.
return std::make_unique<ec::PdChipInfoCommandV0>(port, /*live=*/1);
}
base::ScopedFD TcpcFunction::GetEcDevice() const {
return base::ScopedFD(open(ec::kCrosEcPath, O_RDWR));
}
TcpcFunction::DataType TcpcFunction::EvalImpl() const {
DataType result{};
base::ScopedFD ec_dev = GetEcDevice();
for (uint8_t port = 0; port < kMaxPortCount; ++port) {
auto cmd = GetPdChipInfoCommandV0(port);
if (RunCommandRetry(ec_dev, cmd.get()) != EC_RES_SUCCESS)
break;
base::Value val{base::Value::Type::DICTIONARY};
val.SetStringKey("port", base::NumberToString(port));
val.SetStringKey("vendor_id", base::StringPrintf("0x%x", cmd->VendorId()));
val.SetStringKey("product_id",
base::StringPrintf("0x%x", cmd->ProductId()));
val.SetStringKey("device_id", base::StringPrintf("0x%x", cmd->DeviceId()));
result.push_back(std::move(val));
}
return result;
}
} // namespace runtime_probe