xref: /openbmc/phosphor-led-sysfs/physical.cpp (revision 61675c3265166cecb0f8f5c2c4f80a78d3412c25)
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 <iostream>
18 #include <string>
19 #include "physical.hpp"
20 namespace phosphor
21 {
22 namespace led
23 {
24 
25 /** @brief Populates key parameters */
26 void Physical::setInitialState()
27 {
28     // Control files in /sys/class/leds/<led-name>
29     brightCtrl = path + BRIGHTNESS;
30     blinkCtrl =  path + BLINKCTRL;
31 
32     delayOnCtrl = path + DELAYON;
33     delayOffCtrl = path + DELAYOFF;
34 
35     // 1. read /sys/class/leds/name/trigger
36     // 2. If its 'timer', then its blinking.
37     //    2.1: On blink, use delay_on and delay_off into dutyOn
38     // 3. If its 'none', then read brightness. 255 means, its ON, else OFF.
39 
40     auto trigger = read<std::string>(blinkCtrl);
41     if (trigger == "timer")
42     {
43         // LED is blinking. Get the delay_on and delay_off and compute
44         // DutyCycle. sfsfs values are in strings. Need to convert 'em over to
45         // integer.
46         auto delayOn = std::stoi(read<std::string>(delayOnCtrl));
47         auto delayOff = std::stoi(read<std::string>(delayOffCtrl));
48 
49         // Calculate frequency and then percentage ON
50         frequency = delayOn + delayOff;
51         auto factor = frequency / 100;
52         auto dutyOn = delayOn / factor;
53 
54         // Update.
55         this->dutyOn(dutyOn);
56     }
57     else
58     {
59         // This is hardcoded for now. This will be changed to this->frequency()
60         // when frequency is implemented.
61         // TODO
62         frequency = 1000;
63 
64         // LED is either ON or OFF
65         auto brightness = read<std::string>(brightCtrl);
66         if (brightness == std::string(ASSERT))
67         {
68             // LED is in Solid ON
69             sdbusplus::xyz::openbmc_project::Led::server
70                           ::Physical::state(Action::On);
71         }
72         else
73         {
74             // LED is in OFF state
75             sdbusplus::xyz::openbmc_project::Led::server
76                           ::Physical::state(Action::Off);
77         }
78     }
79     return;
80 }
81 
82 /** @brief Overloaded State Property Setter function */
83 auto Physical::state(Action value) -> Action
84 {
85     // Obtain current operation
86     auto current = sdbusplus::xyz::openbmc_project::Led::server
87                                    ::Physical::state();
88 
89     // Update requested operation into base class
90     auto requested = sdbusplus::xyz::openbmc_project::Led::server
91                                    ::Physical::state(value);
92 
93     // Apply the action.
94     driveLED(current, requested);
95 
96     return value;
97 }
98 
99 /** @brief apply action on the LED */
100 void Physical::driveLED(Action current, Action request)
101 {
102     if (current == request)
103     {
104         // Best we can do here is ignore.
105         return;
106     }
107 
108     // Transition TO Blinking state
109     if (request == Action::Blink)
110     {
111         return blinkOperation();
112     }
113 
114     // Transition TO Stable states.
115     if(request == Action::On || request == Action::Off)
116     {
117         return stableStateOperation(request);
118     }
119     return;
120 }
121 
122 /** @brief Either TurnON -or- TurnOFF */
123 void Physical::stableStateOperation(Action action)
124 {
125     auto value = (action == Action::On) ? ASSERT : DEASSERT;
126 
127     // Write "none" to trigger to clear any previous action
128     write(blinkCtrl, "none");
129 
130     // And write the current command
131     write(brightCtrl, value);
132     return;
133 }
134 
135 /** @brief BLINK the LED */
136 void Physical::blinkOperation()
137 {
138     // Get the latest dutyOn that the user requested
139     auto dutyOn = this->dutyOn();
140 
141     // Write "timer" to "trigger" file
142     write(blinkCtrl, "timer");
143 
144     // Write DutyON. Value in percentage 1_millisecond.
145     // so 50% input becomes 500. Driver wants string input
146     auto percentage = frequency / 100;
147     write(delayOnCtrl, std::to_string(dutyOn * percentage));
148 
149     // Write DutyOFF. Value in milli seconds so 50% input becomes 500.
150     write(delayOffCtrl, std::to_string((100 - dutyOn) * percentage));
151     return;
152 }
153 
154 } // namespace led
155 } // namespace phosphor
156