/******************************************************************************* * Copyright (C) 2010, Linaro * Copyright (C) 2010, IBM Corporation * * This file is part of PowerDebug. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Amit Arora (IBM Corporation) * - initial API and implementation *******************************************************************************/ #include #include "powerdebug.h" int numregulators; int dump; int ticktime=3; /* in seconds */ int init_regulator_ds(void) { DIR *regdir; struct dirent *item; regdir = opendir("/sys/class/regulator"); if (!regdir) return(1); while((item = readdir(regdir))) { if (strncmp(item->d_name, "regulator", 9)) continue; numregulators++; } closedir(regdir); regulators_info = (struct regulator_info *)malloc(numregulators* sizeof(struct regulator_info)); if (!regulators_info) { fprintf(stderr, "init_regulator_ds: Not enough memory to "); fprintf(stderr, "read information for %d regulators!\n", numregulators); return(1); } return(0); } int read_and_print_sensor_info(int verbose) { DIR *dir, *subdir; int len, found = 0; char filename[PATH_MAX], devpath[PATH_MAX]; char device[PATH_MAX]; struct dirent *item, *subitem; /* 1. readdir /sys/class/hwmon 2. foreach subdir in above, do following a) check if its virtual or physical (check for device) b) for each *type* (in, temp, pwm, fan, curr, power, energy) i> search for "_" (strrchr... check for last) ii> check the *item* depending on type i.e for "in" type items=min, max, input, label for "fan" type items=min,max,input,div,target,label for "pwm" type items=enable, mode, freq for "temp" type items=type, max, min,input,crit,offset,label,lowest,highest, for "curr" type items=max,min,input for "power" type items=average,average_interval,average_min/max, average_highest/lowest, input, input_highest/lowest, accuracy,alarm, cap, cap_min/max for "energy" type items=input for "intrusion" type items=alarm,beep */ sprintf(filename, "%s", "/sys/class/hwmon"); dir = opendir(filename); if (!dir) return errno; while ((item = readdir(dir))) { if (item->d_name[0] == '.') /* skip the hidden files */ continue; found = 1; sprintf(filename, "/sys/class/hwmon/%s", item->d_name); sprintf(devpath, "%s/device", filename); len = readlink(devpath, device, PATH_MAX - 1); if (len < 0) strcpy(devpath, filename); else device[len] = '\0'; subdir = opendir(devpath); printf("\nSensor Information for %s :\n", item->d_name); fflush(stdin); while ((subitem = readdir(subdir))) { if (subitem->d_name[0] == '.') /* skip hidden files */ continue; if(!strncmp(subitem->d_name, "in", 2)) get_sensor_info(devpath, subitem->d_name, "in", verbose); else if (!strncmp(subitem->d_name, "temp", 4)) get_sensor_info(devpath, subitem->d_name, "temp", verbose); else if (!strncmp(subitem->d_name, "fan", 4)) get_sensor_info(devpath, subitem->d_name, "fan", verbose); else if (!strncmp(subitem->d_name, "pwm", 4)) get_sensor_info(devpath, subitem->d_name, "pwm", verbose); } closedir(subdir); } closedir(dir); if(!found && verbose) { printf("Could not find sensor information!"); printf(" Looks like /sys/class/hwmon is empty.\n"); } return 0; } void read_info_from_dirent(struct dirent *ritem, char *str, int idx) { if (!strcmp(ritem->d_name, "name")) strcpy(regulators_info[idx].name, str); if (!strcmp(ritem->d_name, "state")) strcpy(regulators_info[idx].state, str); if (!strcmp(ritem->d_name, "status")) strcpy(regulators_info[idx].status, str); if (!strcmp(ritem->d_name, "type")) strcpy(regulators_info[idx].type, str); if (!strcmp(ritem->d_name, "opmode")) strcpy(regulators_info[idx].opmode, str); if (!strcmp(ritem->d_name, "microvolts")) regulators_info[idx].microvolts = atoi(str); if (!strcmp(ritem->d_name, "min_microvolts")) regulators_info[idx].min_microvolts = atoi(str); if (!strcmp(ritem->d_name, "max_microvolts")) regulators_info[idx].max_microvolts = atoi(str); if (!strcmp(ritem->d_name, "microamps")) regulators_info[idx].microamps = atoi(str); if (!strcmp(ritem->d_name, "min_microamps")) regulators_info[idx].min_microamps = atoi(str); if (!strcmp(ritem->d_name, "max_microamps")) regulators_info[idx].max_microamps = atoi(str); if (!strcmp(ritem->d_name, "requested_microamps")) regulators_info[idx].requested_microamps = atoi(str); if (!strcmp(ritem->d_name, "num_users")) regulators_info[idx].num_users = atoi(str); } int read_regulator_info(void) { FILE *file = NULL; DIR *regdir, *dir; int len, count = 0, ret = 0; char line[1024], filename[1024], *fptr; struct dirent *item, *ritem; regdir = opendir("/sys/class/regulator"); if (!regdir) return(1); while((item = readdir(regdir))) { if (strlen(item->d_name) < 3) continue; if (strncmp(item->d_name, "regulator", 9)) continue; len = sprintf(filename, "/sys/class/regulator/%s", item->d_name); dir = opendir(filename); if (!dir) continue; count++; if (count > numregulators) { ret = 1; goto exit; } strcpy(regulators_info[count-1].name, item->d_name); while((ritem = readdir(dir))) { if (strlen(ritem->d_name) < 3) continue; sprintf(filename + len, "/%s", ritem->d_name); file = fopen(filename, "r"); if (!file) continue; memset(line, 0, 1024); fptr = fgets(line, 1024, file); fclose(file); if (!fptr) continue; read_info_from_dirent(ritem, fptr, count - 1); } exit: closedir(dir); if (ret) break; } closedir(regdir); return ret; } int main(int argc, char **argv) { int c; int firsttime = 1; int regulators = 0, sensors = 0, verbose = 0; /* * Options: * -r, --regulator : regulator * -s, --sensor : sensors * -d, --dump : dump * -v, --verbose : verbose * -V, --version : version * -h, --help : help * no option / default : show usage! */ while (1) { int optindex = 0; static struct option long_options[] = { {"regulator", 0, 0, 'r'}, {"sensor", 0, 0, 's'}, {"dump", 0, 0, 'd'}, {"verbose", 0, 0, 'v'}, {"version", 0, 0, 'V'}, {"help", 0, 0, 'h'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "rsdvVh", long_options, &optindex); if (c == -1) break; switch (c) { case 'r': regulators = 1; break; case 's': sensors = 1; break; case 'd': dump = 1; break; case 'v': verbose = 1; break; case 'V': version(); break; case 'h': usage(argv); break; case '?': fprintf (stderr, "%s: Unknown option %c'.\n", argv[0], optopt); exit(1); default: usage(argv); break; } } /* Need atleast one option specified */ if (!regulators && !sensors) { usage(argv); } init_regulator_ds(); while(1) { int key = 0; struct timeval tval; fd_set readfds; if (!dump) { if(firsttime) { init_curses(); firsttime = 0; } create_windows(); show_header(); } if (regulators) { read_regulator_info(); if (!dump) show_regulator_info(verbose); else print_regulator_info(verbose); } if (sensors) { read_and_print_sensor_info(verbose); } if (dump) break; FD_ZERO(&readfds); FD_SET(0, &readfds); tval.tv_sec = ticktime; tval.tv_usec = (ticktime - tval.tv_sec) * 1000000; key = select(1, &readfds, NULL, NULL, &tval); if (key) { char keychar; int keystroke = fgetc(stdin); if (keystroke == EOF) exit(0); keychar = toupper(keystroke); if (keychar == 'Q') exit(0); if (keychar == 'R') ticktime = 3; } } exit(0); }