1 /*
2 * Copyright 2023 The Android Open Source Project
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 <cstring>
18 #include <dirent.h>
19 #include <dump/pixel_dump.h>
20 #include <fstream>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/sysinfo.h>
24 #include <time.h>
25 #include <vector>
26
27 #include <android-base/file.h>
28 #include <android-base/strings.h>
29 #include "DumpstateUtil.h"
30
31
printTitle(const char * msg)32 void printTitle(const char *msg) {
33 printf("\n------ %s ------\n", msg);
34 }
35
getCommandOutput(const char * cmd,std::string * output)36 int getCommandOutput(const char *cmd, std::string *output) {
37 char buffer[1024];
38 FILE *pipe = popen(cmd, "r");
39 if (!pipe) {
40 return -1;
41 }
42
43 while (fgets(buffer, sizeof buffer, pipe) != NULL) {
44 *output += buffer;
45 }
46 pclose(pipe);
47
48 if (output->back() == '\n')
49 output->pop_back();
50
51 return 0;
52 }
53
isValidFile(const char * file)54 bool isValidFile(const char *file) {
55 FILE *fp = fopen(file, "r");
56 if (fp != NULL) {
57 fclose(fp);
58 return true;
59 }
60 return false;
61 }
62
isValidDir(const char * directory)63 bool isValidDir(const char *directory) {
64 DIR *dir = opendir(directory);
65 if (dir == NULL)
66 return false;
67
68 closedir(dir);
69 return true;
70 }
71
isUserBuild()72 bool isUserBuild() {
73 return ::android::os::dumpstate::PropertiesHelper::IsUserBuild();
74 }
75
getFilesInDir(const char * directory,std::vector<std::string> * files)76 int getFilesInDir(const char *directory, std::vector<std::string> *files) {
77 std::string content;
78 struct dirent *entry;
79
80 DIR *dir = opendir(directory);
81 if (dir == NULL)
82 return -1;
83
84 files->clear();
85 while ((entry = readdir(dir)) != NULL)
86 files->push_back(entry->d_name);
87 closedir(dir);
88
89 sort(files->begin(), files->end());
90 return 0;
91 }
92
dumpPowerStatsTimes()93 void dumpPowerStatsTimes() {
94 const char *title = "Power Stats Times";
95 char rBuff[128];
96 struct timespec rTs;
97 struct sysinfo info;
98 int ret;
99
100 printTitle(title);
101
102 sysinfo(&info);
103
104 const time_t boottime = time(NULL) - info.uptime;
105
106 ret = clock_gettime(CLOCK_REALTIME, &rTs);
107 if (ret)
108 return;
109
110 struct tm *nowTime = std::localtime(&rTs.tv_sec);
111
112 std::strftime(rBuff, sizeof(rBuff), "%m/%d/%Y %H:%M:%S", nowTime);
113 printf("Boot: %s", ctime(&boottime));
114 printf("Now: %s\n", rBuff);
115 }
116
readContentsOfDir(const char * title,const char * directory,const char * strMatch,bool useStrMatch=false,bool printDirectory=false)117 int readContentsOfDir(const char* title, const char* directory, const char* strMatch,
118 bool useStrMatch = false, bool printDirectory = false) {
119 std::vector<std::string> files;
120 std::string content;
121 std::string fileLocation;
122 int ret;
123
124 ret = getFilesInDir(directory, &files);
125 if (ret < 0)
126 return ret;
127
128 printTitle(title);
129 for (auto &file : files) {
130 if (useStrMatch && std::string::npos == std::string(file).find(strMatch)) {
131 continue;
132 }
133
134 fileLocation = std::string(directory) + std::string(file);
135 if (!android::base::ReadFileToString(fileLocation, &content)) {
136 continue;
137 }
138 if (printDirectory) {
139 printf("\n\n%s\n", fileLocation.c_str());
140 }
141 if (content.back() == '\n')
142 content.pop_back();
143 printf("%s\n", content.c_str());
144 }
145 return 0;
146 }
147
dumpAcpmStats()148 void dumpAcpmStats() {
149 const char* acpmDir = "/sys/devices/platform/acpm_stats/";
150 const char* statsSubStr = "_stats";
151 const char* acpmTitle = "ACPM stats";
152 readContentsOfDir(acpmTitle, acpmDir, statsSubStr, true, true);
153 }
154
dumpTcpmPsyUevent()155 void dumpTcpmPsyUevent() {
156 const char* tcpmPsy = "tcpm-source-psy-";
157 DIR *dir = opendir("/sys/class/power_supply/");
158 struct dirent *entry;
159
160 if (dir == NULL)
161 return;
162
163 while ((entry = readdir(dir)) != NULL) {
164 if (std::string::npos != std::string(entry->d_name).find(tcpmPsy)) {
165 std::string fullPath("/sys/class/power_supply/" + (const std::string)entry->d_name +
166 "/uevent");
167 dumpFileContent("Power supply property tcpm", fullPath.c_str());
168 break;
169 }
170 }
171
172 closedir(dir);
173 }
174
dumpPowerSupplyStats()175 void dumpPowerSupplyStats() {
176 const char* dumpList[][2] = {
177 {"CPU PM stats", "/sys/devices/system/cpu/cpupm/cpupm/time_in_state"},
178 {"GENPD summary", "/d/pm_genpd/pm_genpd_summary"},
179 {"Power supply property battery", "/sys/class/power_supply/battery/uevent"},
180 {"Power supply property dc", "/sys/class/power_supply/dc/uevent"},
181 {"Power supply property gcpm", "/sys/class/power_supply/gcpm/uevent"},
182 {"Power supply property gcpm_pps", "/sys/class/power_supply/gcpm_pps/uevent"},
183 {"Power supply property main-charger", "/sys/class/power_supply/main-charger/uevent"},
184 {"Power supply property dc-mains", "/sys/class/power_supply/dc-mains/uevent"},
185 {"Power supply property usb", "/sys/class/power_supply/usb/uevent"},
186 {"Power supply property wireless", "/sys/class/power_supply/wireless/uevent"},
187 };
188
189 for (const auto &row : dumpList) {
190 dumpFileContent(row[0], row[1]);
191 }
192
193 dumpTcpmPsyUevent();
194 }
195
dumpMaxFg()196 void dumpMaxFg() {
197 const char *maxfgLoc = "/sys/class/power_supply/maxfg";
198
199 const char *maxfg [][2] = {
200 {"Power supply property maxfg", "/sys/class/power_supply/maxfg/uevent"},
201 {"m5_state", "/sys/class/power_supply/maxfg/m5_model_state"},
202 {"maxfg logbuffer", "/dev/logbuffer_maxfg"},
203 {"maxfg_monitor logbuffer", "/dev/logbuffer_maxfg_monitor"},
204 };
205
206 const char *maxfgFlip [][2] = {
207 {"Power supply property maxfg_base", "/sys/class/power_supply/maxfg_base/uevent"},
208 {"Power supply property maxfg_flip", "/sys/class/power_supply/maxfg_flip/uevent"},
209 {"m5_state", "/sys/class/power_supply/maxfg_base/m5_model_state"},
210 {"maxfg_base", "/dev/logbuffer_maxfg_base"},
211 {"maxfg_flip", "/dev/logbuffer_maxfg_flip"},
212 {"maxfg_base", "/dev/logbuffer_maxfg_base_monitor"},
213 {"maxfg_flip", "/dev/logbuffer_maxfg_flip_monitor"},
214 };
215
216 const char *maxfgHistoryName = "Maxim FG History";
217 const char *maxfgHistoryDir = "/dev/maxfg_history";
218
219 std::string content;
220
221
222 if (isValidDir(maxfgLoc)) {
223 for (const auto &row : maxfg) {
224 dumpFileContent(row[0], row[1]);
225 }
226 } else {
227 for (const auto &row : maxfgFlip) {
228 dumpFileContent(row[0], row[1]);
229 }
230 }
231
232 if (isValidFile(maxfgHistoryDir)) {
233 dumpFileContent(maxfgHistoryName, maxfgHistoryDir);
234 }
235 }
236
dumpPowerSupplyDock()237 void dumpPowerSupplyDock() {
238 const char* powerSupplyPropertyDockTitle = "Power supply property dock";
239 const char* powerSupplyPropertyDockFile = "/sys/class/power_supply/dock/uevent";
240 if (isValidFile(powerSupplyPropertyDockFile)) {
241 dumpFileContent(powerSupplyPropertyDockTitle, powerSupplyPropertyDockFile);
242 }
243 }
244
dumpLogBufferTcpm()245 void dumpLogBufferTcpm() {
246 const char* logbufferTcpmTitle = "Logbuffer TCPM";
247 const char* logbufferTcpmFile = "/dev/logbuffer_tcpm";
248 const char* debugTcpmFile = "/sys/kernel/debug/tcpm";
249 const char* tcpmLogTitle = "TCPM logs";
250 const char* tcpmFile = "/sys/kernel/debug/tcpm";
251 const char* tcpmFileAlt = "/sys/kernel/debug/usb/tcpm";
252 int retCode;
253
254 dumpFileContent(logbufferTcpmTitle, logbufferTcpmFile);
255
256 retCode = readContentsOfDir(tcpmLogTitle, isValidFile(debugTcpmFile) ? tcpmFile : tcpmFileAlt,
257 NULL);
258 if (retCode < 0)
259 printTitle(tcpmLogTitle);
260 }
261
dumpTcpc()262 void dumpTcpc() {
263 int ret;
264 const char* max77759TcpcHead = "TCPC";
265 const char* i2cSubDirMatch = "i2c-";
266 const char* directory = "/sys/devices/platform/10d60000.hsi2c/";
267 const char* max77759Tcpc [][2] {
268 {"registers:", "/i2c-max77759tcpc/registers"},
269 {"frs:", "/i2c-max77759tcpc/frs"},
270 {"auto_discharge:", "/i2c-max77759tcpc/auto_discharge"},
271 {"bcl2_enabled:", "/i2c-max77759tcpc/bcl2_enabled"},
272 {"cc_toggle_enable:", "/i2c-max77759tcpc/cc_toggle_enable"},
273 {"containment_detection:", "/i2c-max77759tcpc/containment_detection"},
274 {"containment_detection_status:", "/i2c-max77759tcpc/containment_detection_status"},
275 };
276
277 std::vector<std::string> files;
278 std::string content;
279
280 printTitle(max77759TcpcHead);
281
282 ret = getFilesInDir(directory, &files);
283 if (ret < 0) {
284 for (auto &tcpcVal : max77759Tcpc)
285 printf("%s\n", tcpcVal[0]);
286 return;
287 }
288
289 for (auto &file : files) {
290 for (auto &tcpcVal : max77759Tcpc) {
291 printf("%s ", tcpcVal[0]);
292 if (std::string::npos == std::string(file).find(i2cSubDirMatch)) {
293 continue;
294 }
295
296 std::string fileName = directory + file + "/" + std::string(tcpcVal[1]);
297
298 if (!android::base::ReadFileToString(fileName, &content)) {
299 continue;
300 }
301
302 printf("%s\n", content.c_str());
303 }
304 }
305 }
306
dumpPdEngine()307 void dumpPdEngine() {
308 const char* pdEngine [][2] {
309 {"PD Engine", "/dev/logbuffer_usbpd"},
310 {"PPS-google_cpm", "/dev/logbuffer_cpm"},
311 {"PPS-dc", "/dev/logbuffer_pca9468"},
312 };
313
314 for (const auto &row : pdEngine) {
315 dumpFileContent(row[0], row[1]);
316 }
317 }
318
dumpEusbRepeater()319 void dumpEusbRepeater() {
320 const char* dumpTitle = "registers dump of eUSB repeater";
321 const char* dumpFile = "/d/eusb_repeater/registers";
322
323 if (isValidFile(dumpFile)) {
324 dumpFileContent(dumpTitle, dumpFile);
325 }
326 }
327
dumpWc68()328 void dumpWc68() {
329 const char* wc68Title = "WC68";
330 const char* wc68File = "/dev/logbuffer_wc68";
331
332 if (isValidFile(wc68File)) {
333 dumpFileContent(wc68Title, wc68File);
334 }
335 }
336
dumpLn8411()337 void dumpLn8411() {
338 const char* ln8411Title = "LN8411";
339 const char* ln8411File = "/dev/logbuffer_ln8411";
340
341 if (isValidFile(ln8411File)) {
342 dumpFileContent(ln8411Title, ln8411File);
343 }
344 }
345
dumpBatteryHealth()346 void dumpBatteryHealth() {
347 const char* batteryHealth [][2] {
348 {"Battery Health", "/sys/class/power_supply/battery/health_index_stats"},
349 {"Battery Health SoC Residency", "/sys/class/power_supply/battery/swelling_data"},
350 {"BMS", "/dev/logbuffer_ssoc"},
351 {"TTF", "/dev/logbuffer_ttf"},
352 {"TTF details", "/sys/class/power_supply/battery/ttf_details"},
353 {"TTF stats", "/sys/class/power_supply/battery/ttf_stats"},
354 {"aacr_state", "/sys/class/power_supply/battery/aacr_state"},
355 {"maxq", "/dev/logbuffer_maxq"},
356 {"TEMP/DOCK-DEFEND", "/dev/logbuffer_bd"},
357 };
358
359 for (const auto &row : batteryHealth) {
360 dumpFileContent(row[0], row[1]);
361 }
362 }
363
dumpBatteryDefend()364 void dumpBatteryDefend() {
365 const char* defendConfig [][4] {
366 {"TRICKLE-DEFEND Config",
367 "/sys/devices/platform/google,battery/power_supply/battery/", "bd_"},
368 {"DWELL-DEFEND Config", "/sys/devices/platform/google,charger/", "charge_s"},
369 {"DWELL-DEFEND Time", "/mnt/vendor/persist/battery/", "defender_"},
370 {"TEMP-DEFEND Config", "/sys/devices/platform/google,charger/", "bd_"},
371 };
372
373 std::vector<std::string> files;
374 struct dirent *entry;
375 std::string content;
376 std::string fileLocation;
377
378 for (auto &config : defendConfig) {
379 DIR *dir = opendir(config[1]);
380 if (dir == NULL)
381 continue;
382
383 printTitle(config[0]);
384 while ((entry = readdir(dir)) != NULL) {
385 if (std::string(entry->d_name).find(config[2]) != std::string::npos &&
386 strncmp(config[2], entry->d_name, strlen(config[2])) == 0) {
387 files.push_back(entry->d_name);
388 }
389 }
390 closedir(dir);
391
392 sort(files.begin(), files.end());
393
394 for (auto &file : files) {
395 fileLocation = std::string(config[1]) + std::string(file);
396 if (!android::base::ReadFileToString(fileLocation, &content) || content.empty()) {
397 content = "\n";
398 }
399
400 printf("%s: %s", file.c_str(), content.c_str());
401
402 if (content.back() != '\n')
403 printf("\n");
404 }
405
406 files.clear();
407 }
408 }
409
printValuesOfDirectory(const char * directory,std::string debugfs,const char * strMatch)410 void printValuesOfDirectory(const char *directory, std::string debugfs, const char *strMatch) {
411 std::vector<std::string> files;
412 auto info = directory;
413 std::string content;
414 struct dirent *entry;
415 DIR *dir = opendir(debugfs.c_str());
416 if (dir == NULL)
417 return;
418
419 printTitle((debugfs + std::string(strMatch) + "/" + std::string(info)).c_str());
420 while ((entry = readdir(dir)) != NULL)
421 if (std::string(entry->d_name).find(strMatch) != std::string::npos)
422 files.push_back(entry->d_name);
423 closedir(dir);
424
425 sort(files.begin(), files.end());
426
427 for (auto &file : files) {
428 std::string fileDirectory = debugfs + file;
429 std::string fileLocation = fileDirectory + "/" + std::string(info);
430 if (!android::base::ReadFileToString(fileLocation, &content)) {
431 content = "\n";
432 }
433
434 printf("%s:\n%s", fileDirectory.c_str(), content.c_str());
435
436 if (content.back() != '\n')
437 printf("\n");
438 }
439 files.clear();
440 }
441
dumpChg()442 void dumpChg() {
443 const std::string pmic_bus = "/sys/devices/platform/10cb0000.hsi2c/i2c-11/11-0066";
444 const char* chg_reg_dump_file = "/sys/class/power_supply/main-charger/device/registers_dump";
445 const std::string chg_name_cmd = "/sys/class/power_supply/main-charger/device/name";
446 const std::string pmic_name_cmd = pmic_bus + "/name";
447 const std::string pmic_reg_dump_file = pmic_bus + "/registers_dump";
448 const std::string reg_dump_str = " registers dump";
449 const char* chgConfig [][2] {
450 {"DC_registers dump", "/sys/class/power_supply/dc-mains/device/registers_dump"},
451 };
452 std::string chg_name;
453 std::string pmic_name;
454
455 printf("\n");
456
457 int ret = android::base::ReadFileToString(chg_name_cmd, &chg_name);
458 if (ret && !chg_name.empty()) {
459 chg_name.erase(chg_name.length() - 1); // remove new line
460 const std::string chg_reg_dump_title = chg_name + reg_dump_str;
461
462 /* CHG reg dump */
463 dumpFileContent(chg_reg_dump_title.c_str(), chg_reg_dump_file);
464 }
465
466 ret = android::base::ReadFileToString(pmic_name_cmd, &pmic_name);
467 if (ret && !pmic_name.empty()) {
468 pmic_name.erase(pmic_name.length() - 1); // remove new line
469 const std::string pmic_reg_dump_title = pmic_name + reg_dump_str;
470
471 /* PMIC reg dump */
472 dumpFileContent(pmic_reg_dump_title.c_str(), pmic_reg_dump_file.c_str());
473 }
474
475 for (auto &config : chgConfig) {
476 dumpFileContent(config[0], config[1]);
477 }
478 }
479
dumpChgUserDebug()480 void dumpChgUserDebug() {
481 const std::string debugfs = "/d/";
482 const char *maxFgDir = "/d/maxfg";
483 const char *maxFgStrMatch = "maxfg";
484 const char *maxFg77779StrMatch = "max77779fg";
485 const char *chgTblName = "Charging table dump";
486 const char *chgTblDir = "/d/google_battery/chg_raw_profile";
487
488 const char *maxFgInfo [] {
489 "fg_model",
490 "algo_ver",
491 "model_ok",
492 "registers",
493 "nv_registers",
494 };
495
496 const char *max77779FgInfo [] {
497 "fg_model",
498 "algo_ver",
499 "model_ok",
500 "registers",
501 "debug_registers",
502 };
503
504 if (isUserBuild())
505 return;
506
507 dumpFileContent(chgTblName, chgTblDir);
508
509 if (isValidDir(maxFgDir)) {
510 for (auto & directory : maxFgInfo) {
511 printValuesOfDirectory(directory, debugfs, maxFgStrMatch);
512 }
513 } else {
514 for (auto & directory : max77779FgInfo) {
515 printValuesOfDirectory(directory, debugfs, maxFg77779StrMatch);
516 }
517 }
518 }
519
dumpBatteryEeprom()520 void dumpBatteryEeprom() {
521 const char *title = "Battery EEPROM";
522 const char *files[] {
523 "/sys/devices/platform/10c90000.hsi2c/i2c-9/9-0050/eeprom",
524 };
525 std::string result;
526 std::string xxdCmd;
527
528 printTitle(title);
529 for (auto &file : files) {
530 if (!isValidFile(file))
531 continue;
532
533 xxdCmd = "xxd " + std::string(file);
534
535 int ret = getCommandOutput(xxdCmd.c_str(), &result);
536 if (ret < 0)
537 return;
538
539 printf("%s\n", result.c_str());
540 }
541 }
542
dumpChargerStats()543 void dumpChargerStats() {
544 const char *chgStatsTitle = "Charger Stats";
545 const char *chgStatsLocation = "/sys/class/power_supply/battery/charge_details";
546 const char *chargerStats [][3] {
547 {"Google Charger", "/sys/kernel/debug/google_charger/", "pps_"},
548 {"Google Battery", "/sys/kernel/debug/google_battery/", "ssoc_"},
549 };
550 std::vector<std::string> files;
551 std::string content;
552 struct dirent *entry;
553
554 dumpFileContent(chgStatsTitle, chgStatsLocation);
555
556 if (isUserBuild())
557 return;
558
559 for (auto &stat : chargerStats) {
560 DIR *dir = opendir(stat[1]);
561 if (dir == NULL)
562 return;
563
564 printTitle(stat[0]);
565 while ((entry = readdir(dir)) != NULL)
566 if (std::string(entry->d_name).find(stat[2]) != std::string::npos)
567 files.push_back(entry->d_name);
568 closedir(dir);
569
570 sort(files.begin(), files.end());
571
572 for (auto &file : files) {
573 std::string fileLocation = std::string(stat[1]) + file;
574 if (!android::base::ReadFileToString(fileLocation, &content)) {
575 content = "\n";
576 }
577
578 printf("%s: %s", file.c_str(), content.c_str());
579
580 if (content.back() != '\n')
581 printf("\n");
582 }
583 files.clear();
584 }
585 }
586
dumpWlcLogs()587 void dumpWlcLogs() {
588 const char *dumpWlcList [][2] {
589 {"WLC Logs", "/dev/logbuffer_wireless"},
590 {"WLC VER", "/sys/class/power_supply/wireless/device/version"},
591 {"WLC STATUS", "/sys/class/power_supply/wireless/device/status"},
592 {"WLC FW Version", "/sys/class/power_supply/wireless/device/fw_rev"},
593 {"RTX", "/dev/logbuffer_rtx"},
594 };
595
596 for (auto &row : dumpWlcList) {
597 if (!isValidFile(row[1]))
598 printTitle(row[0]);
599 dumpFileContent(row[0], row[1]);
600 }
601 }
602
dumpGvoteables()603 void dumpGvoteables() {
604 const char *directory = "/sys/kernel/debug/gvotables/";
605 const char *statusName = "/status";
606 const char *title = "gvotables";
607 std::string content;
608 std::vector<std::string> files;
609 int ret;
610
611 if (isUserBuild())
612 return;
613
614 ret = getFilesInDir(directory, &files);
615 if (ret < 0)
616 return;
617
618 printTitle(title);
619 for (auto &file : files) {
620 std::string fileLocation = std::string(directory) + file + std::string(statusName);
621 if (!android::base::ReadFileToString(fileLocation, &content)) {
622 continue;
623 }
624
625 printf("%s: %s", file.c_str(), content.c_str());
626
627 if (content.back() != '\n')
628 printf("\n");
629 }
630 files.clear();
631 }
632
dumpMitigation()633 void dumpMitigation() {
634 const char *mitigationList [][2] {
635 {"Lastmeal" , "/data/vendor/mitigation/lastmeal.txt"},
636 {"Thismeal" , "/data/vendor/mitigation/thismeal.txt"},
637 };
638
639 for (auto &row : mitigationList) {
640 if (!isValidFile(row[1]))
641 printTitle(row[0]);
642 dumpFileContent(row[0], row[1]);
643 }
644 }
645
dumpMitigationStats()646 void dumpMitigationStats() {
647 int ret;
648 const char *directory = "/sys/devices/virtual/pmic/mitigation/last_triggered_count/";
649 const char *capacityDirectory = "/sys/devices/virtual/pmic/mitigation/last_triggered_capacity/";
650 const char *timestampDirectory =
651 "/sys/devices/virtual/pmic/mitigation/last_triggered_timestamp/";
652 const char *voltageDirectory = "/sys/devices/virtual/pmic/mitigation/last_triggered_voltage/";
653 const char *capacitySuffix = "_cap";
654 const char *timeSuffix = "_time";
655 const char *voltageSuffix = "_volt";
656 const char *countSuffix = "_count";
657 const char *title = "Mitigation Stats";
658
659 std::vector<std::string> files;
660 std::string content;
661 std::string fileLocation;
662 std::string source;
663 std::string subModuleName;
664 int count;
665 int soc;
666 int time;
667 int voltage;
668
669 ret = getFilesInDir(directory, &files);
670 if (ret < 0)
671 return;
672
673 printTitle(title);
674 printf("Source\t\tCount\tSOC\tTime\tVoltage\n");
675
676 for (auto &file : files) {
677 fileLocation = std::string(directory) + std::string(file);
678 if (!android::base::ReadFileToString(fileLocation, &content)) {
679 continue;
680 }
681
682 ret = atoi(android::base::Trim(content).c_str());
683 if (ret == -1)
684 continue;
685 count = ret;
686
687 subModuleName = std::string(file);
688 subModuleName.erase(subModuleName.find(countSuffix), strlen(countSuffix));
689
690 fileLocation = std::string(capacityDirectory) + std::string(subModuleName) +
691 std::string(capacitySuffix);
692 if (!android::base::ReadFileToString(fileLocation, &content)) {
693 continue;
694 }
695 ret = atoi(android::base::Trim(content).c_str());
696 if (ret == -1)
697 continue;
698 soc = ret;
699
700 fileLocation = std::string(timestampDirectory) + std::string(subModuleName) +
701 std::string(timeSuffix);
702 if (!android::base::ReadFileToString(fileLocation, &content)) {
703 continue;
704 }
705 ret = atoi(android::base::Trim(content).c_str());
706 if (ret == -1)
707 continue;
708 time = ret;
709
710 fileLocation = std::string(voltageDirectory) + std::string(subModuleName) +
711 std::string(voltageSuffix);
712 if (!android::base::ReadFileToString(fileLocation, &content)) {
713 continue;
714 }
715 ret = atoi(android::base::Trim(content).c_str());
716 if (ret == -1)
717 continue;
718 voltage = ret;
719 printf("%s \t%i\t%i\t%i\t%i\n", subModuleName.c_str(), count, soc, time, voltage);
720 }
721 }
722
dumpMitigationDirs()723 void dumpMitigationDirs() {
724 const int paramCount = 4;
725 const char *titles[] = {
726 "Clock Divider Ratio",
727 "Clock Stats",
728 "Triggered Level",
729 "Instruction",
730 };
731 const char *directories[] = {
732 "/sys/devices/virtual/pmic/mitigation/clock_ratio/",
733 "/sys/devices/virtual/pmic/mitigation/clock_stats/",
734 "/sys/devices/virtual/pmic/mitigation/triggered_lvl/",
735 "/sys/devices/virtual/pmic/mitigation/instruction/",
736 };
737 const char *paramSuffix[] = {"_ratio", "_stats", "_lvl", ""};
738 const char *titleRowVal[] = {
739 "Source\t\tRatio",
740 "Source\t\tStats",
741 "Source\t\tLevel",
742 "",
743 };
744 const int eraseCnt[] = {6, 6, 4, 0};
745 const bool useTitleRow[] = {true, true, true, false};
746
747 std::vector<std::string> files;
748 std::string content;
749 std::string fileLocation;
750 std::string source;
751 std::string subModuleName;
752 std::string readout;
753
754 for (int i = 0; i < paramCount; i++) {
755 printTitle(titles[i]);
756 if (useTitleRow[i]) {
757 printf("%s\n", titleRowVal[i]);
758 }
759
760 getFilesInDir(directories[i], &files);
761
762 for (auto &file : files) {
763 fileLocation = std::string(directories[i]) + std::string(file);
764 if (!android::base::ReadFileToString(fileLocation, &content)) {
765 continue;
766 }
767
768 readout = android::base::Trim(content);
769
770 subModuleName = std::string(file);
771 subModuleName.erase(subModuleName.find(paramSuffix[i]), eraseCnt[i]);
772
773 if (useTitleRow[i]) {
774 printf("%s \t%s\n", subModuleName.c_str(), readout.c_str());
775 } else {
776 printf("%s=%s\n", subModuleName.c_str(), readout.c_str());
777 }
778 }
779 }
780 }
781
dumpIrqDurationCounts()782 void dumpIrqDurationCounts() {
783 const char *title = "IRQ Duration Counts";
784 const char *colNames = "Source\t\t\t\tlt_5ms_cnt\tbt_5ms_to_10ms_cnt\tgt_10ms_cnt\tCode"
785 "\tCurrent Threshold (uA)\tCurrent Reading (uA)\n";
786 const int nonOdpmChannelCnt = 9;
787 const int odpmChCnt = 12;
788
789 enum Duration {
790 LT_5MS,
791 BT_5MS_10MS,
792 GT_10MS,
793 DUR_MAX,
794 };
795 const char *irqDurDirectories[] = {
796 "/sys/devices/virtual/pmic/mitigation/irq_dur_cnt/less_than_5ms_count",
797 "/sys/devices/virtual/pmic/mitigation/irq_dur_cnt/between_5ms_to_10ms_count",
798 "/sys/devices/virtual/pmic/mitigation/irq_dur_cnt/greater_than_10ms_count",
799 };
800
801 enum PowerWarn {
802 MAIN,
803 SUB,
804 PWRWARN_MAX,
805 };
806 const char *pwrwarnDirectories[] = {
807 "/sys/devices/virtual/pmic/mitigation/main_pwrwarn/",
808 "/sys/devices/virtual/pmic/mitigation/sub_pwrwarn/",
809 };
810
811 const char *lpfCurrentDirs[] = {
812 "/sys/devices/platform/acpm_mfd_bus@15500000/i2c-7/7-001f/s2mpg14-meter/"
813 "s2mpg14-odpm/iio:device1/lpf_current",
814 "/sys/devices/platform/acpm_mfd_bus@15510000/i2c-8/8-002f/s2mpg15-meter/"
815 "s2mpg15-odpm/iio:device0/lpf_current",
816 };
817
818 bool titlesInitialized = false;
819
820 std::vector<std::string> channelNames;
821 std::vector<std::string> channelData[DUR_MAX];
822 std::vector<std::string> pwrwarnThreshold[PWRWARN_MAX];
823 std::vector<std::string> pwrwarnCode[PWRWARN_MAX];
824 std::vector<std::string> lpfCurrentVals[PWRWARN_MAX];
825 std::vector<std::string> files;
826
827 std::string content;
828 std::string token;
829 std::string tokenCh;
830 std::string fileLocation;
831
832 for (int i = 0; i < DUR_MAX; i++) {
833 if (!android::base::ReadFileToString(irqDurDirectories[i], &content)) {
834 return;
835 }
836
837 std::istringstream tokenStream(content);
838
839 while (std::getline(tokenStream, token, '\n')) {
840 if (!titlesInitialized) {
841 tokenCh = token;
842 tokenCh.erase(tokenCh.find(':'), tokenCh.length());
843 channelNames.push_back(tokenCh);
844 }
845
846 // there is a space after the ':' which needs to be removed
847 token.erase(0, token.find(':') + 1);
848 channelData[i].push_back(token);
849
850 }
851 if (!titlesInitialized)
852 titlesInitialized = true;
853 }
854
855 for (int i = 0; i < PWRWARN_MAX; i++) {
856 getFilesInDir(pwrwarnDirectories[i], &files);
857
858 for (auto &file : files) {
859 fileLocation = std::string(pwrwarnDirectories[i]) + std::string(file);
860 if (!android::base::ReadFileToString(fileLocation, &content)) {
861 continue;
862 }
863
864 std::string readout;
865
866 readout = android::base::Trim(content);
867
868 std::string readoutThreshold = readout;
869 readoutThreshold.erase(0, readoutThreshold.find('=') + 1);
870
871 std::string readoutCode = readout;
872 readoutCode.erase(readoutCode.find('='), readoutCode.length());
873
874 pwrwarnThreshold[i].push_back(readoutThreshold);
875 pwrwarnCode[i].push_back(readoutCode);
876 }
877 }
878
879 for (int i = 0; i < PWRWARN_MAX; i++) {
880 if (!android::base::ReadFileToString(lpfCurrentDirs[i], &content)) {
881 continue;
882 }
883
884 std::istringstream tokenStream(content);
885
886 bool first = true;
887 while (std::getline(tokenStream, token, '\n')) {
888 token.erase(0, token.find(' '));
889 if (first) {
890 first = false;
891 continue;
892 }
893 lpfCurrentVals[i].push_back(token);
894 }
895 }
896
897 printTitle(title);
898 printf("%s", colNames);
899
900 for (uint i = 0; i < channelNames.size(); i++) {
901 std::string code = "";
902 std::string threshold = "";
903 std::string current = "";
904 std::string ltDataMsg = "";
905 std::string btDataMsg = "";
906 std::string gtDataMsg = "";
907 int pmicSel = 0;
908 int offset = 0;
909 std::string channelNameSuffix = " \t";
910 if (i >= nonOdpmChannelCnt) {
911 offset = nonOdpmChannelCnt;
912 if (i >= (odpmChCnt + nonOdpmChannelCnt)) {
913 pmicSel = 1;
914 offset = odpmChCnt + nonOdpmChannelCnt;
915 }
916 channelNameSuffix = "";
917
918 code = pwrwarnCode[pmicSel][i - offset];
919 threshold = pwrwarnThreshold[pmicSel][i - offset];
920 current = lpfCurrentVals[pmicSel][i - offset];
921 }
922
923 if (i < channelData[0].size())
924 ltDataMsg = channelData[0][i];
925
926 if (i < channelData[1].size())
927 btDataMsg = channelData[1][i];
928
929 if (i < channelData[2].size())
930 gtDataMsg = channelData[2][i];
931
932 std::string adjustedChannelName = channelNames[i] + channelNameSuffix;
933 printf("%s \t%s\t\t%s\t\t\t%s\t\t%s \t%s \t\t%s\n",
934 adjustedChannelName.c_str(),
935 ltDataMsg.c_str(),
936 btDataMsg.c_str(),
937 gtDataMsg.c_str(),
938 code.c_str(),
939 threshold.c_str(),
940 current.c_str());
941 }
942 }
943
main()944 int main() {
945 dumpPowerStatsTimes();
946 dumpAcpmStats();
947 dumpPowerSupplyStats();
948 dumpMaxFg();
949 dumpPowerSupplyDock();
950 dumpLogBufferTcpm();
951 dumpTcpc();
952 dumpPdEngine();
953 dumpEusbRepeater();
954 dumpWc68();
955 dumpLn8411();
956 dumpBatteryHealth();
957 dumpBatteryDefend();
958 dumpChg();
959 dumpChgUserDebug();
960 dumpBatteryEeprom();
961 dumpChargerStats();
962 dumpWlcLogs();
963 dumpGvoteables();
964 dumpMitigation();
965 dumpMitigationStats();
966 dumpMitigationDirs();
967 dumpIrqDurationCounts();
968 }
969
970