xref: /openbmc/phosphor-led-sysfs/physical.cpp (revision e5c40feae02560f56790457be1c2e289ccd0ce6f)
1 /**
2  * Copyright © 2016 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "physical.hpp"
18 
19 #include <iostream>
20 #include <string>
21 namespace phosphor
22 {
23 namespace led
24 {
25 
26 /** @brief Populates key parameters */
27 void Physical::setInitialState()
28 {
29     // 1. read /sys/class/leds/name/trigger
30     // 2. If its 'timer', then its blinking.
31     //    2.1: On blink, use delay_on and delay_off into dutyOn
32     // 3. If its 'none', then read brightness. 255 means, its ON, else OFF.
33 
34     auto trigger = led.getTrigger();
35     if (trigger == "timer")
36     {
37         // LED is blinking. Get the delay_on and delay_off and compute
38         // DutyCycle. sfsfs values are in strings. Need to convert 'em over to
39         // integer.
40         auto delayOn = led.getDelayOn();
41         auto delayOff = led.getDelayOff();
42 
43         // Calculate frequency and then percentage ON
44         periodMs = delayOn + delayOff;
45         auto factor = periodMs / 100;
46         auto dutyOn = delayOn / factor;
47 
48         // Update.
49         this->dutyOn(dutyOn);
50     }
51     else
52     {
53         // This is hardcoded for now. This will be changed to this->period()
54         // when configurable periodicity is implemented.
55         // TODO
56         periodMs = 1000;
57 
58         // LED is either ON or OFF
59         auto brightness = led.getBrightness();
60         if (brightness == ASSERT)
61         {
62             // LED is in Solid ON
63             sdbusplus::xyz::openbmc_project::Led::server ::Physical::state(
64                 Action::On);
65         }
66         else
67         {
68             // LED is in OFF state
69             sdbusplus::xyz::openbmc_project::Led::server ::Physical::state(
70                 Action::Off);
71         }
72     }
73     return;
74 }
75 
76 /** @brief Overloaded State Property Setter function */
77 auto Physical::state(Action value) -> Action
78 {
79     // Obtain current operation
80     auto current =
81         sdbusplus::xyz::openbmc_project::Led::server ::Physical::state();
82 
83     // Update requested operation into base class
84     auto requested =
85         sdbusplus::xyz::openbmc_project::Led::server ::Physical::state(value);
86 
87     // Apply the action.
88     driveLED(current, requested);
89 
90     return value;
91 }
92 
93 /** @brief apply action on the LED */
94 void Physical::driveLED(Action current, Action request)
95 {
96     if (current == request)
97     {
98         // Best we can do here is ignore.
99         return;
100     }
101 
102     // Transition TO Blinking state
103     if (request == Action::Blink)
104     {
105         return blinkOperation();
106     }
107 
108     // Transition TO Stable states.
109     if (request == Action::On || request == Action::Off)
110     {
111         return stableStateOperation(request);
112     }
113     return;
114 }
115 
116 /** @brief Either TurnON -or- TurnOFF */
117 void Physical::stableStateOperation(Action action)
118 {
119     auto value = (action == Action::On) ? ASSERT : DEASSERT;
120 
121     // Write "none" to trigger to clear any previous action
122     led.setTrigger("none");
123 
124     // And write the current command
125     led.setBrightness(value);
126     return;
127 }
128 
129 /** @brief BLINK the LED */
130 void Physical::blinkOperation()
131 {
132     // Get the latest dutyOn that the user requested
133     auto dutyOn = this->dutyOn();
134 
135     // Write "timer" to "trigger" file
136     led.setTrigger("timer");
137 
138     // Write DutyON. Value in percentage 1_millisecond.
139     // so 50% input becomes 500. Driver wants string input
140     auto factor = periodMs / 100;
141     led.setDelayOn(dutyOn * factor);
142 
143     // Write DutyOFF. Value in milli seconds so 50% input becomes 500.
144     led.setDelayOff((100 - dutyOn) * factor);
145     return;
146 }
147 
148 } // namespace led
149 } // namespace phosphor
150