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