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