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 */
setInitialState()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 uint16_t periodMs = delayOn + led->getDelayOff();
38 auto percentScale = periodMs / 100;
39 this->dutyOn(delayOn / percentScale);
40 this->period(periodMs);
41 sdbusplus::xyz::openbmc_project::Led::server::Physical::state(
42 Action::Blink);
43 }
44 else
45 {
46 // Cache current LED state
47 auto brightness = led->getBrightness();
48 if (brightness != 0U && assert != 0U)
49 {
50 sdbusplus::xyz::openbmc_project::Led::server::Physical::state(
51 Action::On);
52 }
53 else
54 {
55 sdbusplus::xyz::openbmc_project::Led::server::Physical::state(
56 Action::Off);
57 }
58 }
59 }
60
state() const61 auto Physical::state() const -> Action
62 {
63 return sdbusplus::xyz::openbmc_project::Led::server::Physical::state();
64 }
65
state(Action value)66 auto Physical::state(Action value) -> Action
67 {
68 auto current =
69 sdbusplus::xyz::openbmc_project::Led::server::Physical::state();
70
71 auto requested =
72 sdbusplus::xyz::openbmc_project::Led::server::Physical::state(value);
73
74 driveLED(current, requested);
75
76 return value;
77 }
78
driveLED(Action current,Action request)79 void Physical::driveLED(Action current, Action request)
80 {
81 if (current == request)
82 {
83 return;
84 }
85
86 if (request == Action::On || request == Action::Off)
87 {
88 return stableStateOperation(request);
89 }
90
91 assert(request == Action::Blink);
92 blinkOperation();
93 }
94
stableStateOperation(Action action)95 void Physical::stableStateOperation(Action action)
96 {
97 auto value = (action == Action::On) ? assert : deasserted;
98
99 led->setTrigger("none");
100 led->setBrightness(value);
101 }
102
blinkOperation()103 void Physical::blinkOperation()
104 {
105 /*
106 The configuration of the trigger type must precede the configuration of
107 the trigger type properties. From the kernel documentation:
108 "You can change triggers in a similar manner to the way an IO scheduler
109 is chosen (via /sys/class/leds/<device>/trigger). Trigger specific
110 parameters can appear in /sys/class/leds/<device> once a given trigger is
111 selected."
112 Refer:
113 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/leds/leds-class.txt?h=v5.2#n26
114 */
115 auto d = static_cast<unsigned long>(dutyOn());
116 if (d > 100)
117 {
118 d = 100;
119 }
120
121 auto p = static_cast<unsigned long>(period());
122
123 led->setTrigger("timer");
124 led->setDelayOn(p * d / 100UL);
125 led->setDelayOff(p * (100UL - d) / 100UL);
126 }
127
128 /** @brief set led color property in DBus*/
setLedColor(const std::string & color)129 void Physical::setLedColor(const std::string& color)
130 {
131 static const std::string prefix =
132 "xyz.openbmc_project.Led.Physical.Palette.";
133
134 if (color.empty())
135 {
136 return;
137 }
138
139 std::string tmp = color;
140 tmp[0] = static_cast<char>(toupper(tmp[0]));
141 try
142 {
143 auto palette = convertPaletteFromString(prefix + tmp);
144 setPropertyByName("Color", palette);
145 }
146 catch (const sdbusplus::exception::InvalidEnumString&)
147 {
148 // if color var contains invalid color,
149 // Color property will have default value
150 }
151 }
152
153 } // namespace led
154 } // namespace phosphor
155