blob: a11becf3a3accf6c3d19f6061fb5870cbfa23bf4 [file]
#include "tlbmc/hal/led/led_sysfs.h"
#include <cstdint>
#include <memory>
#include <string>
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "g3/macros.h"
#include "led_config.pb.h"
#include "tlbmc/hal/sysfs/led.h"
namespace milotic_tlbmc {
absl::Status SysfsLed::SetBehaviorImpl(const LedBehavior& behavior) {
switch (behavior.state()) {
case LED_STATE_OFF:
ECCLESIA_RETURN_IF_ERROR(led_sysfs_.SetTrigger(sysfs_name_, "none"));
return led_sysfs_.SetBrightness(sysfs_name_, 0);
case LED_STATE_ON: {
ECCLESIA_RETURN_IF_ERROR(led_sysfs_.SetTrigger(sysfs_name_, "none"));
return led_sysfs_.SetBrightness(sysfs_name_, max_brightness_);
}
case LED_STATE_BLINK: {
// The kernel "timer" trigger blinks the LED in hardware using the
// delay_on / delay_off attributes.
ECCLESIA_RETURN_IF_ERROR(led_sysfs_.SetTrigger(sysfs_name_, "timer"));
ECCLESIA_RETURN_IF_ERROR(led_sysfs_.SetDelayOn(
sysfs_name_, behavior.blink_config().duty_on_ms()));
return led_sysfs_.SetDelayOff(sysfs_name_,
behavior.blink_config().duty_off_ms());
}
default:
return absl::InvalidArgumentError("Unknown LED state");
}
}
absl::StatusOr<LedBehavior> SysfsLed::GetBehaviorImpl() const {
ECCLESIA_ASSIGN_OR_RETURN(std::string trigger,
led_sysfs_.GetTrigger(sysfs_name_));
if (trigger == "timer") {
ECCLESIA_ASSIGN_OR_RETURN(uint32_t delay_on,
led_sysfs_.GetDelayOn(sysfs_name_));
ECCLESIA_ASSIGN_OR_RETURN(uint32_t delay_off,
led_sysfs_.GetDelayOff(sysfs_name_));
LedBehavior behavior;
behavior.set_state(LED_STATE_BLINK);
behavior.mutable_blink_config()->set_duty_on_ms(delay_on);
behavior.mutable_blink_config()->set_duty_off_ms(delay_off);
return behavior;
}
ECCLESIA_ASSIGN_OR_RETURN(uint32_t brightness,
led_sysfs_.GetBrightness(sysfs_name_));
LedBehavior behavior;
behavior.set_state(brightness > 0 ? LED_STATE_ON : LED_STATE_OFF);
return behavior;
}
absl::StatusOr<std::unique_ptr<SysfsLed>> SysfsLed::Create(
const LedConfig& config, const LedSysfs& led_sysfs) {
if (config.name().empty()) {
return absl::InvalidArgumentError("LedConfig name must not be empty");
}
if (!config.has_output()) {
return absl::InvalidArgumentError("LedConfig output must be set");
}
if (!config.output().has_sysfs_name() ||
config.output().sysfs_name().empty()) {
return absl::InvalidArgumentError("Sysfs LED name must not be empty");
}
if (!led_sysfs.IsLedPresent(config.output().sysfs_name())) {
return absl::InvalidArgumentError(
absl::StrCat("Sysfs LED ", config.output().sysfs_name(), " not found"));
}
ECCLESIA_ASSIGN_OR_RETURN(
uint32_t max_brightness,
led_sysfs.GetMaxBrightness(config.output().sysfs_name()));
return absl::WrapUnique(new SysfsLed(config, led_sysfs, max_brightness));
}
} // namespace milotic_tlbmc