xref: /openbmc/phosphor-led-sysfs/physical.cpp (revision 97ddb72359663b5ca9d8e0c22588f0022f729ced)
1 /**
2  * Copyright © 2016,2018 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 <cassert>
20 #include <cstdlib>
21 #include <iostream>
22 #include <string>
23 namespace phosphor
24 {
25 namespace led
26 {
27 
28 /** @brief Populates key parameters */
29 void Physical::setInitialState()
30 {
31     assert = led.getMaxBrightness();
32     auto trigger = led.getTrigger();
33     if (trigger == "timer")
34     {
35         // LED is blinking. Get the on and off delays and derive percent duty
36         auto delayOn = led.getDelayOn();
37         periodMs = delayOn + led.getDelayOff();
38         auto percentScale = periodMs / 100;
39         this->dutyOn(delayOn / percentScale);
40     }
41     else
42     {
43         // TODO: Periodicity is hardcoded for now. This will be changed to
44         // this->period() when configurable periodicity is implemented.
45         periodMs = 1000;
46 
47         // Cache current LED state
48         auto brightness = led.getBrightness();
49         if (brightness == assert)
50         {
51             sdbusplus::xyz::openbmc_project::Led::server::Physical::state(
52                 Action::On);
53         }
54         else
55         {
56             sdbusplus::xyz::openbmc_project::Led::server::Physical::state(
57                 Action::Off);
58         }
59     }
60     return;
61 }
62 
63 auto Physical::state(Action value) -> Action
64 {
65     auto current =
66         sdbusplus::xyz::openbmc_project::Led::server::Physical::state();
67 
68     auto requested =
69         sdbusplus::xyz::openbmc_project::Led::server::Physical::state(value);
70 
71     driveLED(current, requested);
72 
73     return value;
74 }
75 
76 void Physical::driveLED(Action current, Action request)
77 {
78     if (current == request)
79     {
80         return;
81     }
82 
83     if (request == Action::On || request == Action::Off)
84     {
85         return stableStateOperation(request);
86     }
87 
88     assert(request == Action::Blink);
89     blinkOperation();
90 }
91 
92 void Physical::stableStateOperation(Action action)
93 {
94     auto value = (action == Action::On) ? assert : DEASSERT;
95 
96     led.setTrigger("none");
97     led.setBrightness(value);
98     return;
99 }
100 
101 void Physical::blinkOperation()
102 {
103     auto dutyOn = this->dutyOn();
104 
105     // Convert percent duty to milliseconds for sysfs interface
106     auto factor = periodMs / 100;
107     led.setDelayOn(dutyOn * factor);
108     led.setDelayOff((100 - dutyOn) * factor);
109 
110     led.setTrigger("timer");
111     return;
112 }
113 
114 /** @brief set led color property in DBus*/
115 void Physical::setLedColor(const std::string& color)
116 {
117     static const std::string prefix =
118         "xyz.openbmc_project.Led.Physical.Palette.";
119     if (!color.length())
120         return;
121     std::string tmp = color;
122     tmp[0] = toupper(tmp[0]);
123     try
124     {
125         auto palette = convertPaletteFromString(prefix + tmp);
126         setPropertyByName("Color", palette);
127     }
128     catch (const sdbusplus::exception::InvalidEnumString&)
129     {
130         // if color var contains invalid color,
131         // Color property will have default value
132     }
133 }
134 
135 } // namespace led
136 } // namespace phosphor
137