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 <mutex>
22 #include <unistd.h>
23
24 #include "hdf_base.h"
25 #include "securec.h"
26 #include "utils/hdf_log.h"
27 #include "thermal_log.h"
28
29 #define HDF_LOG_TAG ThermalDeviceMitigation
30
31 namespace OHOS {
32 namespace HDI {
33 namespace Thermal {
34 namespace V1_0 {
35 namespace {
36 const int32_t MAX_PATH = 256;
37 const int32_t MAX_BUF_PATH = 256;
38 const std::string SIM_CPU_FREQ_PATH = "/data/cooling/cpu/freq";
39 const std::string GPU_FREQ_PATH = "/data/cooling/gpu/freq";
40 const std::string BATTERY_CHARGER_CURRENT_PATH = "/data/cooling/charger/current";
41 const std::string SIM_BATTERY_CURRENT_PATH = "/data/cooling/battery/current";
42 const std::string BATTERY_VOLTAGE_PATH = "/data/cooling/battery/voltage";
43 std::mutex mutex_;
44 const std::string ACTUAL_CPU_FREQ_PATH = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq";
45 const std::string ACTUAL_BATTERY_CURRENT_PATH = "/sys/class/power_supply/battery/input_current_limited";
46 const int32_t NUM_ZERO = 0;
47 }
WriteSysfsFd(int32_t fd,std::string buf,size_t bytesSize)48 int32_t ThermalDeviceMitigation::WriteSysfsFd(int32_t fd, std::string buf, size_t bytesSize)
49 {
50 ssize_t pos = 0;
51 ssize_t recever = 0;
52 do {
53 recever = write(fd, buf.c_str() + (size_t) pos, bytesSize - (size_t)pos);
54 if (recever < NUM_ZERO) {
55 return recever;
56 }
57 pos += recever;
58 } while ((ssize_t)bytesSize > pos);
59
60 return (int32_t)bytesSize;
61 }
62
OpenSysfsFile(std::string filePath,int32_t flags)63 int32_t ThermalDeviceMitigation::OpenSysfsFile(std::string filePath, int32_t flags)
64 {
65 int32_t ret;
66
67 if (filePath.empty()) {
68 return HDF_ERR_INVALID_PARAM;
69 }
70
71 ret = open(filePath.c_str(), flags);
72 if (ret < NUM_ZERO) {
73 THERMAL_HILOGE(COMP_HDI, "failed to open file %{public}s", filePath.c_str());
74 return ret;
75 }
76 return ret;
77 }
78
WriteSysfsFile(std::string filePath,std::string buf,size_t bytesSize)79 int32_t ThermalDeviceMitigation::WriteSysfsFile(std::string filePath, std::string buf, size_t bytesSize)
80 {
81 int32_t fd = OpenSysfsFile(filePath.c_str(), O_RDWR);
82 if (fd < NUM_ZERO) {
83 THERMAL_HILOGE(COMP_HDI, "failed to open %{public}s", filePath.c_str());
84 return HDF_ERR_IO;
85 }
86 int32_t ret = WriteSysfsFd(fd, buf.c_str(), bytesSize);
87 close(fd);
88 return ret;
89 }
90
SetFlag(bool flag)91 int32_t ThermalDeviceMitigation::SetFlag(bool flag)
92 {
93 flag_ = flag;
94 return HDF_SUCCESS;
95 }
96
ExecuteCpuRequest(uint32_t freq,const std::string & path)97 int32_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, PATH_MAX, sizeof(nodeBuf) - 1, "%s", path.c_str()) < NUM_ZERO) {
107 return ret;
108 }
109 if (snprintf_s(freqBuf, PATH_MAX, sizeof(freqBuf) - 1, "%d", freq) < NUM_ZERO) {
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
CpuRequest(uint32_t freq)122 int32_t ThermalDeviceMitigation::CpuRequest(uint32_t freq)
123 {
124 int32_t ret = ExecuteCpuRequest(freq, ACTUAL_CPU_FREQ_PATH);
125 if (ret != HDF_SUCCESS) {
126 THERMAL_HILOGE(COMP_HDI, "failed to really set freq");
127 }
128 ret = ExecuteCpuRequest(freq, SIM_CPU_FREQ_PATH);
129 if (ret != HDF_SUCCESS) {
130 return HDF_FAILURE;
131 }
132 return HDF_SUCCESS;
133 }
134
ChargerRequest(uint32_t current)135 int32_t ThermalDeviceMitigation::ChargerRequest(uint32_t current)
136 {
137 int32_t ret = ExecuteChargerRequest(current, ACTUAL_BATTERY_CURRENT_PATH);
138 if (ret != HDF_SUCCESS) {
139 THERMAL_HILOGE(COMP_HDI, "failed to really set current");
140 }
141 ret = ExecuteChargerRequest(current, SIM_BATTERY_CURRENT_PATH);
142 if (ret != HDF_SUCCESS) {
143 return HDF_FAILURE;
144 }
145 return HDF_SUCCESS;
146 }
147
GpuRequest(uint32_t freq)148 int32_t ThermalDeviceMitigation::GpuRequest(uint32_t freq)
149 {
150 int32_t ret = HDF_FAILURE;
151 char freqBuf[MAX_PATH] = {0};
152 char nodeBuf[MAX_BUF_PATH] = {0};
153
154 std::lock_guard<std::mutex> lock(mutex_);
155 ret = snprintf_s(nodeBuf, PATH_MAX, sizeof(nodeBuf) - 1, "%s", GPU_FREQ_PATH.c_str());
156 if (ret < NUM_ZERO) {
157 return ret;
158 }
159 ret = snprintf_s(freqBuf, PATH_MAX, sizeof(freqBuf) - 1, "%d", freq);
160 if (ret < NUM_ZERO) {
161 return ret;
162 }
163 if (WriteSysfsFile(nodeBuf, freqBuf, strlen(freqBuf)) > NUM_ZERO) {
164 THERMAL_HILOGI(COMP_HDI, "Set freq to %{public}d", freq);
165 ret = HDF_SUCCESS;
166 } else {
167 THERMAL_HILOGE(COMP_HDI, "failed to set freq");
168 ret = HDF_FAILURE;
169 }
170 return ret;
171 }
172
ExecuteChargerRequest(uint32_t current,const std::string & path)173 int32_t ThermalDeviceMitigation::ExecuteChargerRequest(uint32_t current, const std::string &path)
174 {
175 int32_t ret = HDF_FAILURE;
176 char currentBuf[MAX_PATH] = {0};
177 char nodeBuf[MAX_BUF_PATH] = {0};
178 static uint32_t previous;
179 if (access(path.c_str(), 0) != NUM_ZERO) {
180 return ret;
181 }
182
183 std::lock_guard<std::mutex> lock(mutex_);
184 ret = snprintf_s(nodeBuf, PATH_MAX, sizeof(nodeBuf) - 1, "%s", path.c_str());
185 if (ret < NUM_ZERO) {
186 return ret;
187 }
188 ret = snprintf_s(currentBuf, PATH_MAX, sizeof(currentBuf) - 1, "%d%s", current, "\n");
189 if (ret < NUM_ZERO) {
190 return ret;
191 }
192 if (WriteSysfsFile(nodeBuf, currentBuf, strlen(currentBuf)) > NUM_ZERO) {
193 THERMAL_HILOGI(COMP_HDI, "Set current to %{public}d", current);
194 previous = current;
195 ret = HDF_SUCCESS;
196 } else {
197 THERMAL_HILOGE(COMP_HDI, "failed to set current");
198 ret = HDF_FAILURE;
199 }
200 return ret;
201 }
202
BatteryCurrentRequest(uint32_t current)203 int32_t ThermalDeviceMitigation::BatteryCurrentRequest(uint32_t current)
204 {
205 int32_t ret = HDF_FAILURE;
206 char currentBuf[MAX_PATH] = {0};
207 char nodeBuf[MAX_BUF_PATH] = {0};
208
209 std::lock_guard<std::mutex> lock(mutex_);
210 ret = snprintf_s(nodeBuf, PATH_MAX, sizeof(nodeBuf) - 1, "%s", SIM_BATTERY_CURRENT_PATH.c_str());
211 if (ret < NUM_ZERO) {
212 return ret;
213 }
214 ret = snprintf_s(currentBuf, PATH_MAX, sizeof(currentBuf) - 1, "%d", current);
215 if (ret < NUM_ZERO) {
216 return ret;
217 }
218 if (WriteSysfsFile(nodeBuf, currentBuf, strlen(currentBuf)) > NUM_ZERO) {
219 THERMAL_HILOGI(COMP_HDI, "Set current to %{public}d", current);
220 ret = HDF_SUCCESS;
221 } else {
222 THERMAL_HILOGE(COMP_HDI, "failed to set current");
223 ret = HDF_FAILURE;
224 }
225 return ret;
226 }
227
BatteryVoltageRequest(uint32_t voltage)228 int32_t ThermalDeviceMitigation::BatteryVoltageRequest(uint32_t voltage)
229 {
230 int32_t ret = HDF_FAILURE;
231 char voltageBuf[MAX_PATH] = {0};
232 char voltageNode[MAX_BUF_PATH] = {0};
233
234 std::lock_guard<std::mutex> lock(mutex_);
235 ret = snprintf_s(voltageNode, PATH_MAX, sizeof(voltageNode) - 1, "%s", BATTERY_VOLTAGE_PATH.c_str());
236 if (ret < NUM_ZERO) {
237 return ret;
238 }
239 ret = snprintf_s(voltageBuf, PATH_MAX, sizeof(voltageBuf) - 1, "%d", voltage);
240 if (ret < NUM_ZERO) {
241 return ret;
242 }
243 if (WriteSysfsFile(voltageNode, voltageBuf, strlen(voltageBuf)) > NUM_ZERO) {
244 THERMAL_HILOGI(COMP_HDI, "Set current to %{public}d", voltage);
245 ret = HDF_SUCCESS;
246 } else {
247 THERMAL_HILOGE(COMP_HDI, "failed to set current");
248 ret = HDF_FAILURE;
249 }
250 return ret;
251 }
252 } // V1_0
253 } // Thermal
254 } // HDI
255 } // OHOS