blob: e7ca58290b55c01d929843836f792a0a2e999ad5 [file] [log] [blame]
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +05301/**
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
Andrew Jefferyc41bf5b2018-05-25 16:39:22 +093017#include "physical.hpp"
18
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +053019#include <iostream>
20#include <string>
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +053021namespace phosphor
22{
23namespace led
24{
25
26/** @brief Populates key parameters */
27void Physical::setInitialState()
28{
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +053029 // Control files in /sys/class/leds/<led-name>
30 brightCtrl = path + BRIGHTNESS;
Andrew Jefferyc41bf5b2018-05-25 16:39:22 +093031 blinkCtrl = path + BLINKCTRL;
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +053032
33 delayOnCtrl = path + DELAYON;
34 delayOffCtrl = path + DELAYOFF;
35
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +053036 // 1. read /sys/class/leds/name/trigger
37 // 2. If its 'timer', then its blinking.
38 // 2.1: On blink, use delay_on and delay_off into dutyOn
39 // 3. If its 'none', then read brightness. 255 means, its ON, else OFF.
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +053040
41 auto trigger = read<std::string>(blinkCtrl);
42 if (trigger == "timer")
43 {
44 // LED is blinking. Get the delay_on and delay_off and compute
45 // DutyCycle. sfsfs values are in strings. Need to convert 'em over to
46 // integer.
47 auto delayOn = std::stoi(read<std::string>(delayOnCtrl));
48 auto delayOff = std::stoi(read<std::string>(delayOffCtrl));
49
50 // Calculate frequency and then percentage ON
51 frequency = delayOn + delayOff;
52 auto factor = frequency / 100;
53 auto dutyOn = delayOn / factor;
54
55 // Update.
56 this->dutyOn(dutyOn);
57 }
58 else
59 {
60 // This is hardcoded for now. This will be changed to this->frequency()
61 // when frequency is implemented.
62 // TODO
63 frequency = 1000;
64
65 // LED is either ON or OFF
66 auto brightness = read<std::string>(brightCtrl);
67 if (brightness == std::string(ASSERT))
68 {
69 // LED is in Solid ON
Andrew Jefferyc41bf5b2018-05-25 16:39:22 +093070 sdbusplus::xyz::openbmc_project::Led::server ::Physical::state(
71 Action::On);
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +053072 }
73 else
74 {
75 // LED is in OFF state
Andrew Jefferyc41bf5b2018-05-25 16:39:22 +093076 sdbusplus::xyz::openbmc_project::Led::server ::Physical::state(
77 Action::Off);
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +053078 }
79 }
80 return;
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +053081}
82
83/** @brief Overloaded State Property Setter function */
84auto Physical::state(Action value) -> Action
85{
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +053086 // Obtain current operation
Andrew Jefferyc41bf5b2018-05-25 16:39:22 +093087 auto current =
88 sdbusplus::xyz::openbmc_project::Led::server ::Physical::state();
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +053089
90 // Update requested operation into base class
Andrew Jefferyc41bf5b2018-05-25 16:39:22 +093091 auto requested =
92 sdbusplus::xyz::openbmc_project::Led::server ::Physical::state(value);
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +053093
94 // Apply the action.
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +053095 driveLED(current, requested);
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +053096
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +053097 return value;
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +053098}
99
100/** @brief apply action on the LED */
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +0530101void Physical::driveLED(Action current, Action request)
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +0530102{
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +0530103 if (current == request)
104 {
105 // Best we can do here is ignore.
106 return;
107 }
108
109 // Transition TO Blinking state
110 if (request == Action::Blink)
111 {
112 return blinkOperation();
113 }
114
115 // Transition TO Stable states.
Andrew Jefferyc41bf5b2018-05-25 16:39:22 +0930116 if (request == Action::On || request == Action::Off)
Vishwanatha Subbanna61675c32016-11-30 15:52:15 +0530117 {
118 return stableStateOperation(request);
119 }
120 return;
121}
122
123/** @brief Either TurnON -or- TurnOFF */
124void Physical::stableStateOperation(Action action)
125{
126 auto value = (action == Action::On) ? ASSERT : DEASSERT;
127
128 // Write "none" to trigger to clear any previous action
129 write(blinkCtrl, "none");
130
131 // And write the current command
132 write(brightCtrl, value);
133 return;
134}
135
136/** @brief BLINK the LED */
137void Physical::blinkOperation()
138{
139 // Get the latest dutyOn that the user requested
140 auto dutyOn = this->dutyOn();
141
142 // Write "timer" to "trigger" file
143 write(blinkCtrl, "timer");
144
145 // Write DutyON. Value in percentage 1_millisecond.
146 // so 50% input becomes 500. Driver wants string input
147 auto percentage = frequency / 100;
148 write(delayOnCtrl, std::to_string(dutyOn * percentage));
149
150 // Write DutyOFF. Value in milli seconds so 50% input becomes 500.
151 write(delayOffCtrl, std::to_string((100 - dutyOn) * percentage));
Vishwanatha Subbanna75b55102016-11-30 14:20:53 +0530152 return;
153}
154
155} // namespace led
156} // namespace phosphor