summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--argument.cpp3
-rw-r--r--physical.cpp115
-rw-r--r--physical.hpp118
3 files changed, 222 insertions, 14 deletions
diff --git a/argument.cpp b/argument.cpp
index 7b70fe0..b70a0dd 100644
--- a/argument.cpp
+++ b/argument.cpp
@@ -73,7 +73,8 @@ void ArgumentParser::usage(char** argv)
std::cerr << "Usage: " << argv[0] << " [options]" << std::endl;
std::cerr << "Options:" << std::endl;
std::cerr << " --help Print this menu" << std::endl;
- std::cerr << " --path=<path> sysfs path like /sys/class/leds"
+ std::cerr << " --path=<path> absolute path of LED in sysfs; like";
+ std::cerr << " /sys/class/leds/<name>"
<< std::endl;
}
} // namespace led
diff --git a/physical.cpp b/physical.cpp
index 31fc1ee..38c69b0 100644
--- a/physical.cpp
+++ b/physical.cpp
@@ -25,32 +25,129 @@ namespace led
/** @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;
}
diff --git a/physical.hpp b/physical.hpp
index 0eac97b..c24d3f2 100644
--- a/physical.hpp
+++ b/physical.hpp
@@ -1,6 +1,7 @@
#pragma once
#include <string>
+#include <fstream>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server/object.hpp>
#include "xyz/openbmc_project/Led/Physical/server.hpp"
@@ -8,6 +9,42 @@ namespace phosphor
{
namespace led
{
+/** @brief Acts as input and output file for the current LED power state.
+ * Write "0" to trigger a LED OFF operation.
+ * Write "255" to trigger a LED ON operation.
+ * To know the current power state of the LED, a read on this
+ * would give either 0 or 255 indicating if the LED is currently
+ * Off / On AT THAT moment.
+ * Example: /sys/class/leds/myled/brightness
+ */
+constexpr auto BRIGHTNESS = "/brightness";
+
+/** @brief Assert LED by writing 255 */
+constexpr auto ASSERT = "255";
+
+/** @brief De-assert by writing "0" */
+constexpr auto DEASSERT = "0";
+
+/** @brief Write "timer" to this file telling the driver that
+ * the intended operation is BLINK. When the value "timer" is written to
+ * the file, 2 more files get auto generated and are named "delay_on" and
+ * "delay_off"
+ * To move away from blinking, write "none"
+ * Example: /sys/class/leds/myled/trigger
+ */
+constexpr auto BLINKCTRL = "/trigger";
+
+/** @brief write number of milliseconds that the LED needs to be ON
+ * while blinking. Default is 500 by the driver.
+ * Example: /sys/class/leds/myled/delay_on
+ */
+constexpr auto DELAYON = "/delay_on";
+
+/** @brief Write number of milliseconds that the LED needs to be OFF
+ * while blinking. Default is 500 by the driver.
+ * Example: /sys/class/leds/myled/delay_off
+ */
+constexpr auto DELAYOFF = "/delay_off";
/** @class Physical
* @brief Responsible for applying actions on a particular physical LED
@@ -62,18 +99,91 @@ class Physical : public sdbusplus::server::object::object<
*/
std::string path;
+ /** @brief Frequency range that the LED can operate on.
+ * Will be removed when frequency is put into interface
+ */
+ uint32_t frequency;
+
+ /** @brief Brightness described above */
+ std::string brightCtrl;
+
+ /** @brief BlinkCtrl described above */
+ std::string blinkCtrl;
+
+ /** @brief delay_on described above */
+ std::string delayOnCtrl;
+
+ /** @brief delay_ff described above */
+ std::string delayOffCtrl;
+
+ /** @brief reads sysfs and then setsup the parameteres accordingly
+ *
+ * @return None
+ */
+ void setInitialState();
+
/** @brief Applies the user triggered action on the LED
* by writing to sysfs
*
+ * @param [in] current - Current state of LED
+ * @param [in] request - Requested state
+ *
* @return None
*/
- void driveLED(void);
+ void driveLED(Action current, Action request);
- /** @brief reads sysfs and then setsup the parameteres accordingly
+ /** @brief Sets the LED to either ON or OFF state
+ *
+ * @param [in] action - Requested action. Could be OFF or ON
+ * @return None
+ */
+ void stableStateOperation(Action action);
+
+ /** @brief Sets the LED to BLINKING
+ *
+ * @return None
+ */
+ void blinkOperation();
+
+ /** @brief Generic file writer.
+ * There are files like "brightness", "trigger" , "delay_on" and
+ * "delay_off" that will tell what the LED driver needs to do.
*
- * @return Status or exception thrown
+ * @param[in] filename - Name of file to be written
+ * @param[in] data - Data to be written to
+ * @return - None
*/
- void setInitialState(void);
+ template <typename T>
+ auto write(const std::string& fileName, T&& data)
+ {
+ if(std::ifstream(fileName))
+ {
+ std::ofstream file(fileName, std::ios::out);
+ file << data;
+ file.close();
+ }
+ return;
+ }
+
+ /** @brief Generic file reader.
+ * There are files like "brightness", "trigger" , "delay_on" and
+ * "delay_off" that will tell what the LED driver needs to do.
+ *
+ * @param[in] filename - Name of file to be read
+ * @return - File content
+ */
+ template <typename T>
+ T read(const std::string& fileName)
+ {
+ T data = T();
+ if(std::ifstream(fileName))
+ {
+ std::ifstream file(fileName, std::ios::in);
+ file >> data;
+ file.close();
+ }
+ return data;
+ }
};
} // namespace led
OpenPOWER on IntegriCloud