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