| #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 |