blob: 776a67bc7da523d0d65238fac64641b4561b83c0 [file] [log] [blame]
/*
* Copyright 2010, Intel Corporation
*
* This file is part of PowerTOP
*
* This program file is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program in a file named COPYING; if not, write to the
* Free Software Foundation, Inc,
* 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
* or just google for it.
*
* Authors:
* Arjan van de Ven <arjan@linux.intel.com>
* Peter Anvin
*/
#include <map>
#include <string.h>
#include <iostream>
#include <utility>
#include <iostream>
#include <fstream>
#include <string>
#include <ctype.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "lib.h"
#ifndef HAVE_NO_PCI
extern "C" {
#include <pci/pci.h>
}
#endif
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <locale.h>
#include <libintl.h>
#include <limits>
#include <math.h>
#include <ncurses.h>
static int kallsyms_read = 0;
double percentage(double F)
{
F = F * 100.0;
// if (F > 100.0)
// F = 100.0;
if (F < 0.0)
F = 0.0;
return F;
}
char *hz_to_human(unsigned long hz, char *buffer, int digits)
{
unsigned long long Hz;
buffer[0] = 0;
Hz = hz;
/* default: just put the Number in */
sprintf(buffer,"%9lli", Hz);
if (Hz>1000) {
if (digits == 2)
sprintf(buffer, "%4lli MHz", (Hz+500)/1000);
else
sprintf(buffer, "%6lli MHz", (Hz+500)/1000);
}
if (Hz>1500000) {
if (digits == 2)
sprintf(buffer, "%4.2f GHz", (Hz+5000.0)/1000000);
else
sprintf(buffer, "%3.1f GHz", (Hz+5000.0)/1000000);
}
return buffer;
}
using namespace std;
map<unsigned long, string> kallsyms;
static void read_kallsyms(void)
{
ifstream file;
char line[1024];
kallsyms_read = 1;
file.open("/proc/kallsyms", ios::in);
while (file) {
char *c = NULL, *c2 = NULL;
unsigned long address = 0;
memset(line, 0, 1024);
file.getline(line, 1024);
c = strchr(line, ' ');
if (!c)
continue;
*c = 0;
c2 = c + 1;
if (*c2) c2++;
if (*c2) c2++;
address = strtoull(line, NULL, 16);
c = strchr(c2, '\t');
if (c)
*c = 0;
if (address != 0)
kallsyms[address] = c2;
}
file.close();
}
const char *kernel_function(uint64_t address)
{
const char *c;
if (!kallsyms_read)
read_kallsyms();
c = kallsyms[address].c_str();
if (!c)
return "";
return c;
}
static int _max_cpu;
int get_max_cpu(void)
{
return _max_cpu;
}
void set_max_cpu(int cpu)
{
if (cpu > _max_cpu)
_max_cpu = cpu;
}
void write_sysfs(const string &filename, const string &value)
{
ofstream file;
file.open(filename.c_str(), ios::out);
if (!file)
return;
try
{
file << value;
file.close();
} catch (std::exception &exc) {
return;
}
}
int read_sysfs(const string &filename, bool *ok)
{
ifstream file;
int i;
file.open(filename.c_str(), ios::in);
if (!file) {
if (ok)
*ok = false;
return 0;
}
try
{
file >> i;
if (ok)
*ok = true;
} catch (std::exception &exc) {
if (ok)
*ok = false;
i = 0;
}
file.close();
return i;
}
string read_sysfs_string(const string &filename)
{
ifstream file;
char content[4096];
char *c;
file.open(filename.c_str(), ios::in);
if (!file)
return "";
try
{
file.getline(content, 4096);
file.close();
c = strchr(content, '\n');
if (c)
*c = 0;
} catch (std::exception &exc) {
file.close();
return "";
}
return content;
}
string read_sysfs_string(const char *format, const char *param)
{
ifstream file;
char content[4096];
char *c;
char filename[8192];
snprintf(filename, 8191, format, param);
file.open(filename, ios::in);
if (!file)
return "";
try
{
file.getline(content, 4096);
file.close();
c = strchr(content, '\n');
if (c)
*c = 0;
} catch (std::exception &exc) {
file.close();
return "";
}
return content;
}
void format_watts(double W, char *buffer, unsigned int len)
{
buffer[0] = 0;
char buf[32];
sprintf(buffer, _("%7sW"), fmt_prefix(W, buf));
if (W < 0.0001)
sprintf(buffer, _(" 0 mW"));
while (mbstowcs(NULL,buffer,len) < len)
strcat(buffer, " ");
}
#ifndef HAVE_NO_PCI
static struct pci_access *pci_access;
char *pci_id_to_name(uint16_t vendor, uint16_t device, char *buffer, int len)
{
char *ret;
buffer[0] = 0;
if (!pci_access) {
pci_access = pci_alloc();
pci_init(pci_access);
}
ret = pci_lookup_name(pci_access, buffer, len, PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE, vendor, device);
return ret;
}
void end_pci_access(void)
{
if (pci_access)
pci_free_name_list(pci_access);
}
#else
char *pci_id_to_name(uint16_t vendor, uint16_t device, char *buffer, int len)
{
return NULL;
}
void end_pci_access(void)
{
}
#endif /* HAVE_NO_PCI */
int utf_ok = -1;
/* pretty print numbers while limiting the precision */
char *fmt_prefix(double n, char *buf)
{
static const char prefixes[] = "yzafpnum kMGTPEZY";
char tmpbuf[16];
int omag, npfx;
char *p, *q, pfx, *c;
int i;
if (utf_ok == -1) {
char *g;
g = getenv("LANG");
if (g && strstr(g, "UTF-8"))
utf_ok = 1;
else
utf_ok = 0;
}
p = buf;
*p = ' ';
if (n < 0.0) {
*p = '-';
n = -n;
p++;
}
snprintf(tmpbuf, sizeof tmpbuf, "%.2e", n);
c = strchr(tmpbuf, 'e');
if (!c) {
sprintf(buf, "NaN");
return buf;
}
omag = atoi(c + 1);
npfx = ((omag + 27) / 3) - (27/3);
omag = (omag + 27) % 3;
q = tmpbuf;
if (omag == 2)
omag = -1;
for (i = 0; i < 3; i++) {
while (!isdigit(*q))
q++;
*p++ = *q++;
if (i == omag)
*p++ = '.';
}
*p++ = ' ';
pfx = prefixes[npfx + 8];
if (pfx == ' ') {
/* do nothing */
} else if (pfx == 'u' && utf_ok > 0) {
strcpy(p, "ยต"); /* Mu is a multibyte sequence */
while (*p)
p++;
} else {
*p++ = pfx;
}
*p = '\0';
return buf;
}
static map<string, string> pretty_prints;
static int pretty_print_init = 0;
static void init_pretty_print(void)
{
pretty_prints["[12] i8042"] = _("PS/2 Touchpad / Keyboard / Mouse");
pretty_prints["ahci"] = _("SATA controller");
pretty_prints["usb-device-8087-0020"] = _("Intel built in USB hub");
}
char *pretty_print(const char *str, char *buf, int len)
{
const char *p;
if (!pretty_print_init)
init_pretty_print();
p = pretty_prints[str].c_str();
if (strlen(p) == 0)
p = str;
snprintf(buf, len, "%s", p);
if (len)
buf[len - 1] = 0;
return buf;
}
int equals(double a, double b)
{
return fabs(a - b) <= std::numeric_limits<double>::epsilon();
}
void process_directory(const char *d_name, callback fn)
{
struct dirent *entry;
DIR *dir;
dir = opendir(d_name);
if (!dir)
return;
while (1) {
entry = readdir(dir);
if (!entry)
break;
if (entry->d_name[0] == '.')
continue;
if (strcmp(entry->d_name, "lo")==0)
continue;
fn(entry->d_name);
}
closedir(dir);
}
int get_user_input(char *buf, unsigned sz)
{
fflush(stdout);
echo();
/* Upon successful completion, these functions return OK. Otherwise, they return ERR. */
int ret = getnstr(buf, sz);
noecho();
fflush(stdout);
/* to distinguish between getnstr error and empty line */
return ret || strlen(buf);
}