Add methods to trigger action on LED
Implements the ON, OFF and BLINK operations on a given LED.
Change-Id: I74b5ac01d8e76961999a2673d52d73296f5603d7
Signed-off-by: Vishwanatha Subbanna <vishwa@linux.vnet.ibm.com>
diff --git a/physical.cpp b/physical.cpp
index 31fc1ee..38c69b0 100644
--- a/physical.cpp
+++ b/physical.cpp
@@ -25,32 +25,129 @@
/** @brief Populates key parameters */
void Physical::setInitialState()
{
+ // Control files in /sys/class/leds/<led-name>
+ brightCtrl = path + BRIGHTNESS;
+ blinkCtrl = path + BLINKCTRL;
+
+ delayOnCtrl = path + DELAYON;
+ delayOffCtrl = path + DELAYOFF;
+
// 1. read /sys/class/leds/name/trigger
// 2. If its 'timer', then its blinking.
// 2.1: On blink, use delay_on and delay_off into dutyOn
// 3. If its 'none', then read brightness. 255 means, its ON, else OFF.
- // Implementation in the next patchset.
+
+ auto trigger = read<std::string>(blinkCtrl);
+ if (trigger == "timer")
+ {
+ // LED is blinking. Get the delay_on and delay_off and compute
+ // DutyCycle. sfsfs values are in strings. Need to convert 'em over to
+ // integer.
+ auto delayOn = std::stoi(read<std::string>(delayOnCtrl));
+ auto delayOff = std::stoi(read<std::string>(delayOffCtrl));
+
+ // Calculate frequency and then percentage ON
+ frequency = delayOn + delayOff;
+ auto factor = frequency / 100;
+ auto dutyOn = delayOn / factor;
+
+ // Update.
+ this->dutyOn(dutyOn);
+ }
+ else
+ {
+ // This is hardcoded for now. This will be changed to this->frequency()
+ // when frequency is implemented.
+ // TODO
+ frequency = 1000;
+
+ // LED is either ON or OFF
+ auto brightness = read<std::string>(brightCtrl);
+ if (brightness == std::string(ASSERT))
+ {
+ // LED is in Solid ON
+ sdbusplus::xyz::openbmc_project::Led::server
+ ::Physical::state(Action::On);
+ }
+ else
+ {
+ // LED is in OFF state
+ sdbusplus::xyz::openbmc_project::Led::server
+ ::Physical::state(Action::Off);
+ }
+ }
+ return;
}
/** @brief Overloaded State Property Setter function */
auto Physical::state(Action value) -> Action
{
- // Set the base class's state to actuals since the getter
- // operation is handled there.
- auto action = sdbusplus::xyz::openbmc_project::Led::server
+ // Obtain current operation
+ auto current = sdbusplus::xyz::openbmc_project::Led::server
+ ::Physical::state();
+
+ // Update requested operation into base class
+ auto requested = sdbusplus::xyz::openbmc_project::Led::server
::Physical::state(value);
// Apply the action.
- driveLED();
+ driveLED(current, requested);
- return action;
+ return value;
}
/** @brief apply action on the LED */
-void Physical::driveLED()
+void Physical::driveLED(Action current, Action request)
{
- // Replace with actual code.
- std::cout << " Drive LED STUB :: \n";
+ if (current == request)
+ {
+ // Best we can do here is ignore.
+ return;
+ }
+
+ // Transition TO Blinking state
+ if (request == Action::Blink)
+ {
+ return blinkOperation();
+ }
+
+ // Transition TO Stable states.
+ if(request == Action::On || request == Action::Off)
+ {
+ return stableStateOperation(request);
+ }
+ return;
+}
+
+/** @brief Either TurnON -or- TurnOFF */
+void Physical::stableStateOperation(Action action)
+{
+ auto value = (action == Action::On) ? ASSERT : DEASSERT;
+
+ // Write "none" to trigger to clear any previous action
+ write(blinkCtrl, "none");
+
+ // And write the current command
+ write(brightCtrl, value);
+ return;
+}
+
+/** @brief BLINK the LED */
+void Physical::blinkOperation()
+{
+ // Get the latest dutyOn that the user requested
+ auto dutyOn = this->dutyOn();
+
+ // Write "timer" to "trigger" file
+ write(blinkCtrl, "timer");
+
+ // Write DutyON. Value in percentage 1_millisecond.
+ // so 50% input becomes 500. Driver wants string input
+ auto percentage = frequency / 100;
+ write(delayOnCtrl, std::to_string(dutyOn * percentage));
+
+ // Write DutyOFF. Value in milli seconds so 50% input becomes 500.
+ write(delayOffCtrl, std::to_string((100 - dutyOn) * percentage));
return;
}