1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "thermal_device_mitigation.h" 17 18#include <cstdio> 19#include <cstdlib> 20#include <fcntl.h> 21#include <fstream> 22#include <unistd.h> 23 24#include "hdf_base.h" 25#include "securec.h" 26#include "hdf_log.h" 27#include "thermal_log.h" 28#include "thermal_hdf_config.h" 29 30#define HDF_LOG_TAG ThermalDeviceMitigation 31 32namespace OHOS { 33namespace HDI { 34namespace Thermal { 35namespace V1_1 { 36namespace { 37const int32_t MAX_PATH = 256; 38const int32_t MAX_BUF_PATH = 256; 39const std::string SIM_CPU_FREQ_PATH = "/data/service/el0/thermal/cooling/cpu/freq"; 40const std::string GPU_FREQ_PATH = "/data/service/el0/thermal/cooling/gpu/freq"; 41const std::string BATTERY_CHARGER_CURRENT_PATH = "/data/service/el0/thermal/cooling/charger/current"; 42const std::string SIM_BATTERY_CURRENT_PATH = "/data/service/el0/thermal/cooling/battery/current"; 43const std::string BATTERY_VOLTAGE_PATH = "/data/service/el0/thermal/cooling/battery/voltage"; 44const std::string ACTUAL_BATTERY_CURRENT_PATH = "/sys/class/power_supply/battery/input_current_limited"; 45const int32_t NUM_ZERO = 0; 46} 47int32_t ThermalDeviceMitigation::WriteSysfsFd(int32_t fd, std::string buf, size_t bytesSize) 48{ 49 ssize_t pos = 0; 50 do { 51 ssize_t recever = write(fd, buf.c_str() + (size_t) pos, bytesSize - (size_t)pos); 52 if (recever < NUM_ZERO) { 53 return recever; 54 } 55 pos += recever; 56 } while ((ssize_t)bytesSize > pos); 57 58 return (int32_t)bytesSize; 59} 60 61int32_t ThermalDeviceMitigation::OpenSysfsFile(std::string filePath, int32_t flags) 62{ 63 int32_t ret; 64 65 if (filePath.empty()) { 66 return HDF_ERR_INVALID_PARAM; 67 } 68 69 ret = open(filePath.c_str(), flags); 70 if (ret < NUM_ZERO) { 71 THERMAL_HILOGE(COMP_HDI, "failed to open file"); 72 return ret; 73 } 74 return ret; 75} 76 77int32_t ThermalDeviceMitigation::WriteSysfsFile(std::string filePath, std::string buf, size_t bytesSize) 78{ 79 std::fstream file(filePath.c_str(), std::ios::out | std::ios::trunc); 80 file.close(); 81 int32_t fd = OpenSysfsFile(filePath.c_str(), O_RDWR); 82 if (fd < NUM_ZERO) { 83 THERMAL_HILOGE(COMP_HDI, "failed to open SysfsFile"); 84 return HDF_ERR_IO; 85 } 86 int32_t ret = WriteSysfsFd(fd, buf.c_str(), bytesSize); 87 close(fd); 88 return ret; 89} 90 91int32_t ThermalDeviceMitigation::SetFlag(bool flag) 92{ 93 flag_ = flag; 94 return HDF_SUCCESS; 95} 96 97int32_t ThermalDeviceMitigation::ExecuteCpuRequest(uint32_t freq, const std::string &path) 98{ 99 int32_t ret = HDF_FAILURE; 100 char freqBuf[MAX_PATH] = {0}; 101 char nodeBuf[MAX_BUF_PATH] = {0}; 102 if (access(path.c_str(), 0) != NUM_ZERO) { 103 return ret; 104 } 105 std::lock_guard<std::mutex> lock(mutex_); 106 if (snprintf_s(nodeBuf, MAX_BUF_PATH, sizeof(nodeBuf) - 1, "%s", path.c_str()) < EOK) { 107 return ret; 108 } 109 if (snprintf_s(freqBuf, MAX_PATH, sizeof(freqBuf) - 1, "%u", freq) < EOK) { 110 return ret; 111 } 112 if (WriteSysfsFile(nodeBuf, freqBuf, strlen(freqBuf)) > NUM_ZERO) { 113 THERMAL_HILOGI(COMP_HDI, "Set freq to %{public}d", freq); 114 ret = HDF_SUCCESS; 115 } else { 116 THERMAL_HILOGE(COMP_HDI, "failed to set freq"); 117 ret = HDF_FAILURE; 118 } 119 return ret; 120} 121 122int32_t ThermalDeviceMitigation::CpuRequest(uint32_t freq) 123{ 124 int32_t ret = ExecuteCpuRequest(freq, SIM_CPU_FREQ_PATH); 125 if (ret != HDF_SUCCESS) { 126 return HDF_FAILURE; 127 } 128 return HDF_SUCCESS; 129} 130 131int32_t ThermalDeviceMitigation::ChargerRequest(uint32_t current) 132{ 133 int32_t ret = ExecuteChargerRequest(current, ACTUAL_BATTERY_CURRENT_PATH); 134 if (ret != HDF_SUCCESS) { 135 THERMAL_HILOGE(COMP_HDI, "failed to really set current"); 136 } 137 ret = ExecuteChargerRequest(current, SIM_BATTERY_CURRENT_PATH); 138 if (ret != HDF_SUCCESS) { 139 return HDF_FAILURE; 140 } 141 return HDF_SUCCESS; 142} 143 144int32_t ThermalDeviceMitigation::GpuRequest(uint32_t freq) 145{ 146 int32_t ret = HDF_FAILURE; 147 char freqBuf[MAX_PATH] = {0}; 148 char nodeBuf[MAX_BUF_PATH] = {0}; 149 150 std::lock_guard<std::mutex> lock(mutex_); 151 ret = snprintf_s(nodeBuf, MAX_BUF_PATH, sizeof(nodeBuf) - 1, "%s", GPU_FREQ_PATH.c_str()); 152 if (ret < EOK) { 153 return ret; 154 } 155 ret = snprintf_s(freqBuf, MAX_PATH, sizeof(freqBuf) - 1, "%u", freq); 156 if (ret < EOK) { 157 return ret; 158 } 159 if (WriteSysfsFile(nodeBuf, freqBuf, strlen(freqBuf)) > NUM_ZERO) { 160 THERMAL_HILOGI(COMP_HDI, "Set freq to %{public}d", freq); 161 ret = HDF_SUCCESS; 162 } else { 163 THERMAL_HILOGE(COMP_HDI, "failed to set freq"); 164 ret = HDF_FAILURE; 165 } 166 return ret; 167} 168 169int32_t ThermalDeviceMitigation::ExecuteChargerRequest(uint32_t current, const std::string &path) 170{ 171 int32_t ret = HDF_FAILURE; 172 char currentBuf[MAX_PATH] = {0}; 173 char nodeBuf[MAX_BUF_PATH] = {0}; 174 if (access(path.c_str(), 0) != NUM_ZERO) { 175 return ret; 176 } 177 178 std::lock_guard<std::mutex> lock(mutex_); 179 ret = snprintf_s(nodeBuf, MAX_BUF_PATH, sizeof(nodeBuf) - 1, "%s", path.c_str()); 180 if (ret < EOK) { 181 return ret; 182 } 183 ret = snprintf_s(currentBuf, MAX_PATH, sizeof(currentBuf) - 1, "%u%s", current, "\n"); 184 if (ret < EOK) { 185 return ret; 186 } 187 if (WriteSysfsFile(nodeBuf, currentBuf, strlen(currentBuf)) > NUM_ZERO) { 188 THERMAL_HILOGI(COMP_HDI, "Set current to %{public}d", current); 189 ret = HDF_SUCCESS; 190 } else { 191 THERMAL_HILOGE(COMP_HDI, "failed to set current"); 192 ret = HDF_FAILURE; 193 } 194 return ret; 195} 196 197int32_t ThermalDeviceMitigation::BatteryCurrentRequest(uint32_t current) 198{ 199 int32_t ret = HDF_FAILURE; 200 char currentBuf[MAX_PATH] = {0}; 201 char nodeBuf[MAX_BUF_PATH] = {0}; 202 203 std::lock_guard<std::mutex> lock(mutex_); 204 ret = snprintf_s(nodeBuf, MAX_BUF_PATH, sizeof(nodeBuf) - 1, "%s", SIM_BATTERY_CURRENT_PATH.c_str()); 205 if (ret < EOK) { 206 return ret; 207 } 208 ret = snprintf_s(currentBuf, MAX_PATH, sizeof(currentBuf) - 1, "%u", current); 209 if (ret < EOK) { 210 return ret; 211 } 212 if (WriteSysfsFile(nodeBuf, currentBuf, strlen(currentBuf)) > NUM_ZERO) { 213 THERMAL_HILOGI(COMP_HDI, "Set current to %{public}d", current); 214 ret = HDF_SUCCESS; 215 } else { 216 THERMAL_HILOGE(COMP_HDI, "failed to set current"); 217 ret = HDF_FAILURE; 218 } 219 return ret; 220} 221 222int32_t ThermalDeviceMitigation::BatteryVoltageRequest(uint32_t voltage) 223{ 224 int32_t ret = HDF_FAILURE; 225 char voltageBuf[MAX_PATH] = {0}; 226 char voltageNode[MAX_BUF_PATH] = {0}; 227 228 std::lock_guard<std::mutex> lock(mutex_); 229 ret = snprintf_s(voltageNode, MAX_BUF_PATH, sizeof(voltageNode) - 1, "%s", BATTERY_VOLTAGE_PATH.c_str()); 230 if (ret < EOK) { 231 return ret; 232 } 233 ret = snprintf_s(voltageBuf, MAX_PATH, sizeof(voltageBuf) - 1, "%u", voltage); 234 if (ret < EOK) { 235 return ret; 236 } 237 if (WriteSysfsFile(voltageNode, voltageBuf, strlen(voltageBuf)) > NUM_ZERO) { 238 THERMAL_HILOGI(COMP_HDI, "Set current to %{public}d", voltage); 239 ret = HDF_SUCCESS; 240 } else { 241 THERMAL_HILOGE(COMP_HDI, "failed to set current"); 242 ret = HDF_FAILURE; 243 } 244 return ret; 245} 246 247int32_t ThermalDeviceMitigation::IsolateCpu(int32_t num) 248{ 249 int32_t ret = HDF_FAILURE; 250 char valueBuf[MAX_PATH] = {0}; 251 char isolateCpuPath[MAX_BUF_PATH] = {0}; 252 std::string type = "soc"; 253 std::string path; 254 255 ret = ThermalHdfConfig::GetInstance().GetIsolateCpuNodePath(flag_, type, path); 256 if (ret != HDF_SUCCESS) { 257 THERMAL_HILOGE(COMP_HDI, "get Isolate Cpu config path is null"); 258 return HDF_FAILURE; 259 } 260 261 ret = snprintf_s(isolateCpuPath, MAX_BUF_PATH, sizeof(isolateCpuPath) - 1, "%s", path.c_str()); 262 if (ret < EOK) { 263 return ret; 264 } 265 266 ret = snprintf_s(valueBuf, MAX_PATH, sizeof(valueBuf) - 1, "%d", num); 267 if (ret < EOK) { 268 return ret; 269 } 270 271 std::lock_guard<std::mutex> lock(mutex_); 272 if (WriteSysfsFile(isolateCpuPath, valueBuf, strlen(valueBuf)) > NUM_ZERO) { 273 THERMAL_HILOGI(COMP_HDI, "isolate cpu %{public}d", num); 274 ret = HDF_SUCCESS; 275 } else { 276 THERMAL_HILOGE(COMP_HDI, "failed to isolate cpu"); 277 ret = HDF_FAILURE; 278 } 279 return ret; 280} 281} // V1_1 282} // Thermal 283} // HDI 284} // OHOS 285