summaryrefslogtreecommitdiffstats
path: root/physical.cpp
blob: 0de2a53d9d489565b3b7b4da76bda7e8ab3f0f58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**
 * Copyright © 2016 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "physical.hpp"

#include <iostream>
#include <string>
namespace phosphor
{
namespace led
{

/** @brief Populates key parameters */
void Physical::setInitialState()
{
    // 1. read /sys/class/leds/name/trigger
    // 2. If its 'timer', then its blinking.
    //    2.1: On blink, use delay_on and delay_off into dutyOn
    // 3. If its 'none', then read brightness. 255 means, its ON, else OFF.

    auto trigger = led.getTrigger();
    if (trigger == "timer")
    {
        // LED is blinking. Get the delay_on and delay_off and compute
        // DutyCycle. sfsfs values are in strings. Need to convert 'em over to
        // integer.
        auto delayOn = led.getDelayOn();
        auto delayOff = led.getDelayOff();

        // Calculate frequency and then percentage ON
        periodMs = delayOn + delayOff;
        auto factor = periodMs / 100;
        auto dutyOn = delayOn / factor;

        // Update.
        this->dutyOn(dutyOn);
    }
    else
    {
        // This is hardcoded for now. This will be changed to this->period()
        // when configurable periodicity is implemented.
        // TODO
        periodMs = 1000;

        // LED is either ON or OFF
        auto brightness = led.getBrightness();
        if (brightness == ASSERT)
        {
            // LED is in Solid ON
            sdbusplus::xyz::openbmc_project::Led::server ::Physical::state(
                Action::On);
        }
        else
        {
            // LED is in OFF state
            sdbusplus::xyz::openbmc_project::Led::server ::Physical::state(
                Action::Off);
        }
    }
    return;
}

/** @brief Overloaded State Property Setter function */
auto Physical::state(Action value) -> Action
{
    // Obtain current operation
    auto current =
        sdbusplus::xyz::openbmc_project::Led::server ::Physical::state();

    // Update requested operation into base class
    auto requested =
        sdbusplus::xyz::openbmc_project::Led::server ::Physical::state(value);

    // Apply the action.
    driveLED(current, requested);

    return value;
}

/** @brief apply action on the LED */
void Physical::driveLED(Action current, Action request)
{
    if (current == request)
    {
        // Best we can do here is ignore.
        return;
    }

    // Transition TO Blinking state
    if (request == Action::Blink)
    {
        return blinkOperation();
    }

    // Transition TO Stable states.
    if (request == Action::On || request == Action::Off)
    {
        return stableStateOperation(request);
    }
    return;
}

/** @brief Either TurnON -or- TurnOFF */
void Physical::stableStateOperation(Action action)
{
    auto value = (action == Action::On) ? ASSERT : DEASSERT;

    // Write "none" to trigger to clear any previous action
    led.setTrigger("none");

    // And write the current command
    led.setBrightness(value);
    return;
}

/** @brief BLINK the LED */
void Physical::blinkOperation()
{
    // Get the latest dutyOn that the user requested
    auto dutyOn = this->dutyOn();

    // Write "timer" to "trigger" file
    led.setTrigger("timer");

    // Write DutyON. Value in percentage 1_millisecond.
    // so 50% input becomes 500. Driver wants string input
    auto factor = periodMs / 100;
    led.setDelayOn(dutyOn * factor);

    // Write DutyOFF. Value in milli seconds so 50% input becomes 500.
    led.setDelayOff((100 - dutyOn) * factor);
    return;
}

} // namespace led
} // namespace phosphor
OpenPOWER on IntegriCloud