blob: e679d4d0071374d46ae2880ce72993706bd7621e [file] [log] [blame]
// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "power_manager/powerd/system/wake_on_dp_configurator.h"
#include <fcntl.h>
#include <base/check.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <libec/get_mkbp_wake_mask_command.h>
#include <libec/set_mkbp_wake_mask_command.h>
namespace power_manager::system {
namespace {
bool GetMkbpWakeMask(const base::ScopedFD& cros_ec_fd,
uint32_t* wake_mask_out) {
DCHECK(cros_ec_fd.is_valid());
DCHECK(wake_mask_out);
if (cros_ec_fd.get() < 0)
return false;
// TODO(b/265492733): Move to EcCommandFactory to allow mocking for unittests.
ec::GetMkbpWakeMaskEventCommand cmd;
if (!cmd.Run(cros_ec_fd.get())) {
LOG(ERROR) << "Failed to get current MKBP wake mask. Result : "
<< cmd.Result();
return false;
}
*wake_mask_out = cmd.GetWakeMask();
return true;
}
bool SetMkbpWakeMask(const base::ScopedFD& cros_ec_fd, uint32_t wake_mask) {
DCHECK(cros_ec_fd.is_valid());
if (cros_ec_fd.get() < 0)
return false;
// TODO(b/265492733): Move to EcCommandFactory to allow mocking for unittests.
ec::SetMkbpWakeMaskEventCommand cmd(wake_mask);
if (!cmd.Run(cros_ec_fd.get())) {
LOG(ERROR) << "Failed to set new MKBP wake mask to '0x" << std::hex
<< wake_mask << "' Result: " << std::dec << cmd.Result();
return false;
}
return true;
}
} // namespace
void ConfigureWakeOnDp(bool enable) {
uint32_t wake_mask;
base::ScopedFD cros_ec_fd = base::ScopedFD(open(ec::kCrosEcPath, O_RDWR));
if (!cros_ec_fd.is_valid()) {
PLOG(ERROR) << "Failed to open " << ec::kCrosEcPath;
return;
}
if (!GetMkbpWakeMask(cros_ec_fd, &wake_mask))
return;
if (enable)
wake_mask |= (1 << EC_MKBP_EVENT_DP_ALT_MODE_ENTERED);
else
wake_mask &= ~(1 << EC_MKBP_EVENT_DP_ALT_MODE_ENTERED);
if (SetMkbpWakeMask(cros_ec_fd, wake_mask))
LOG(INFO) << "Wake on dp is " << (enable ? "enabled" : "disabled");
}
} // namespace power_manager::system