blob: bf507106bdf907b1ee3682ba411cec0eeaad8c79 [file] [log] [blame]
// Copyright 2019 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.
#ifndef POWER_MANAGER_POWERD_SYSTEM_CROS_EC_IOCTL_H_
#define POWER_MANAGER_POWERD_SYSTEM_CROS_EC_IOCTL_H_
#include <fcntl.h>
#include <sys/ioctl.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/strings/stringprintf.h>
#include <chromeos/ec/cros_ec_dev.h>
#include <chromeos/ec/ec_commands.h>
namespace power_manager {
namespace system {
namespace cros_ec_ioctl {
// Character device exposing the EC command interface.
constexpr char kCrosEcDevNodePath[] = "/dev/cros_ec";
// Empty request or response for the IoctlCommand template below.
struct EmptyParam {};
// Empty struct is one byte in C++, get the size we want instead.
template <typename T>
constexpr size_t realsizeof() {
return std::is_empty<T>::value ? 0 : sizeof(T);
}
// Helper to build and send the command structures for cros_ec.
template <typename Request, typename Response>
class IoctlCommand {
public:
explicit IoctlCommand(uint32_t cmd, uint32_t ver = 0, const Request& req = {})
: data_({
{ver, cmd, realsizeof<Request>(), realsizeof<Response>(), 0xff},
{req},
}) {}
IoctlCommand(const IoctlCommand&) = delete;
IoctlCommand& operator=(const IoctlCommand&) = delete;
virtual ~IoctlCommand() = default;
void SetReq(const Request& req) { data_.req = req; }
// Runs an EC command.
// @param ec_fd file descriptor for the EC device.
// @return true if command runs successfully and response size is same as
// expected, false otherwise.
bool Run(int ec_fd) {
data_.cmd.result = 0xff;
int ret = ioctl(ec_fd, CROS_EC_DEV_IOCXCMD_V2, &data_);
if (ret >= 0) {
VLOG(1) << base::StringPrintf("CROS EC ioctl command 0x%x succeeded",
data_.cmd.command);
return static_cast<uint32_t>(ret) == data_.cmd.insize;
}
PLOG(ERROR) << base::StringPrintf("CROS EC ioctl command 0x%x failed",
data_.cmd.command);
return false;
}
Response* Resp() { return &data_.resp; }
Request* Req() { return &data_.req; }
uint16_t Result() { return data_.cmd.result; }
struct Data {
struct cros_ec_command_v2 cmd;
union {
Request req;
Response resp;
};
};
private:
virtual int ioctl(int fd, uint32_t request, Data* data) {
return ::ioctl(fd, request, data);
}
Data data_;
};
} // namespace cros_ec_ioctl
} // namespace system
} // namespace power_manager
#endif // POWER_MANAGER_POWERD_SYSTEM_CROS_EC_IOCTL_H_