diff options
| author | Simon Quigley <tsimonq2@ubuntu.com> | 2017-08-16 04:32:39 -0500 | 
|---|---|---|
| committer | Simon Quigley <tsimonq2@ubuntu.com> | 2017-08-16 04:32:39 -0500 | 
| commit | 9a9db98089717990cd5e0eef529f6bb0819ebe46 (patch) | |
| tree | a9afaabce984d5fe552fa8bf1a9405db9bdd2699 /modules | |
| parent | 69a2124e9a081518297951256eb5c8d72d93361f (diff) | |
New upstream version 0.5.1+git20170815
Diffstat (limited to 'modules')
47 files changed, 6172 insertions, 2429 deletions
| diff --git a/modules/benchmark.c b/modules/benchmark.c index 94997df8..50fddf4d 100644 --- a/modules/benchmark.c +++ b/modules/benchmark.c @@ -36,6 +36,7 @@ void scan_bfsh(gboolean reload);  void scan_cryptohash(gboolean reload);  void scan_fib(gboolean reload);  void scan_nqueens(gboolean reload); +void scan_zlib(gboolean reload);  void scan_gui(gboolean reload);  gchar *callback_fft(); @@ -44,6 +45,7 @@ gchar *callback_bfsh();  gchar *callback_fib();  gchar *callback_cryptohash();  gchar *callback_nqueens(); +gchar *callback_zlib();  gchar *callback_gui();  static ModuleEntry entries[] = { @@ -51,9 +53,12 @@ static ModuleEntry entries[] = {      {N_("CPU CryptoHash"), "cryptohash.png", callback_cryptohash, scan_cryptohash, MODULE_FLAG_NONE},      {N_("CPU Fibonacci"), "nautilus.png", callback_fib, scan_fib, MODULE_FLAG_NONE},      {N_("CPU N-Queens"), "nqueens.png", callback_nqueens, scan_nqueens, MODULE_FLAG_NONE}, +    {N_("CPU Zlib"), "file-roller.png", callback_zlib, scan_zlib, MODULE_FLAG_NONE},      {N_("FPU FFT"), "fft.png", callback_fft, scan_fft, MODULE_FLAG_NONE},      {N_("FPU Raytracing"), "raytrace.png", callback_raytr, scan_raytr, MODULE_FLAG_NONE}, +#if !GTK_CHECK_VERSION(3,0,0)      {N_("GPU Drawing"), "module.png", callback_gui, scan_gui, MODULE_FLAG_NO_REMOTE}, +#endif      {NULL}  }; @@ -187,30 +192,30 @@ static gchar *__benchmark_include_results(gdouble result,  {      GKeyFile *conf;      gchar **machines; -    gchar *path, *results = g_strdup(""), *return_value, *processor_frequency; +    gchar *path, *results = g_strdup(""), *return_value, *processor_frequency, *processor_name;      int i;      conf = g_key_file_new();      path = g_build_filename(g_get_home_dir(), ".hardinfo", "benchmark.conf", NULL);      if (!g_file_test(path, G_FILE_TEST_EXISTS)) { -	DEBUG("local benchmark.conf not found, trying system-wide"); -	g_free(path); -	path = g_build_filename(params.path_data, "benchmark.conf", NULL); +        DEBUG("local benchmark.conf not found, trying system-wide"); +        g_free(path); +        path = g_build_filename(params.path_data, "benchmark.conf", NULL);      }      g_key_file_load_from_file(conf, path, 0, NULL);      machines = g_key_file_get_keys(conf, benchmark, NULL, NULL);      for (i = 0; machines && machines[i]; i++) { -	gchar *value, *cleaned_machine; +        gchar *value, *cleaned_machine; -	value   = g_key_file_get_value(conf, benchmark, machines[i], NULL); -	cleaned_machine = clean_cpuname(machines[i]); -	results = h_strconcat(results, cleaned_machine, "=", value, "\n", NULL); +        value   = g_key_file_get_value(conf, benchmark, machines[i], NULL); +        cleaned_machine = clean_cpuname(machines[i]); +        results = h_strconcat(results, cleaned_machine, "=", value, "\n", NULL); -	g_free(value); -	g_free(cleaned_machine); +        g_free(value); +        g_free(cleaned_machine);      }      g_strfreev(machines); @@ -218,30 +223,37 @@ static gchar *__benchmark_include_results(gdouble result,      g_key_file_free(conf);      if (result > 0.0f) { -        processor_frequency = module_call_method("devices::getProcessorFrequency"); -        return_value = g_strdup_printf(_("[$ShellParam$]\n" -			       	   "Zebra=1\n" -			       	   "OrderType=%d\n" -	       			   "ViewType=3\n" -	       			   "ColumnTitle$Extra1=CPU Clock\n" -			       	   "ColumnTitle$Progress=Results\n" -			       	   "ColumnTitle$TextValue=CPU\n" -			       	   "ShowColumnHeaders=true\n" -	       			   "[%s]\n" -		       		   "<big><b>This Machine</b></big>=%.3f|%s MHz\n" -			       	   "%s"), order_type, benchmark, result, processor_frequency, results); +        processor_name = module_call_method("devices::getProcessorName"); +        processor_frequency = module_call_method("devices::getProcessorFrequencyDesc"); +        return_value = g_strdup_printf("[$ShellParam$]\n" +                       "Zebra=1\n" +                       "OrderType=%d\n" +                       "ViewType=3\n" +                       "ColumnTitle$Extra1=%s\n" /* CPU Clock */ +                       "ColumnTitle$Progress=%s\n" /* Results */ +                       "ColumnTitle$TextValue=%s\n" /* CPU */ +                       "ShowColumnHeaders=true\n" +                       "[%s]\n" +                       "<big><b>%s</b></big>=%.3f|%s\n" +                       "%s", order_type, +                       _("CPU Config"), _("Results"), _("CPU"), +                       benchmark, +                       processor_name, result, processor_frequency, results);          g_free(processor_frequency); +        g_free(processor_name);      } else { -        return_value = g_strdup_printf(_("[$ShellParam$]\n" -			       	   "Zebra=1\n" -			       	   "OrderType=%d\n" -	       			   "ViewType=3\n" -	       			   "ColumnTitle$Extra1=CPU Clock\n" -			       	   "ColumnTitle$Progress=Results\n" -			       	   "ColumnTitle$TextValue=CPU\n" -			       	   "ShowColumnHeaders=true\n" -	       			   "[%s]\n" -			       	   "%s"), order_type, benchmark, results); +        return_value = g_strdup_printf("[$ShellParam$]\n" +                       "Zebra=1\n" +                       "OrderType=%d\n" +                       "ViewType=3\n" +                       "ColumnTitle$Extra1=%s\n" /* CPU Clock */ +                       "ColumnTitle$Progress=%s\n" /* Results */ +                       "ColumnTitle$TextValue=%s\n" /* CPU */ +                       "ShowColumnHeaders=true\n" +                       "[%s]\n%s", +                       order_type, +                       _("CPU Config"), _("Results"), _("CPU"), +                       benchmark, results);      }      return return_value;  } @@ -306,6 +318,12 @@ gchar *callback_fib()  				     "CPU Fibonacci");  } +gchar *callback_zlib() +{ +    return benchmark_include_results(bench_results[BENCHMARK_ZLIB], +				     "CPU Zlib"); +} +  typedef struct _BenchmarkDialog BenchmarkDialog;  struct _BenchmarkDialog {      GtkWidget *dialog; @@ -348,7 +366,7 @@ static gboolean do_benchmark_handler(GIOChannel *source,  static void do_benchmark(void (*benchmark_function)(void), int entry)  {      int old_priority = 0; -     +      if (params.gui_running && !sending_benchmark_results) {         gchar *argv[] = { params.argv0, "-b", entries[entry].name,                           "-m", "benchmark.so", "-a", NULL }; @@ -364,7 +382,7 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)         shell_view_set_enabled(FALSE);         shell_status_update(bench_status); -        +         g_free(bench_status);         bench_image = icon_cache_get_image("benchmark.png"); @@ -388,7 +406,7 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)         benchmark_dialog = g_new0(BenchmarkDialog, 1);         benchmark_dialog->dialog = bench_dialog;         benchmark_dialog->result = -1.0f; -        +         if (!g_path_is_absolute(params.argv0)) {            spawn_flags |= G_SPAWN_SEARCH_PATH;         } @@ -432,7 +450,7 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)            return;         } -        +         gtk_widget_destroy(bench_dialog);         g_free(benchmark_dialog);         shell_status_set_enabled(TRUE); @@ -504,12 +522,20 @@ void scan_fib(gboolean reload)      SCAN_END();  } +void scan_zlib(gboolean reload) +{ +    SCAN_START(); +    do_benchmark(benchmark_zlib, BENCHMARK_ZLIB); +    SCAN_END(); +} +  const gchar *hi_note_func(gint entry)  {      switch (entry) {      case BENCHMARK_CRYPTOHASH:  	return _("Results in MiB/second. Higher is better."); +    case BENCHMARK_ZLIB:      case BENCHMARK_GUI:          return _("Results in HIMarks. Higher is better."); @@ -595,7 +621,7 @@ static gchar *get_benchmark_results()      g_free(machineram);      sending_benchmark_results = FALSE; -     +      return result;  } diff --git a/modules/benchmark/zlib.c b/modules/benchmark/zlib.c new file mode 100644 index 00000000..eeec9d0e --- /dev/null +++ b/modules/benchmark/zlib.c @@ -0,0 +1,71 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2017 Leandro A. F. Pereira <leandro@hardinfo.org> + * + *    This program 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. + * + *    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; if not, write to the Free Software + *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA + */ + +#include <glib.h> +#include <stdlib.h> +#include <zlib.h> + +#include "benchmark.h" + +static gpointer zlib_for(unsigned int start, unsigned int end, void *data, gint thread_number) +{ +    char *compressed; +    uLong bound = compressBound(bound); +    unsigned int i; + +    compressed = malloc(bound); +    if (!compressed) +        return NULL; +     +    for (i = start; i <= end; i++) {  +        char uncompressed[65536]; +        uLong compressedBound = bound; +        uLong destBound = sizeof(uncompressed); + +        compress(compressed, &compressedBound, data, 65536); +        uncompress(uncompressed, &destBound, compressed, compressedBound); +    } + +    free(compressed); +     +    return NULL; +} + +void +benchmark_zlib(void) +{ +    gdouble elapsed = 0; +    gchar *tmpsrc, *bdata_path; +     +    bdata_path = g_build_filename(params.path_data, "benchmark.data", NULL); +    if (!g_file_get_contents(bdata_path, &tmpsrc, NULL, NULL)) { +        g_free(bdata_path); +        return; +    }      +     +    shell_view_set_enabled(FALSE); +    shell_status_update("Running Zlib benchmark..."); +         +    elapsed = benchmark_parallel_for(0, 50000, zlib_for, tmpsrc); +     +    g_free(bdata_path); +    g_free(tmpsrc); + +    gdouble marks = (50000. * 65536.) / (elapsed * 840205128.); +    bench_results[BENCHMARK_ZLIB] = marks; +} diff --git a/modules/computer.c b/modules/computer.c index eda405e8..513d94f5 100644 --- a/modules/computer.c +++ b/modules/computer.c @@ -16,13 +16,14 @@   *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA   */ +#include <config.h> +#include <gtk/gtk.h> +#include <stdarg.h>  #include <stdlib.h>  #include <string.h> -#include <gtk/gtk.h> -#include <config.h> -#include <time.h>  #include <string.h>  #include <sys/stat.h> +#include <time.h>  #include <hardinfo.h>  #include <iconcache.h> @@ -31,21 +32,22 @@  #include <vendor.h>  #include "computer.h" +#include "info.h"  /* Callbacks */ -gchar *callback_summary(); -gchar *callback_os(); -gchar *callback_modules(); -gchar *callback_boots(); -gchar *callback_locales(); -gchar *callback_fs(); -gchar *callback_display(); -gchar *callback_network(); -gchar *callback_users(); -gchar *callback_groups(); -gchar *callback_env_var(); +gchar *callback_summary(void); +gchar *callback_os(void); +gchar *callback_modules(void); +gchar *callback_boots(void); +gchar *callback_locales(void); +gchar *callback_fs(void); +gchar *callback_display(void); +gchar *callback_network(void); +gchar *callback_users(void); +gchar *callback_groups(void); +gchar *callback_env_var(void);  #if GLIB_CHECK_VERSION(2,14,0) -gchar *callback_dev(); +gchar *callback_dev(void);  #endif /* GLIB_CHECK_VERSION(2,14,0) */  /* Scan callbacks */ @@ -81,6 +83,7 @@ static ModuleEntry entries[] = {      {NULL},  }; +  gchar *module_list = NULL;  Computer *computer = NULL; @@ -89,7 +92,7 @@ gchar *hi_more_info(gchar * entry)      gchar *info = moreinfo_lookup_with_prefix("COMP", entry);      if (info) -	return g_strdup(info); +        return g_strdup(info);      return g_strdup_printf("[%s]", entry);  } @@ -99,22 +102,22 @@ gchar *hi_get_field(gchar * field)      gchar *tmp;      if (g_str_equal(field, _("Memory"))) { -	MemoryInfo *mi = computer_get_memory(); -	tmp = g_strdup_printf(_("%dMB (%dMB used)"), mi->total, mi->used); -	g_free(mi); +        MemoryInfo *mi = computer_get_memory(); +        tmp = g_strdup_printf(_("%dMB (%dMB used)"), mi->total, mi->used); +        g_free(mi);      } else if (g_str_equal(field, _("Uptime"))) { -	tmp = computer_get_formatted_uptime(); +        tmp = computer_get_formatted_uptime();      } else if (g_str_equal(field, _("Date/Time"))) { -	time_t t = time(NULL); +        time_t t = time(NULL); -	tmp = g_new0(gchar, 64); -	strftime(tmp, 64, "%c", localtime(&t)); +        tmp = g_new0(gchar, 64); +        strftime(tmp, 64, "%c", localtime(&t));      } else if (g_str_equal(field, _("Load Average"))) { -	tmp = computer_get_formatted_loadavg(); +        tmp = computer_get_formatted_loadavg();      } else if (g_str_equal(field, _("Available entropy in /dev/random"))) { -	tmp = computer_get_entropy_avail(); +        tmp = computer_get_entropy_avail();      } else { -	tmp = g_strdup_printf("Unknown field: %s", field); +        tmp = g_strdup_printf("Unknown field: %s", field);      }      return tmp;  } @@ -189,7 +192,7 @@ static gchar *dev_list = NULL;  void scan_dev(gboolean reload)  {      SCAN_START(); -     +      int i;      struct {         gchar *compiler_name; @@ -198,8 +201,13 @@ void scan_dev(gboolean reload)         gboolean stdout;      } detect_lang[] = {         { N_("Scripting Languages"), NULL, FALSE }, -       { N_("CPython"), "python -V", "\\d+\\.\\d+\\.\\d+", TRUE }, +       { N_("Gambas3 (gbr3)"), "gbr3 --version", "\\d+\\.\\d+\\.\\d+", TRUE }, +       { N_("Python"), "python -V", "\\d+\\.\\d+\\.\\d+", FALSE }, +       { N_("Python2"), "python2 -V", "\\d+\\.\\d+\\.\\d+", FALSE }, +       { N_("Python3"), "python3 -V", "\\d+\\.\\d+\\.\\d+", TRUE },         { N_("Perl"), "perl -v", "\\d+\\.\\d+\\.\\d+", TRUE }, +       { N_("Perl6 (VM)"), "perl6 -v", "(?<=This is ).*", TRUE }, +       { N_("Perl6"), "perl6 -v", "(?<=implementing Perl )\\w*\\.\\w*", TRUE },         { N_("PHP"), "php --version", "\\d+\\.\\d+\\.\\S+", TRUE},         { N_("Ruby"), "ruby --version", "\\d+\\.\\d+\\.\\d+", TRUE },         { N_("Bash"), "bash --version", "\\d+\\.\\d+\\.\\S+", TRUE}, @@ -207,6 +215,7 @@ void scan_dev(gboolean reload)         { N_("C (GCC)"), "gcc -v", "\\d+\\.\\d+\\.\\d+", FALSE },         { N_("C (Clang)"), "clang -v", "\\d+\\.\\d+", FALSE },         { N_("D (dmd)"), "dmd --help", "\\d+\\.\\d+", TRUE }, +       { N_("Gambas3 (gbc3)"), "gbc3 --version", "\\d+\\.\\d+\\.\\d+", FALSE },         { N_("Java"), "javac -version", "\\d+\\.\\d+\\.\\d+", FALSE },         { N_("CSharp (Mono, old)"), "mcs --version", "\\d+\\.\\d+\\.\\d+\\.\\d+", TRUE },         { N_("CSharp (Mono)"), "gmcs --version", "\\d+\\.\\d+\\.\\d+\\.\\d+", TRUE }, @@ -216,36 +225,38 @@ void scan_dev(gboolean reload)         { N_("Go"), "go version", "\\d+\\.\\d+\\.?\\d* ", TRUE },         { N_("Tools"), NULL, FALSE },         { N_("make"), "make --version", "\\d+\\.\\d+", TRUE }, -       { N_("GDB"), "gdb --version", "\\d+\\.\\S+", TRUE }, +       { N_("GDB"), "gdb --version", "(?<=^GNU gdb ).*", TRUE },         { N_("strace"), "strace -V", "\\d+\\.\\d+\\.?\\d*", TRUE },         { N_("valgrind"), "valgrind --version", "\\d+\\.\\d+\\.\\S+", TRUE },         { N_("QMake"), "qmake --version", "\\d+\\.\\S+", TRUE},         { N_("CMake"), "cmake --version", "\\d+\\.\\d+\\.?\\d*", TRUE}, +       { N_("Gambas3 IDE"), "gambas3 --version", "\\d+\\.\\d+\\.\\d+", FALSE },      }; -     +      g_free(dev_list); -     +      dev_list = g_strdup(""); -     +      for (i = 0; i < G_N_ELEMENTS(detect_lang); i++) {         gchar *version = NULL; -       gchar *output; +       gchar *output, *ignored;         gchar *temp;         GRegex *regex;         GMatchInfo *match_info;         gboolean found; -        +         if (!detect_lang[i].regex) { -            dev_list = h_strdup_cprintf("[%s]\n", dev_list, detect_lang[i].compiler_name); +            dev_list = h_strdup_cprintf("[%s]\n", dev_list, _(detect_lang[i].compiler_name));              continue;         } -        +         if (detect_lang[i].stdout) { -            found = g_spawn_command_line_sync(detect_lang[i].version_command, &output, NULL, NULL, NULL); +            found = g_spawn_command_line_sync(detect_lang[i].version_command, &output, &ignored, NULL, NULL);         } else { -            found = g_spawn_command_line_sync(detect_lang[i].version_command, NULL, &output, NULL, NULL); +            found = g_spawn_command_line_sync(detect_lang[i].version_command, &ignored, &output, NULL, NULL);         } -        +       g_free(ignored); +         if (found) {             regex = g_regex_new(detect_lang[i].regex, 0, 0, NULL); @@ -253,41 +264,131 @@ void scan_dev(gboolean reload)             if (g_match_info_matches(match_info)) {                 version = g_match_info_fetch(match_info, 0);             } -            +             g_match_info_free(match_info);             g_regex_unref(regex);             g_free(output);         } -        -       if (version) { -           dev_list = h_strdup_cprintf("%s=%s\n", dev_list, detect_lang[i].compiler_name, version); -           g_free(version); -       } else { -           dev_list = h_strdup_cprintf(_("%s=Not found\n"), dev_list, detect_lang[i].compiler_name); -       } -        + +       if (version == NULL) +           version = strdup(_("Not found")); + +       dev_list = h_strdup_cprintf("%s=%s\n", dev_list, detect_lang[i].compiler_name, version); +       g_free(version); +         temp = g_strdup_printf(_("Detecting version: %s"),                                detect_lang[i].compiler_name);         shell_status_update(temp);         g_free(temp);      } -     +      SCAN_END();  } -gchar *callback_dev() +gchar *callback_dev(void)  { -    return g_strdup_printf(_("[$ShellParam$]\n" -			   "ColumnTitle$TextValue=Program\n" -			   "ColumnTitle$Value=Version\n" -			   "ShowColumnHeaders=true\n" -                           "%s"), dev_list); +    return g_strdup_printf( +                "[$ShellParam$]\n" +                "ColumnTitle$TextValue=%s\n" /* Program */ +                "ColumnTitle$Value=%s\n" /* Version */ +                "ShowColumnHeaders=true\n" +                "%s", +                _("Program"), _("Version"), +                dev_list);  }  #endif /* GLIB_CHECK_VERSION(2,14,0) */ +static gchar *detect_machine_type(void) +{ +    GDir *dir; +    gchar *chassis; + +    if (g_file_get_contents("/sys/devices/virtual/dmi/id/chassis_type", &chassis, NULL, NULL)) { +        static const char *types[] = { +            N_("Invalid chassis type (0)"), +            N_("Unknown chassis type"), /* 1 is "Other", but not helpful in HardInfo */ +            N_("Unknown chassis type"), +            N_("Desktop"), +            N_("Low-profile Desktop"), +            N_("Pizza Box"), +            N_("Mini Tower"), +            N_("Tower"), +            N_("Portable"), +            N_("Laptop"), +            N_("Notebook"), +            N_("Handheld"), +            N_("Docking Station"), +            N_("All-in-one"), +            N_("Subnotebook"), +            N_("Space-saving"), +            N_("Lunch Box"), +            N_("Main Server Chassis"), +            N_("Expansion Chassis"), +            N_("Sub Chassis"), +            N_("Bus Expansion Chassis"), +            N_("Peripheral Chassis"), +            N_("RAID Chassis"), +            N_("Rack Mount Chassis"), +            N_("Sealed-case PC"), +        }; +        int chassis_type = atoi(idle_free(chassis)); + +        if (chassis_type >= 0 && chassis_type < G_N_ELEMENTS(types)) +            return g_strdup(_(types[chassis_type])); +    } + +    if (g_file_test("/proc/pmu/info", G_FILE_TEST_EXISTS)) +        return g_strdup(_("Laptop")); + +    dir = g_dir_open("/proc/acpi/battery", 0, NULL); +    if (dir) { +        const gchar *name = g_dir_read_name(dir); + +        g_dir_close(dir); + +        if (name) +            return g_strdup(_("Laptop")); +    } + +    dir = g_dir_open("/sys/class/power_supply", 0, NULL); +    if (dir) { +        const gchar *name; + +        while ((name = g_dir_read_name(dir))) { +            gchar *contents; +            gchar type[PATH_MAX]; +            int r; + +            r = snprintf(type, sizeof(type), "%s/%s/type", +                         "/sys/class/power_supply", name); +            if (r < 0 || r > PATH_MAX) +                continue; + +            if (g_file_get_contents(type, &contents, NULL, NULL)) { +                if (g_str_has_prefix(contents, "Battery")) { +                    g_free(contents); +                    g_dir_close(dir); + +                    return g_strdup(_("Laptop")); +                } + +                g_free(contents); +            } +        } + +        g_dir_close(dir); +    } + +    /* FIXME: check if batteries are found using /proc/apm */ + +    /* FIXME: use dmidecode if available to get chassis type */ + +    return g_strdup(_("Unknown physical machine type")); +} +  /* Table based off imvirt by Thomas Liske <liske@ibh.de>     Copyright (c) 2008 IBH IT-Service GmbH under GPLv2. */ -gchar *computer_get_virtualization() +gchar *computer_get_virtualization(void)  {      gboolean found = FALSE;      gint i, j; @@ -324,18 +425,18 @@ gchar *computer_get_virtualization()          { " hypervisor", "Virtual (hypervisor present)"} ,          { NULL }      }; -     +      DEBUG("Detecting virtual machine");      if (g_file_test("/proc/xen", G_FILE_TEST_EXISTS)) {           DEBUG("/proc/xen found; assuming Xen");           return g_strdup("Xen");      } -     +      for (i = 0; files[i+1]; i++) {           gchar buffer[512];           FILE *file; -          +           if ((file = fopen(files[i], "r"))) {                while (!found && fgets(buffer, 512, file)) {                    for (j = 0; vm_types[j+1].str; j++) { @@ -345,200 +446,191 @@ gchar *computer_get_virtualization()                        }                    }                } -               +                fclose(file); -               +                if (found) {                    DEBUG("%s found (by reading file %s)",                          vm_types[j].vmtype, files[i]);                    return g_strdup(vm_types[j].vmtype);                }           } -          +      } -     +      DEBUG("no virtual machine detected; assuming physical machine"); -     -    return g_strdup(_("Physical machine")); -} - -gchar *callback_summary() -{ -    gchar *processor_name, *alsa_cards; -    gchar *input_devices, *printers; -    gchar *storage_devices, *summary; -    gchar *virt; -     -    processor_name  = module_call_method("devices::getProcessorName"); -    alsa_cards      = computer_get_alsacards(computer); -    input_devices   = module_call_method("devices::getInputDevices"); -    printers        = module_call_method("devices::getPrinters"); -    storage_devices = module_call_method("devices::getStorageDevices"); -    virt            = computer_get_virtualization(); - -    summary = g_strdup_printf(_("[$ShellParam$]\n" -			      "UpdateInterval$Memory=1000\n" -			      "UpdateInterval$Date/Time=1000\n" -			      "#ReloadInterval=5000\n" -			      "[Computer]\n" -			      "Processor=%s\n" -			      "Memory=...\n" -			      "Machine Type=%s\n" -			      "Operating System=%s\n" -			      "User Name=%s\n" -			      "Date/Time=...\n" -			      "[Display]\n" -			      "Resolution=%dx%d pixels\n" -			      "OpenGL Renderer=%s\n" -			      "X11 Vendor=%s\n" -			      "\n%s\n" -			      "[Input Devices]\n%s\n" -			      "\n%s\n" -			      "\n%s\n"), -			      processor_name, -			      virt, -			      computer->os->distro, -			      computer->os->username, -			      computer->display->width, -			      computer->display->height, -			      computer->display->ogl_renderer, -			      computer->display->vendor, -			      alsa_cards, -			      input_devices, printers, storage_devices); - -    g_free(processor_name); -    g_free(alsa_cards); -    g_free(input_devices); -    g_free(printers); -    g_free(storage_devices); -    g_free(virt); - -    return summary; -} - -gchar *callback_os() -{ -    return g_strdup_printf(_("[$ShellParam$]\n" -			   "UpdateInterval$Uptime=10000\n" -			   "UpdateInterval$Load Average=1000\n" -			   "UpdateInterval$Available entropy in /dev/random=1000\n" -			   "[Version]\n" -			   "Kernel=%s\n" -			   "Version=%s\n" -			   "C Library=%s\n" -			   "Distribution=%s\n" -			   "[Current Session]\n" -			   "Computer Name=%s\n" -			   "User Name=%s\n" -			   "#Language=%s\n" -			   "Home Directory=%s\n" -			   "Desktop Environment=%s\n" -			   "[Misc]\n" -			   "Uptime=...\n" -			   "Load Average=...\n" -			   "Available entropy in /dev/random=..."), -			   computer->os->kernel, -			   computer->os->kernel_version, -			   computer->os->libc, -			   computer->os->distro, -			   computer->os->hostname, -			   computer->os->username, -			   computer->os->language, -			   computer->os->homedir, -			   computer->os->desktop); -} - -gchar *callback_modules() -{ -    return g_strdup_printf(_("[Loaded Modules]\n" -			   "%s" -			   "[$ShellParam$]\n" -			   "ViewType=1\n" -			   "ColumnTitle$TextValue=Name\n" -			   "ColumnTitle$Value=Description\n" -			   "ShowColumnHeaders=true\n"), module_list); -} - -gchar *callback_boots() -{ -    return g_strdup_printf(_("[$ShellParam$]\n" -			   "ColumnTitle$TextValue=Date & Time\n" -			   "ColumnTitle$Value=Kernel Version\n" -			   "ShowColumnHeaders=true\n" -			   "\n" -			   "%s"), computer->os->boots); -} - -gchar *callback_locales() -{ -    return g_strdup_printf(_("[$ShellParam$]\n" -			   "ViewType=1\n" -			   "ColumnTitle$TextValue=Language Code\n" -			   "ColumnTitle$Value=Name\n" -			   "ShowColumnHeaders=true\n" -			   "[Available Languages]\n" -			   "%s"), computer->os->languages); -} - -gchar *callback_fs() -{ -    return g_strdup_printf(_("[$ShellParam$]\n" -			   "ViewType=4\n" -			   "ReloadInterval=5000\n" -			   "Zebra=1\n" -			   "NormalizePercentage=false\n" -			   "ColumnTitle$Extra1=Mount Point\n" -			   "ColumnTitle$Progress=Usage\n" -			   "ColumnTitle$TextValue=Device\n" -			   "ShowColumnHeaders=true\n" -			   "[Mounted File Systems]\n%s\n"), fs_list); -} - -gchar *callback_display() -{ -    return g_strdup_printf(_("[Display]\n" -			   "Resolution=%dx%d pixels\n" -			   "Vendor=%s\n" -			   "Version=%s\n" -			   "[Monitors]\n" -			   "%s" -			   "[Extensions]\n" -			   "%s" -			   "[OpenGL]\n" -			   "Vendor=%s\n" -			   "Renderer=%s\n" -			   "Version=%s\n" -			   "Direct Rendering=%s\n"), -			   computer->display->width, -			   computer->display->height, -			   computer->display->vendor, -			   computer->display->version, -			   computer->display->monitors, -			   computer->display->extensions, -			   computer->display->ogl_vendor, -			   computer->display->ogl_renderer, -			   computer->display->ogl_version, -			   computer->display->dri ? _("Y_es") : _("No")); -} - -gchar *callback_users() -{ -    return g_strdup_printf("[$ShellParam$]\n" -			   "ReloadInterval=10000\n" -			   "ViewType=1\n" -			   "[Users]\n" -			   "%s\n", users); -} - -gchar *callback_groups() -{ -    return g_strdup_printf(_("[$ShellParam$]\n" -			   "ReloadInterval=10000\n" -			   "ColumnTitle$TextValue=Name\n" -			   "ColumnTitle$Value=Group ID\n" -			   "ShowColumnHeaders=true\n" -			   "[Groups]\n" -			   "%s\n"), groups); + +    return detect_machine_type(); +} + +gchar *callback_summary(void) +{ +    struct Info *info = info_new(); + +    info_add_group(info, _("Computer"), +        info_field_printf(_("Processor"), "%s", +            module_call_method("devices::getProcessorName")), +        info_field_update(_("Memory"), 1000), +        info_field_printf(_("Machine Type"), "%s", +            computer_get_virtualization()), +        info_field(_("Operating System"), computer->os->distro), +        info_field(_("User Name"), computer->os->username), +        info_field_update(_("Date/Time"), 1000), +        info_field_last()); + +    info_add_group(info, _("Display"), +        info_field_printf(_("Resolution"), _(/* label for resolution */ "%dx%d pixels"), +            computer->display->width, computer->display->height), +        info_field(_("OpenGL Renderer"), computer->display->ogl_renderer), +        info_field(_("X11 Vendor"), computer->display->vendor), +        info_field_last()); + +    info_add_computed_group(info, _("Audio Devices"), +        idle_free(computer_get_alsacards(computer))); +    info_add_computed_group(info, _("Input Devices"), +        idle_free(module_call_method("devices::getInputDevices"))); +    info_add_computed_group(info, _("Printers"), +        idle_free(module_call_method("devices::getPrinters"))); +    info_add_computed_group(info, _("Storage"), +        idle_free(module_call_method("devices::getStorageDevices"))); + +    return info_flatten(info); +} + +gchar *callback_os(void) +{ +    struct Info *info = info_new(); + +    info_add_group(info, _("Version"), +        info_field(_("Kernel"), computer->os->kernel), +        info_field(_("Version"), computer->os->kernel_version), +        info_field(_("C Library"), computer->os->libc), +        info_field(_("Distribution"), computer->os->distro), +        info_field_last()); + +    info_add_group(info, _("Current Session"), +        info_field(_("Computer Name"), computer->os->hostname), +        info_field(_("User Name"), computer->os->username), +        info_field(_("Language"), computer->os->language), +        info_field(_("Home Directory"), computer->os->homedir), +        info_field_last()); + +    info_add_group(info, _("Misc"), +        info_field_update(_("Uptime"), 1000), +        info_field_update(_("Load Average"), 10000), +        info_field_update(_("Available entropy in /dev/random"), 1000), +        info_field_last()); + +    return info_flatten(info); +} + +gchar *callback_modules(void) +{ +    struct Info *info = info_new(); + +    info_add_computed_group(info, _("Loaded Modules"), module_list); + +    info_set_column_title(info, "TextValue", _("Name")); +    info_set_column_title(info, "Value", _("Description")); +    info_set_column_headers_visible(info, TRUE); +    info_set_view_type(info, SHELL_VIEW_DUAL); + +    return info_flatten(info); +} + +gchar *callback_boots(void) +{ +    struct Info *info = info_new(); + +    info_add_computed_group(info, _("Boots"), computer->os->boots); + +    info_set_column_title(info, "TextValue", _("Date & Time")); +    info_set_column_title(info, "Value", _("Kernel Version")); +    info_set_column_headers_visible(info, TRUE); + +    return info_flatten(info); +} + +gchar *callback_locales(void) +{ +    struct Info *info = info_new(); + +    info_add_computed_group(info, _("Available Languages"), computer->os->languages); + +    info_set_column_title(info, "TextValue", _("Language Code")); +    info_set_column_title(info, "Value", _("Name")); +    info_set_view_type(info, SHELL_VIEW_DUAL); +    info_set_column_headers_visible(info, TRUE); + +    return info_flatten(info); +} + +gchar *callback_fs(void) +{ +    struct Info *info = info_new(); + +    info_add_computed_group(info, _("Mounted File Systems"), fs_list); + +    info_set_column_title(info, "Extra1", _("Mount Point")); +    info_set_column_title(info, "Progress", _("Usage")); +    info_set_column_title(info, "TextValue", _("Device")); +    info_set_column_headers_visible(info, TRUE); +    info_set_view_type(info, SHELL_VIEW_PROGRESS_DUAL); +    info_set_zebra_visible(info, TRUE); +    info_set_normalize_percentage(info, FALSE); + +    return info_flatten(info); +} + +gchar *callback_display(void) +{ +    struct Info *info = info_new(); + +    info_add_group(info, _("Display"), +        info_field_printf(_("Resolution"), _(/* resolution WxH unit */ "%dx%d pixels"), +                computer->display->width, computer->display->height), +        info_field(_("Vendor"), computer->display->vendor), +        info_field(_("Version"), computer->display->version), +        info_field_last()); + +    info_add_computed_group(info, _("Monitors"), computer->display->monitors); + +    info_add_group(info, _("OpenGL"), +        info_field(_("Vendor"), computer->display->ogl_vendor), +        info_field(_("Renderer"), computer->display->ogl_renderer), +        info_field(_("Version"), computer->display->ogl_version), +        info_field(_("Direct Rendering"), +            computer->display->dri ? _("Yes") : _("No")), +        info_field_last()); + +    info_add_computed_group(info, _("Extensions"), computer->display->extensions); + +    return info_flatten(info); +} + +gchar *callback_users(void) +{ +    struct Info *info = info_new(); + +    info_add_computed_group(info, _("Users"), users); +    info_set_view_type(info, SHELL_VIEW_DUAL); +    info_set_reload_interval(info, 10000); + +    return info_flatten(info); +} + +gchar *callback_groups(void) +{ +    struct Info *info = info_new(); + +    info_add_computed_group(info, _("Group"), groups); + +    info_set_column_title(info, "TextValue", _("Name")); +    info_set_column_title(info, "Value", _("Group ID")); +    info_set_column_headers_visible(info, TRUE); +    info_set_reload_interval(info, 10000); + +    return info_flatten(info);  }  gchar *get_os_kernel(void) @@ -569,16 +661,16 @@ gchar *get_display_summary(void)  gchar *get_kernel_module_description(gchar *module)  {      gchar *description; -     +      if (!_module_hash_table) {          scan_modules(FALSE);      } -     +      description = g_hash_table_lookup(_module_hash_table, module);      if (!description) {          return NULL;      } -     +      return g_strdup(description);  } @@ -587,19 +679,19 @@ gchar *get_audio_cards(void)      if (!computer->alsa) {        computer->alsa = computer_get_alsainfo();      } -     +      return computer_get_alsacards(computer);  }  ShellModuleMethod *hi_exported_methods(void)  {      static ShellModuleMethod m[] = { -	{"getOSKernel", get_os_kernel}, -	{"getOS", get_os}, -	{"getDisplaySummary", get_display_summary}, -	{"getAudioCards", get_audio_cards}, -	{"getKernelModuleDescription", get_kernel_module_description}, -	{NULL} +        {"getOSKernel", get_os_kernel}, +        {"getOS", get_os}, +        {"getDisplaySummary", get_display_summary}, +        {"getAudioCards", get_audio_cards}, +        {"getKernelModuleDescription", get_kernel_module_description}, +        {NULL}      };      return m; @@ -629,30 +721,34 @@ gchar **hi_module_get_dependencies(void)  gchar *hi_module_get_summary(void)  { -    return g_strdup("[Operating System]\n" +    return g_strdup_printf("[%s]\n"                      "Icon=os.png\n"                      "Method=computer::getOS\n" -                    "[CPU]\n" +                    "[%s]\n"                      "Icon=processor.png\n" -                    "Method=devices::getProcessorName\n" -                    "[RAM]\n" +                    "Method=devices::getProcessorNameAndDesc\n" +                    "[%s]\n"                      "Icon=memory.png\n"                      "Method=devices::getMemoryTotal\n" -                    "[Motherboard]\n" +                    "[%s]\n"                      "Icon=module.png\n"                      "Method=devices::getMotherboard\n" -                    "[Graphics]\n" +                    "[%s]\n"                      "Icon=monitor.png\n"                      "Method=computer::getDisplaySummary\n" -                    "[Storage]\n" +                    "[%s]\n"                      "Icon=hdd.png\n"                      "Method=devices::getStorageDevices\n" -                    "[Printers]\n" +                    "[%s]\n"                      "Icon=printer.png\n"                      "Method=devices::getPrinters\n" -                    "[Audio]\n" +                    "[%s]\n"                      "Icon=audio.png\n" -                    "Method=computer::getAudioCards\n"); +                    "Method=computer::getAudioCards\n", +                    _("Operating System"), +                    _("CPU"), _("RAM"), _("Motherboard"), _("Graphics"), +                    _("Storage"), _("Printers"), _("Audio") +                    );  }  void hi_module_deinit(void) @@ -672,7 +768,7 @@ void hi_module_deinit(void)          g_free(computer->os->boots);          g_free(computer->os);      } -     +      if (computer->display) {          g_free(computer->display->ogl_vendor);          g_free(computer->display->ogl_renderer); @@ -684,15 +780,15 @@ void hi_module_deinit(void)          g_free(computer->display->monitors);          g_free(computer->display);      } -     +      if (computer->alsa) {          g_slist_free(computer->alsa->cards);          g_free(computer->alsa);      } -     +      g_free(computer->date_time);      g_free(computer); -     +      moreinfo_del_with_prefix("COMP");  } @@ -704,11 +800,11 @@ void hi_module_init(void)  ModuleAbout *hi_module_get_about(void)  {      static ModuleAbout ma[] = { -	{ -	 .author = "Leandro A. F. Pereira", -	 .description = N_("Gathers high-level computer information"), -	 .version = VERSION, -	 .license = "GNU GPL version 2"} +    { +     .author = "Leandro A. F. Pereira", +     .description = N_("Gathers high-level computer information"), +     .version = VERSION, +     .license = "GNU GPL version 2"}      };      return ma; diff --git a/modules/computer/alsa.c b/modules/computer/alsa.c index e1e7b946..00c1fceb 100644 --- a/modules/computer/alsa.c +++ b/modules/computer/alsa.c @@ -23,16 +23,16 @@ gchar *  computer_get_alsacards(Computer * computer)  {      GSList *p; -    gchar *tmp = g_strdup(_("[Audio Devices]\n")); +    gchar *tmp = g_strdup_printf("[%s]\n", _("Audio Devices"));      gint n = 0;      if (computer->alsa) { -	for (p = computer->alsa->cards; p; p = p->next) { -	    AlsaCard *ac = (AlsaCard *) p->data; +        for (p = computer->alsa->cards; p; p = p->next) { +            AlsaCard *ac = (AlsaCard *) p->data; -	    tmp = h_strdup_cprintf(_("Audio Adapter#%d=%s\n"), -	                           tmp, ++n, ac->friendly_name); -	} +            tmp = h_strdup_cprintf("%s#%d=%s\n", tmp, +                        _("Audio Adapter"), ++n, ac->friendly_name); +        }      }      return tmp; @@ -48,22 +48,22 @@ computer_get_alsainfo(void)      cards = fopen("/proc/asound/cards", "r");      if (!cards) -	return NULL; +        return NULL;      ai = g_new0(AlsaInfo, 1);      while (fgets(buffer, 128, cards)) { -	gchar **tmp; +        gchar **tmp; -	ac = g_new0(AlsaCard, 1); +        ac = g_new0(AlsaCard, 1); -	tmp = g_strsplit(buffer, ":", 0); +        tmp = g_strsplit(buffer, ":", 0); -	ac->friendly_name = g_strdup(tmp[1]); -	ai->cards = g_slist_append(ai->cards, ac); +        ac->friendly_name = g_strdup(tmp[1]); +        ai->cards = g_slist_append(ai->cards, ac); -	g_strfreev(tmp); -	(void)fgets(buffer, 128, cards);	/* skip next line */ +        g_strfreev(tmp); +        (void)fgets(buffer, 128, cards);  /* skip next line */      }      fclose(cards); diff --git a/modules/computer/boots.c b/modules/computer/boots.c index 478e89ac..d8a6d32a 100644 --- a/modules/computer/boots.c +++ b/modules/computer/boots.c @@ -30,22 +30,22 @@ scan_boots_real(void)      scan_os(FALSE);      if (!computer->os->boots) -      computer->os->boots = g_strdup(_("[Boots]\n")); +      computer->os->boots = g_strdup_printf("[%s]\n", _("Boots"));      else        return; -     +      last = popen("last", "r");      if (last) {        while (fgets(buffer, 256, last)) {          if (strstr(buffer, "system boot")) {            gchar **tmp, *buf = buffer; -           +            strend(buffer, '\n'); -           +            while (*buf) {              if (*buf == ' ' && *(buf + 1) == ' ') {                memmove(buf, buf + 1, strlen(buf) + 1); -               +                buf--;              } else {                buf++; @@ -53,13 +53,14 @@ scan_boots_real(void)            }            tmp = g_strsplit(buffer, " ", 0); -          computer->os->boots = h_strdup_cprintf("\n%s %s %s %s=%s|%s", -                                                computer->os->boots, -						tmp[4], tmp[5], tmp[6], tmp[7], tmp[3], tmp[8]); +          computer->os->boots = +            h_strdup_cprintf("\n%s %s %s %s=%s|%s", +              computer->os->boots, +              tmp[4], tmp[5], tmp[6], tmp[7], tmp[3], tmp[8]);            g_strfreev(tmp);          }        } -       +        pclose(last);      }  } diff --git a/modules/computer/environment.c b/modules/computer/environment.c index 2a8d235c..dc0fb6f3 100644 --- a/modules/computer/environment.c +++ b/modules/computer/environment.c @@ -23,19 +23,19 @@ static gchar *_env = NULL;  void scan_env_var(gboolean reload)  {      SCAN_START(); -     +      gchar **envlist;      gint i; -     +      g_free(_env); -     -    _env = g_strdup(_("[Environment Variables]\n")); + +    _env = g_strdup_printf("[%s]\n", _("Environment Variables") );      for (i = 0, envlist = g_listenv(); envlist[i]; i++) {        _env = h_strdup_cprintf("%s=%s\n", _env,                                envlist[i], g_getenv(envlist[i]));      }      g_strfreev(envlist); -     +      SCAN_END();  } diff --git a/modules/computer/filesystem.c b/modules/computer/filesystem.c index a7162777..397dc636 100644 --- a/modules/computer/filesystem.c +++ b/modules/computer/filesystem.c @@ -16,8 +16,8 @@   *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA   *   * Some code from xfce4-mount-plugin, version 0.4.3 - *  Copyright (C) 2005 Jean-Baptiste jb_dul@yahoo.com  - *  Distributed under the terms of GNU GPL 2.  + *  Copyright (C) 2005 Jean-Baptiste jb_dul@yahoo.com + *  Distributed under the terms of GNU GPL 2.   */  #include <string.h> @@ -41,62 +41,64 @@ scan_filesystems(void)      mtab = fopen("/etc/mtab", "r");      if (!mtab) -	return; +        return;      while (fgets(buf, 1024, mtab)) { -	gfloat size, used, avail; -	gchar **tmp; - -	tmp = g_strsplit(buf, " ", 0); -	if (!statfs(tmp[1], &sfs)) { -		gfloat use_ratio; - -		size = (float) sfs.f_bsize * (float) sfs.f_blocks; -		avail = (float) sfs.f_bsize * (float) sfs.f_bavail; -		used = size - avail; - -		if (size == 0.0f) { -			continue; -		} - -		if (avail == 0.0f) { -			use_ratio = 100.0f; -		} else { -			use_ratio = 100.0f * (used / size); -		} - -		gchar *strsize = size_human_readable(size), -		      *stravail = size_human_readable(avail), -	  	      *strused = size_human_readable(used); - -		gchar *strhash; -		 -		strreplacechr(tmp[0], "#", '_'); -		strhash = g_strdup_printf("[%s]\n" -					  "Filesystem=%s\n" -					  "Mounted As=%s\n" -					  "Mount Point=%s\n" -					  "Size=%s\n" -					  "Used=%s\n" -					  "Available=%s\n", -					  tmp[0], -					  tmp[2], -					  strstr(tmp[3], "rw") ? "Read-Write" : -					  "Read-Only", tmp[1], strsize, strused, -					  stravail); -               gchar *key = g_strdup_printf("FS%d", ++count); -		moreinfo_add_with_prefix("COMP", key, strhash); -		g_free(key); - -		fs_list = h_strdup_cprintf("$FS%d$%s=%.2f %% (%s of %s)|%s\n", -					  fs_list, -					  count, tmp[0], use_ratio, stravail, strsize, tmp[1]); - -		g_free(strsize); -		g_free(stravail); -		g_free(strused); -	} -	g_strfreev(tmp); +        gfloat size, used, avail; +        gchar **tmp; + +        tmp = g_strsplit(buf, " ", 0); +        if (!statfs(tmp[1], &sfs)) { +                gfloat use_ratio; + +                size = (float) sfs.f_bsize * (float) sfs.f_blocks; +                avail = (float) sfs.f_bsize * (float) sfs.f_bavail; +                used = size - avail; + +                if (size == 0.0f) { +                        continue; +                } + +                if (avail == 0.0f) { +                        use_ratio = 100.0f; +                } else { +                        use_ratio = 100.0f * (used / size); +                } + +                gchar *strsize = size_human_readable(size), +                      *stravail = size_human_readable(avail), +                      *strused = size_human_readable(used); + +                gchar *strhash; + +                strreplacechr(tmp[0], "#", '_'); +                strhash = g_strdup_printf("[%s]\n" +                        "%s=%s\n" +                        "%s=%s\n" +                        "%s=%s\n" +                        "%s=%s\n" +                        "%s=%s\n" +                        "%s=%s\n", +                        tmp[0], /* path */ +                        _("Filesystem"), tmp[2], +                        _("Mounted As"), ( strstr(tmp[3], "rw") != NULL) ? _("Read-Write") : _("Read-Only"), +                        _("Mount Point"), tmp[1], +                        _("Size"), strsize, +                        _("Used"), strused, +                        _("Available"), stravail); +                gchar *key = g_strdup_printf("FS%d", ++count); +                moreinfo_add_with_prefix("COMP", key, strhash); +                g_free(key); + +                fs_list = h_strdup_cprintf("$FS%d$%s=%.2f %% (%s of %s)|%s\n", +                                          fs_list, +                                          count, tmp[0], use_ratio, stravail, strsize, tmp[1]); + +                g_free(strsize); +                g_free(stravail); +                g_free(strused); +        } +        g_strfreev(tmp);      }      fclose(mtab); diff --git a/modules/computer/languages.c b/modules/computer/languages.c index 5877c41c..d4681839 100644 --- a/modules/computer/languages.c +++ b/modules/computer/languages.c @@ -20,6 +20,7 @@  #include "hardinfo.h"  #include "computer.h" +#include "cpu_util.h" /* for UNKIFNULL() */  void  scan_languages(OperatingSystem * os) @@ -67,43 +68,64 @@ scan_languages(OperatingSystem * os)  	    g_strfreev(tmp);  	} else { -	    gchar *currlocale; - -	    retval = h_strdup_cprintf("$%s$%s=%s\n", retval, name, name, title); - -#define FIELD(f) f ? f : "(Unknown)" -	    currlocale = g_strdup_printf("[Locale Information]\n" -					 "Name=%s (%s)\n" -					 "Source=%s\n" -					 "Address=%s\n" -					 "Email=%s\n" -					 "Language=%s\n" -					 "Territory=%s\n" -					 "Revision=%s\n" -					 "Date=%s\n" -					 "Codeset=%s\n", -					 name, FIELD(title), -					 FIELD(source), FIELD(address), -					 FIELD(email), FIELD(language), -					 FIELD(territory), FIELD(revision), -					 FIELD(date), FIELD(codeset)); -#undef FIELD - -           moreinfo_add_with_prefix("COMP", name, currlocale); - -	    g_free(title); -	    g_free(source); -	    g_free(address); -	    g_free(email); -	    g_free(language); -	    g_free(territory); -	    g_free(revision); -	    g_free(date); -	    g_free(codeset); -	     -	    title = source = address = email = language = territory = \ -	        revision = date = codeset = NULL; -	} +        gchar *currlocale; + +        retval = h_strdup_cprintf("$%s$%s=%s\n", retval, name, name, title); + +        UNKIFNULL(title); +        UNKIFNULL(source); +        UNKIFNULL(address); +        UNKIFNULL(email); +        UNKIFNULL(language); +        UNKIFNULL(territory); +        UNKIFNULL(revision); +        UNKIFNULL(date); +        UNKIFNULL(codeset); + +        /* values may have & */ +        title = hardinfo_clean_value(title, 1); +        source = hardinfo_clean_value(source, 1); +        address = hardinfo_clean_value(address, 1); +        email = hardinfo_clean_value(email, 1); +        language = hardinfo_clean_value(language, 1); +        territory = hardinfo_clean_value(territory, 1); + +        currlocale = g_strdup_printf("[%s]\n" +        /* Name */     "%s=%s (%s)\n" +        /* Source */   "%s=%s\n" +        /* Address */  "%s=%s\n" +        /* Email */    "%s=%s\n" +        /* Language */ "%s=%s\n" +        /* Territory */"%s=%s\n" +        /* Revision */ "%s=%s\n" +        /* Date */     "%s=%s\n" +        /* Codeset */  "%s=%s\n", +                     _("Locale Information"), +                     _("Name"), name, title, +                     _("Source"), source, +                     _("Address"), address, +                     _("E-mail"), email, +                     _("Language"), language, +                     _("Territory"), territory, +                     _("Revision"), revision, +                     _("Date"), date, +                     _("Codeset"), codeset ); + +        moreinfo_add_with_prefix("COMP", name, currlocale); + +        g_free(title); +        g_free(source); +        g_free(address); +        g_free(email); +        g_free(language); +        g_free(territory); +        g_free(revision); +        g_free(date); +        g_free(codeset); + +        title = source = address = email = language = territory = \ +            revision = date = codeset = NULL; +    }      }      fclose(locale); diff --git a/modules/computer/memory.c b/modules/computer/memory.c index 3d320e8a..dc8599c2 100644 --- a/modules/computer/memory.c +++ b/modules/computer/memory.c @@ -28,23 +28,26 @@ computer_get_memory(void)      procmem = fopen("/proc/meminfo", "r");      if (!procmem) -	return NULL; +        return NULL;      mi = g_new0(MemoryInfo, 1);      while (fgets(buffer, 128, procmem)) { -	gchar **tmp = g_strsplit(buffer, ":", 2); - -	tmp[0] = g_strstrip(tmp[0]); -	tmp[1] = g_strstrip(tmp[1]); - -	get_int("MemTotal", mi->total); -	get_int("MemFree", mi->free); -	get_int("Cached", mi->cached); - -	g_strfreev(tmp); +        gchar **tmp = g_strsplit(buffer, ":", 2); +        if (tmp[1] == NULL) { +            g_strfreev(tmp); +            continue; +        } +        tmp[0] = g_strstrip(tmp[0]); +        tmp[1] = g_strstrip(tmp[1]); + +        get_int("MemTotal", mi->total); +        get_int("MemFree", mi->free); +        get_int("Cached", mi->cached); + +        g_strfreev(tmp);      }      fclose(procmem); -     +      mi->used = mi->total - mi->free;      mi->total  /= 1000; diff --git a/modules/computer/modules.c b/modules/computer/modules.c index bbc05f42..df876e3a 100644 --- a/modules/computer/modules.c +++ b/modules/computer/modules.c @@ -20,6 +20,7 @@  #include "hardinfo.h"  #include "computer.h" +#include "cpu_util.h" /* for STRIFNULL() */  #define GET_STR(field_name,ptr)      					\    if (!ptr && strstr(tmp[0], field_name)) {				\ @@ -42,7 +43,7 @@ scan_modules_do(void)      }      g_free(module_list); -     +      module_list = NULL;      moreinfo_del_with_prefix("COMP:MOD"); @@ -51,7 +52,7 @@ scan_modules_do(void)          return;      lsmod = popen(lsmod_path, "r");      if (!lsmod) { -        g_free(lsmod_path);  +        g_free(lsmod_path);  	return;      } @@ -99,7 +100,7 @@ scan_modules_do(void)  	   remove_quotes(license); */  	/* old modutils displays <none> when there's no value for a -	   given field; this is not desirable in the module name  +	   given field; this is not desirable in the module name  	   display, so change it to an empty string */  	if (description && g_str_equal(description, "<none>")) {  	    g_free(description); @@ -121,38 +122,45 @@ scan_modules_do(void)  				      modname,  				      description ? description : ""); -#define NONE_IF_NULL(var) (var) ? (var) : "N/A" - -	/* create the module information string */ -	strmodule = g_strdup_printf("[Module Information]\n" -				    "Path=%s\n" -				    "Used Memory=%.2fKiB\n" -				    "[Description]\n" -				    "Name=%s\n" -				    "Description=%s\n" -				    "Version Magic=%s\n" -				    "[Copyright]\n" -				    "Author=%s\n" -				    "License=%s\n", -				    NONE_IF_NULL(filename), -				    memory / 1024.0, -				    modname, -				    NONE_IF_NULL(description), -				    NONE_IF_NULL(vermagic), -				    NONE_IF_NULL(author), -				    NONE_IF_NULL(license)); - -	/* if there are dependencies, append them to that string */ -	if (deps && strlen(deps)) { -	    gchar **tmp = g_strsplit(deps, ",", 0); - -	    strmodule = h_strconcat(strmodule, -                                    "\n[Dependencies]\n", -                                    g_strjoinv("=\n", tmp), -                                    "=\n", NULL); -	    g_strfreev(tmp); -	    g_free(deps); -	} +    STRIFNULL(filename, _("(Not available)") ); +    STRIFNULL(description, _("(Not available)") ); +    STRIFNULL(vermagic, _("(Not available)") ); +    STRIFNULL(author, _("(Not available)") ); +    STRIFNULL(license, _("(Not available)") ); + +    /* create the module information string */ +    strmodule = g_strdup_printf("[%s]\n" +                        "%s=%s\n" +                        "%s=%.2f %s\n" +                        "[%s]\n" +                        "%s=%s\n" +                        "%s=%s\n" +                        "%s=%s\n" +                        "[%s]\n" +                        "%s=%s\n" +                        "%s=%s\n", +                        _("Module Information"), +                        _("Path"), filename, +                        _("Used Memory"), memory / 1024.0, _("KiB"), +                        _("Description"), +                        _("Name"), modname, +                        _("Description"), description, +                        _("Version Magic"), vermagic, +                        _("Copyright"), +                        _("Author"), author, +                        _("License"), license ); + +    /* if there are dependencies, append them to that string */ +    if (deps && strlen(deps)) { +        gchar **tmp = g_strsplit(deps, ",", 0); + +        strmodule = h_strconcat(strmodule, +                                "\n[", _("Dependencies"), "]\n", +                                g_strjoinv("=\n", tmp), +                                "=\n", NULL); +        g_strfreev(tmp); +        g_free(deps); +    }  	moreinfo_add_with_prefix("COMP", hashkey, strmodule);  	g_free(hashkey); @@ -164,6 +172,6 @@ scan_modules_do(void)  	g_free(filename);      }      pclose(lsmod); -     +      g_free(lsmod_path);  } diff --git a/modules/computer/os.c b/modules/computer/os.c index 3caf6c26..a8886f64 100644 --- a/modules/computer/os.c +++ b/modules/computer/os.c @@ -16,6 +16,7 @@   *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA   */ +#include <gdk/gdkx.h>  #include <string.h>  #include <sys/utsname.h>  #include "hardinfo.h" @@ -24,219 +25,350 @@  static gchar *  get_libc_version(void)  { -    FILE *libc; -    gchar buf[256], *tmp, *p; -    char *libc_paths[] = { -		"/lib/ld-uClibc.so.0", "/lib64/ld-uClibc.so.0", -		"/lib/libc.so.6", "/lib64/libc.so.6" -	}; -	int i; -	 -	for (i=0; i < 4; i++) { -		if (g_file_test(libc_paths[i], G_FILE_TEST_EXISTS)) break; -	} -	switch (i) { -		case 0: case 1: return g_strdup("uClibc Library"); -		case 2: case 3: break; // gnu libc, continue processing -		default: goto err; -	} - -    libc = popen(libc_paths[i], "r"); -    if (!libc) goto err; - -    (void)fgets(buf, 256, libc); -    if (pclose(libc)) goto err; - -    tmp = strstr(buf, "version "); -    if (!tmp) goto err; - -    p = strchr(tmp, ','); -    if (p) *p = '\0'; -    else goto err; - -    return g_strdup_printf(_("GNU C Library version %s (%sstable)"), -                           strchr(tmp, ' ') + 1, -                           strstr(buf, " stable ") ? "" : _("un")); -  err: +    static const struct { +        const char *test_cmd; +        const char *match_str; +        const char *lib_name; +        gboolean try_ver_str; +        gboolean use_stderr; +    } libs[] = { +        { "ldd --version", "GLIBC", N_("GNU C Library"), TRUE, FALSE}, +        { "ldd --version", "GNU libc", N_("GNU C Library"), TRUE, FALSE}, +        { "ldconfig -V", "GLIBC", N_("GNU C Library"), TRUE, FALSE}, +        { "ldconfig -V", "GNU libc", N_("GNU C Library"), TRUE, FALSE}, +        { "ldconfig -v", "uClibc", N_("uClibc or uClibc-ng"), FALSE, FALSE}, +        { "diet", "diet version", N_("diet libc"), TRUE, TRUE}, +        { NULL } +    }; +    int i; + +    for (i = 0; libs[i].test_cmd; i++) { +        gboolean spawned; +        gchar *out, *err, *p; + +        spawned = g_spawn_command_line_sync(libs[i].test_cmd, +            &out, &err, NULL, NULL); +        if (!spawned) +            continue; + +        if (libs[i].use_stderr) { +            p = strend(idle_free(err), '\n'); +            g_free(out); +        } else { +            p = strend(idle_free(out), '\n'); +            g_free(err); +        } + +        if (!p || !strstr(p, libs[i].match_str)) +            continue; + +        if (libs[i].try_ver_str) { +            /* skip the first word, likely "ldconfig" or name of utility */ +            const gchar *ver_str = strchr(p, ' '); + +            if (ver_str) { +                return g_strdup_printf("%s / %s", _(libs[i].lib_name), +                    ver_str + 1); +            } +        } + +	return g_strdup(_(libs[i].lib_name)); +    } +      return g_strdup(_("Unknown"));  } -#include <gdk/gdkx.h> +static gchar *detect_kde_version(void) +{ +    const gchar *cmd; +    const gchar *tmp = g_getenv("KDE_SESSION_VERSION"); +    gchar *out; +    gboolean spawned; + +    if (tmp && tmp[0] == '4') { +        cmd = "kwin --version"; +    } else { +        cmd = "kcontrol --version"; +    } + +    spawned = g_spawn_command_line_sync(cmd, &out, NULL, NULL, NULL); +    if (!spawned) +        return NULL; + +    tmp = strstr(idle_free(out), "KDE: "); +    return tmp ? g_strdup(tmp + strlen("KDE: ")) : NULL; +} + +static gchar * +detect_gnome_version(void) +{ +    gchar *tmp; +    gchar *out; +    gboolean spawned; + +    spawned = g_spawn_command_line_sync( +        "gnome-shell --version", &out, NULL, NULL, NULL); +    if (spawned) { +        tmp = strstr(idle_free(out), _("GNOME Shell ")); + +        if (tmp) { +            tmp += strlen(_("GNOME Shell ")); +            return g_strdup_printf("GNOME %s", strend(tmp, '\n')); +        } +    } + +    spawned = g_spawn_command_line_sync( +        "gnome-about --gnome-version", &out, NULL, NULL, NULL); +    if (spawned) { +        tmp = strstr(idle_free(out), _("Version: ")); + +        if (tmp) { +            tmp += strlen(_("Version: ")); +            return g_strdup_printf("GNOME %s", strend(tmp, '\n')); +        } +    } + +    return NULL; +} -void -detect_desktop_environment(OperatingSystem * os) +static gchar * +detect_window_manager(void)  { -    const gchar *tmp = g_getenv("GNOME_DESKTOP_SESSION_ID"); -    FILE *version; -    char vers[16]; +    GdkScreen *screen = gdk_screen_get_default(); +    const gchar *windowman; +    const gchar *curdesktop; + +    if (!screen || !GDK_IS_SCREEN(screen)) +        return NULL; + +    windowman = gdk_x11_screen_get_window_manager_name(screen); +    if (g_str_equal(windowman, "Xfwm4")) +        return g_strdup("XFCE 4"); + +    curdesktop = g_getenv("XDG_CURRENT_DESKTOP"); +    if (curdesktop) { +        const gchar *desksession = g_getenv("DESKTOP_SESSION"); + +        if (desksession && !g_str_equal(curdesktop, desksession)) +            return g_strdup(desksession); +    } + +    return g_strdup_printf(_("Unknown (Window Manager: %s)"), windowman); +} + +static gchar * +desktop_with_session_type(const gchar *desktop_env) +{ +    const char *tmp; + +    tmp = g_getenv("XDG_SESSION_TYPE");      if (tmp) { -	/* FIXME: this might not be true, as the gnome-panel in path -	   may not be the one that's running. -	   see where the user's running panel is and run *that* to -	   obtain the version. */ -	version = popen("gnome-about --gnome-version", "r"); -	if (version) { -	    (void)fscanf(version, _("Version: %s"), vers); -	    if (pclose(version)) -	        goto unknown; -	} else { -	    goto unknown; -	} - -	os->desktop = g_strdup_printf("GNOME %s", vers); -    } else if (g_getenv("KDE_FULL_SESSION")) { - -	if (g_getenv("KDE_SESSION_VERSION") && strstr(g_getenv("KDE_SESSION_VERSION"),(gchar *)"4")) { -	    version = popen("kwin --version", "r"); -	} else { -	    version = popen("kcontrol --version", "r"); -	} - -	if (version) { -	    char buf[32]; - -	    (void)fgets(buf, 32, version); - -	    (void)fscanf(version, "KDE: %s", vers); -	    if (pclose(version)) -	        goto unknown; -	} else { -	    goto unknown; -	} - -	os->desktop = g_strdup_printf("KDE %s", vers); -    } else { -      unknown: -        os->desktop = NULL; -         -	if (!g_getenv("DISPLAY")) { -	    os->desktop = g_strdup(_("Terminal")); -	} else { -            GdkScreen *screen = gdk_screen_get_default(); - -            if (screen && GDK_IS_SCREEN(screen)) { -              const gchar *windowman; - -              windowman = gdk_x11_screen_get_window_manager_name(screen); -              if (g_str_equal(windowman, "Xfwm4")) { -                  /* FIXME: check if xprop -root | grep XFCE_DESKTOP_WINDOW is defined */ -                  os->desktop = g_strdup("XFCE 4"); -              } else if ((tmp = g_getenv("XDG_CURRENT_DESKTOP"))) { -                  os->desktop = g_strdup(tmp); -                  if ((tmp = g_getenv("DESKTOP_SESSION")) && !g_str_equal(os->desktop, tmp)) { -                      g_free(os->desktop); -                      os->desktop = g_strdup(tmp); -                  } -              } - -              if (!os->desktop) { -                  os->desktop = g_strdup_printf(_("Unknown (Window Manager: %s)"), -                                                windowman); -              } -            } else { -                  os->desktop = g_strdup(_("Unknown")); -            } -	} +        if (!g_str_equal(tmp, "unspecified")) +            return g_strdup_printf(_(/*/{desktop environment} on {session type}*/ "%s on %s"), desktop_env, tmp); +    } + +    return g_strdup(desktop_env); +} + +static gchar * +detect_xdg_environment(const gchar *env_var) +{ +    const gchar *tmp; + +    tmp = g_getenv(env_var); +    if (!tmp) +        return NULL; + +    if (g_str_equal(tmp, "GNOME") || g_str_equal(tmp, "gnome")) { +        gchar *maybe_gnome = detect_gnome_version(); + +        if (maybe_gnome) +            return maybe_gnome;      } +    if (g_str_equal(tmp, "KDE") || g_str_equal(tmp, "kde")) { +        gchar *maybe_kde = detect_kde_version(); + +        if (maybe_kde) +            return maybe_kde; +    } + +    return g_strdup(tmp); +} + +static gchar * +detect_desktop_environment(void) +{ +    const gchar *tmp; +    gchar *windowman; + +    windowman = detect_xdg_environment("XDG_CURRENT_DESKTOP"); +    if (windowman) +        return windowman; +    windowman = detect_xdg_environment("XDG_SESSION_DESKTOP"); +    if (windowman) +        return windowman; + +    tmp = g_getenv("KDE_FULL_SESSION"); +    if (tmp) { +        gchar *maybe_kde = detect_kde_version(); + +        if (maybe_kde) +            return maybe_kde; +    } +    tmp = g_getenv("GNOME_DESKTOP_SESSION_ID"); +    if (tmp) { +        gchar *maybe_gnome = detect_gnome_version(); + +        if (maybe_gnome) +            return maybe_gnome; +    } + +    windowman = detect_window_manager(); +    if (windowman) +        return windowman; + +    if (!g_getenv("DISPLAY")) +        return g_strdup(_("Terminal")); + +    return g_strdup(_("Unknown"));  }  gchar *  computer_get_entropy_avail(void)  { +    gchar tab_entropy_fstr[][32] = { +      N_(/*/bits of entropy for rng (0)*/              "(None or not available)"), +      N_(/*/bits of entropy for rng (low/poor value)*/  "%d bits (low)"), +      N_(/*/bits of entropy for rng (medium value)*/    "%d bits (medium)"), +      N_(/*/bits of entropy for rng (high/good value)*/ "%d bits (healthy)") +    };      gint bits = h_sysfs_read_int("/proc/sys/kernel/random", "entropy_avail"); -    if (bits < 200) -        return g_strdup_printf("%d bits (low)", bits); -    if (bits < 3000) -        return g_strdup_printf("%d bits (medium)", bits); -    return g_strdup_printf("%d bits (healthy)", bits); +    if (bits > 3000) return g_strdup_printf(_(tab_entropy_fstr[3]), bits); +    if (bits > 200)  return g_strdup_printf(_(tab_entropy_fstr[2]), bits); +    if (bits > 1)    return g_strdup_printf(_(tab_entropy_fstr[1]), bits); +    return g_strdup_printf(_(tab_entropy_fstr[0]), bits);  } -OperatingSystem * -computer_get_os(void) +gchar * +computer_get_language(void)  { -    struct utsname utsbuf; -    OperatingSystem *os; +    gchar *tab_lang_env[] = +        { "LANGUAGE", "LANG", "LC_ALL", "LC_MESSAGES", NULL }; +    gchar *lc = NULL, *env = NULL, *ret = NULL; +    gint i = 0; + +    lc = setlocale(LC_ALL, NULL); + +    while (tab_lang_env[i] != NULL) { +        env = g_strdup( g_getenv(tab_lang_env[i]) ); +        if (env != NULL)  break; +        i++; +    } + +    if (env != NULL) +        if (lc != NULL) +            ret = g_strdup_printf("%s (%s)", lc, env); +        else +            ret = g_strdup_printf("%s", env); +    else +        if (lc != NULL) +            ret = g_strdup_printf("%s", lc); + +    if (ret == NULL) +        ret = g_strdup( _("(Unknown)") ); + +    return ret; +} + +static gchar * +detect_distro(void) +{ +    static const struct { +        const gchar *file; +        const gchar *codename; +        const gchar *override; +    } distro_db[] = { +#define DB_PREFIX "/etc/" +        { DB_PREFIX "arch-release", "arch", "Arch Linux" }, +        { DB_PREFIX "fatdog-version", "fatdog" }, +        { DB_PREFIX "debian_version", "deb" }, +        { DB_PREFIX "slackware-version", "slk" }, +        { DB_PREFIX "mandrake-release", "mdk" }, +        { DB_PREFIX "mandriva-release", "mdv" }, +        { DB_PREFIX "fedora-release", "fdra" }, +        { DB_PREFIX "coas", "coas" }, +        { DB_PREFIX "environment.corel", "corel"}, +        { DB_PREFIX "gentoo-release", "gnt" }, +        { DB_PREFIX "conectiva-release", "cnc" }, +        { DB_PREFIX "versão-conectiva", "cnc" }, +        { DB_PREFIX "turbolinux-release", "tl" }, +        { DB_PREFIX "yellowdog-release", "yd" }, +        { DB_PREFIX "sabayon-release", "sbn" }, +        { DB_PREFIX "arch-release", "arch" }, +        { DB_PREFIX "enlisy-release", "enlsy" }, +        { DB_PREFIX "SuSE-release", "suse" }, +        { DB_PREFIX "sun-release", "sun" }, +        { DB_PREFIX "zenwalk-version", "zen" }, +        { DB_PREFIX "DISTRO_SPECS", "ppy", "Puppy Linux" }, +        { DB_PREFIX "puppyversion", "ppy", "Puppy Linux" }, +        { DB_PREFIX "distro-release", "fl" }, +        { DB_PREFIX "vine-release", "vine" }, +        { DB_PREFIX "PartedMagic-version", "pmag" }, +         /* +         * RedHat must be the *last* one to be checked, since +         * some distros (like Mandrake) includes a redhat-relase +         * file too. +         */ +        { DB_PREFIX "redhat-release", "rh" }, +#undef DB_PREFIX +        { NULL, NULL } +    }; +    gchar *contents;      int i; -    os = g_new0(OperatingSystem, 1); +    if (g_spawn_command_line_sync("lsb_release -d", &contents, NULL, NULL, NULL)) { +        gchar *tmp = strstr(idle_free(contents), "Description:\t"); -    /* Attempt to get the Distribution name; try using /etc/lsb-release first, -       then doing the legacy method (checking for /etc/$DISTRO-release files) */ -    if (g_file_test("/etc/lsb-release", G_FILE_TEST_EXISTS)) { -	FILE *release; -	gchar buffer[128]; +        if (tmp) +            return g_strdup(tmp + strlen("Description:\t")); +    } -	release = popen("lsb_release -d", "r"); -	if (release) { -            (void)fgets(buffer, 128, release); -            pclose(release); +    for (i = 0; distro_db[i].file; i++) { +        if (!g_file_get_contents(distro_db[i].file, &contents, NULL, NULL)) +            continue; -            os->distro = buffer; -            os->distro = g_strdup(os->distro + strlen("Description:\t")); +        if (distro_db[i].override) { +            g_free(contents); +            return g_strdup(distro_db[i].override);          } -    } else if (g_file_test("/etc/arch-release", G_FILE_TEST_EXISTS)) { -        os->distrocode = g_strdup("arch"); -        os->distro = g_strdup("Arch Linux"); -    } else { -        for (i = 0;; i++) { -            if (distro_db[i].file == NULL) { -                os->distrocode = g_strdup("unk"); -                os->distro = g_strdup(_("Unknown distribution")); -                break; -            } -            if (g_file_test(distro_db[i].file, G_FILE_TEST_EXISTS)) { -                FILE *distro_ver; -                char buf[128]; - -                distro_ver = fopen(distro_db[i].file, "r"); -                if (distro_ver) { -                    (void)fgets(buf, 128, distro_ver); -                    fclose(distro_ver); -                } else { -                    continue; -                } - -                buf[strlen(buf) - 1] = 0; - -                if (!os->distro) { -                    /* -                     * HACK: Some Debian systems doesn't include -                     * the distribuition name in /etc/debian_release, -                     * so add them here. -                     */ -                    if (!strncmp(distro_db[i].codename, "deb", 3) && -                        ((buf[0] >= '0' && buf[0] <= '9') || buf[0] != 'D')) { -                        os->distro = g_strdup_printf -                            ("Debian GNU/Linux %s", buf); -                    } else { -                        os->distro = g_strdup(buf); -                    } -                } - -                if (g_str_equal(distro_db[i].codename, "ppy")) { -                  gchar *tmp; -                    tmp = g_strdup_printf("Puppy Linux"); -                  g_free(os->distro); -                  os->distro = tmp; -                } - -                if (g_str_equal(distro_db[i].codename, "fatdog")) { -                  gchar *tmp; -                    tmp = g_strdup_printf("Fatdog64 [%.10s]", os->distro); -                  g_free(os->distro); -                  os->distro = tmp; -                } - -                os->distrocode = g_strdup(distro_db[i].codename); - -                break; -            } +        if (g_str_equal(distro_db[i].codename, "deb")) { +            /* HACK: Some Debian systems doesn't include the distribuition +             * name in /etc/debian_release, so add them here. */ +            if (isdigit(contents[0]) || contents[0] != 'D') +                return g_strdup_printf("Debian GNU/Linux %s", (char*)idle_free(contents));          } + +        if (g_str_equal(distro_db[i].codename, "fatdog")) +            return g_strdup_printf("Fatdog64 [%.10s]", (char*)idle_free(contents)); + +        return contents;      } -    os->distro = g_strstrip(os->distro); +    return g_strdup(_("Unknown")); +} + +OperatingSystem * +computer_get_os(void) +{ +    struct utsname utsbuf; +    OperatingSystem *os; +    int i; + +    os = g_new0(OperatingSystem, 1); + +    os->distro = g_strstrip(detect_distro());      /* Kernel and hostname info */      uname(&utsbuf); @@ -244,13 +376,16 @@ computer_get_os(void)      os->kernel = g_strdup_printf("%s %s (%s)", utsbuf.sysname,  				 utsbuf.release, utsbuf.machine);      os->hostname = g_strdup(utsbuf.nodename); -    os->language = g_strdup(g_getenv("LC_MESSAGES")); +    os->language = computer_get_language();      os->homedir = g_strdup(g_get_home_dir());      os->username = g_strdup_printf("%s (%s)",  				   g_get_user_name(), g_get_real_name());      os->libc = get_libc_version();      scan_languages(os); -    detect_desktop_environment(os); + +    os->desktop = detect_desktop_environment(); +    if (os->desktop) +        os->desktop = desktop_with_session_type(idle_free(os->desktop));      os->entropy_avail = computer_get_entropy_avail(); diff --git a/modules/computer/uptime.c b/modules/computer/uptime.c index 8eb563fa..5f0f1942 100644 --- a/modules/computer/uptime.c +++ b/modules/computer/uptime.c @@ -26,11 +26,11 @@ computer_get_uptime(void)      gulong minutes;      if ((procuptime = fopen("/proc/uptime", "r")) != NULL) { -	(void)fscanf(procuptime, "%lu", &minutes); -	ui->minutes = minutes / 60; -	fclose(procuptime); +        (void)fscanf(procuptime, "%lu", &minutes); +        ui->minutes = minutes / 60; +        fclose(procuptime);      } else { -	return NULL; +        return NULL;      }      ui->hours = ui->minutes / 60; @@ -45,32 +45,27 @@ gchar *  computer_get_formatted_uptime()  {      UptimeInfo *ui; -    gchar *tmp; +    const gchar *days_fmt, *hours_fmt, *minutes_fmt; +    gchar *full_fmt = NULL, *ret = NULL;      ui = computer_get_uptime(); -    /* FIXME: Use ngettext */ -#define plural(x) ((x > 1) ? "s" : "") +    days_fmt = ngettext("%d day", "%d days", ui->days); +    hours_fmt = ngettext("%d hour", "%d hours", ui->hours); +    minutes_fmt = ngettext("%d minute", "%d minutes", ui->minutes);      if (ui->days < 1) { -	if (ui->hours < 1) { -	    tmp = -		g_strdup_printf("%d minute%s", ui->minutes, -				plural(ui->minutes)); -	} else { -	    tmp = -		g_strdup_printf("%d hour%s, %d minute%s", ui->hours, -				plural(ui->hours), ui->minutes, -				plural(ui->minutes)); -	} +        if (ui->hours < 1) { +            ret = g_strdup_printf(minutes_fmt, ui->minutes); +        } else { +            full_fmt = g_strdup_printf("%s %s", hours_fmt, minutes_fmt); +            ret = g_strdup_printf(full_fmt, ui->hours, ui->minutes); +        }      } else { -	tmp = -	    g_strdup_printf("%d day%s, %d hour%s and %d minute%s", -			    ui->days, plural(ui->days), ui->hours, -			    plural(ui->hours), ui->minutes, -			    plural(ui->minutes)); +        full_fmt = g_strdup_printf("%s %s %s", days_fmt, hours_fmt, minutes_fmt); +        ret = g_strdup_printf(full_fmt, ui->days, ui->hours, ui->minutes);      } - +    g_free(full_fmt);      g_free(ui); -    return tmp; +    return ret;  } diff --git a/modules/computer/users.c b/modules/computer/users.c index e8f891ac..f47320bb 100644 --- a/modules/computer/users.c +++ b/modules/computer/users.c @@ -39,15 +39,16 @@ scan_users_do(void)      while (passwd_) {          gchar *key = g_strdup_printf("USER%s", passwd_->pw_name); -        gchar *val = g_strdup_printf("[User Information]\n" -                "User ID=%d\n" -                "Group ID=%d\n" -                "Home directory=%s\n" -                "Default shell=%s\n", -                (gint) passwd_->pw_uid, -                (gint) passwd_->pw_gid, -                passwd_->pw_dir, -                passwd_->pw_shell); +        gchar *val = g_strdup_printf("[%s]\n" +                "%s=%d\n" +                "%s=%d\n" +                "%s=%s\n" +                "%s=%s\n", +                _("User Information"), +                _("User ID"), (gint) passwd_->pw_uid, +                _("Group ID"), (gint) passwd_->pw_gid, +                _("Home Directory"), passwd_->pw_dir, +                _("Default Shell"), passwd_->pw_shell);          moreinfo_add_with_prefix("COMP", key, val);          strend(passwd_->pw_gecos, ','); @@ -55,6 +56,6 @@ scan_users_do(void)          passwd_ = getpwent();          g_free(key);      } -     +      endpwent();  } diff --git a/modules/devices.c b/modules/devices.c index 87bb8a80..9c7a184d 100644 --- a/modules/devices.c +++ b/modules/devices.c @@ -37,6 +37,7 @@  #include <socket.h>  #include "devices.h" +#include "dt_util.h"  gchar *callback_processors();  gchar *callback_memory(); @@ -51,6 +52,7 @@ gchar *callback_usb();  gchar *callback_dmi();  gchar *callback_spd();  #endif +gchar *callback_dtree();  gchar *callback_device_resources();  void scan_processors(gboolean reload); @@ -66,6 +68,7 @@ void scan_usb(gboolean reload);  void scan_dmi(gboolean reload);  void scan_spd(gboolean reload);  #endif +void scan_dtree(gboolean reload);  void scan_device_resources(gboolean reload);  gboolean root_required_for_resources(void); @@ -73,6 +76,7 @@ gboolean root_required_for_resources(void);  gchar *hi_more_info(gchar *entry);  enum { +    ENTRY_DTREE,      ENTRY_PROCESSOR,      ENTRY_MEMORY,      ENTRY_PCI, @@ -100,9 +104,14 @@ static ModuleEntry entries[] = {  #if defined(ARCH_x86) || defined(ARCH_x86_64)      [ENTRY_DMI] = {N_("DMI"), "computer.png", callback_dmi, scan_dmi, MODULE_FLAG_NONE},      [ENTRY_SPD] = {N_("Memory SPD"), "memory.png", callback_spd, scan_spd, MODULE_FLAG_NONE}, +    [ENTRY_DTREE] = {"#"}, +#else +    [ENTRY_DMI] = {"#"}, +    [ENTRY_SPD] = {"#"}, +    [ENTRY_DTREE] = {N_("Device Tree"), "devices.png", callback_dtree, scan_dtree, MODULE_FLAG_NONE},  #endif	/* x86 or x86_64 */      [ENTRY_RESOURCES] = {N_("Resources"), "resources.png", callback_device_resources, scan_device_resources, MODULE_FLAG_NONE}, -    {NULL} +    { NULL }  };  static GSList *processors = NULL; @@ -117,21 +126,127 @@ gchar *lginterval = NULL;  #include <vendor.h> -gchar *get_processor_name(void) +static gint proc_cmp_model_name(Processor *a, Processor *b) { +    return g_strcmp0(a->model_name, b->model_name); +} + +static gint proc_cmp_max_freq(Processor *a, Processor *b) { +    if (a->cpu_mhz == b->cpu_mhz) +        return 0; +    if (a->cpu_mhz > b->cpu_mhz) +        return -1; +    return 1; +} + +gchar *processor_describe_default(GSList * processors)  { -    scan_processors(FALSE); +    int packs, cores, threads; +    const gchar  *packs_fmt, *cores_fmt, *threads_fmt; +    gchar *ret, *full_fmt; -    Processor *p = (Processor *) processors->data; +    cpu_procs_cores_threads(&packs, &cores, &threads); -    if (g_slist_length(processors) > 1) { -	return idle_free(g_strdup_printf("%dx %s", -					 g_slist_length(processors), -					 p->model_name)); +    /* if topology info was available, else fallback to old method */ +    if (cores > 0) { +        packs_fmt = ngettext("%d physical processor", "%d physical processors", packs); +        cores_fmt = ngettext("%d core", "%d cores", cores); +        threads_fmt = ngettext("%d thread", "%d threads", threads); +        full_fmt = g_strdup_printf(_(/*/NP procs; NC cores; NT threads*/ "%s; %s; %s"), packs_fmt, cores_fmt, threads_fmt); +        ret = g_strdup_printf(full_fmt, packs, cores, threads); +        g_free(full_fmt); +        return ret;      } else { -	return p->model_name; +        return processor_describe_by_counting_names(processors); +    } +} + +gchar *processor_name_default(GSList * processors) +{ +    gchar *ret = g_strdup(""); +    GSList *tmp, *l; +    Processor *p; +    gchar *cur_str = NULL; +    gint cur_count = 0; + +    tmp = g_slist_copy(processors); +    tmp = g_slist_sort(tmp, (GCompareFunc)proc_cmp_model_name); + +    for (l = tmp; l; l = l->next) { +        p = (Processor*)l->data; +        if (cur_str == NULL) { +            cur_str = p->model_name; +            cur_count = 1; +        } else { +            if(g_strcmp0(cur_str, p->model_name)) { +                ret = h_strdup_cprintf("%s%s", ret, strlen(ret) ? "; " : "", cur_str); +                cur_str = p->model_name; +                cur_count = 1; +            } else { +                cur_count++; +            } +        } +    } +    ret = h_strdup_cprintf("%s%s", ret, strlen(ret) ? "; " : "", cur_str); +    g_slist_free(tmp); +    return ret; +} + +/* TODO: prefix counts are threads when they should be cores. */ +gchar *processor_describe_by_counting_names(GSList * processors) +{ +    gchar *ret = g_strdup(""); +    GSList *tmp, *l; +    Processor *p; +    gchar *cur_str = NULL; +    gint cur_count = 0; + +    tmp = g_slist_copy(processors); +    tmp = g_slist_sort(tmp, (GCompareFunc)proc_cmp_model_name); + +    for (l = tmp; l; l = l->next) { +        p = (Processor*)l->data; +        if (cur_str == NULL) { +            cur_str = p->model_name; +            cur_count = 1; +        } else { +            if(g_strcmp0(cur_str, p->model_name)) { +                ret = h_strdup_cprintf("%s%dx %s", ret, strlen(ret) ? " + " : "", cur_count, cur_str); +                cur_str = p->model_name; +                cur_count = 1; +            } else { +                cur_count++; +            } +        }      } +    ret = h_strdup_cprintf("%s%dx %s", ret, strlen(ret) ? " + " : "", cur_count, cur_str); +    g_slist_free(tmp); +    return ret; +} + +gchar *get_processor_name(void) +{ +    scan_processors(FALSE); +    return processor_name(processors); +} + +gchar *get_processor_desc(void) +{ +    scan_processors(FALSE); +    return processor_describe(processors); +} + +gchar *get_processor_name_and_desc(void) +{ +    scan_processors(FALSE); +    gchar* name = processor_name(processors); +    gchar* desc = processor_describe(processors); +    gchar* nd = g_strdup_printf("%s\n%s", name, desc); +    g_free(name); +    g_free(desc); +    return nd;  } +  gchar *get_storage_devices(void)  {      scan_storage(FALSE); @@ -160,175 +275,127 @@ gchar *get_processor_count(void)      return g_strdup_printf("%d", g_slist_length(processors));  } -gchar *get_processor_frequency(void) +/* TODO: maybe move into processor.c along with processor_name() etc. + * Could mention the big.LITTLE cluster arangement for ARM that kind of thing. + * TODO: prefix counts are threads when they should be cores. */ +gchar *processor_frequency_desc(GSList * processors) +{ +    gchar *ret = g_strdup(""); +    GSList *tmp, *l; +    Processor *p; +    float cur_val = -1; +    gint cur_count = 0; + +    tmp = g_slist_copy(processors); +    tmp = g_slist_sort(tmp, (GCompareFunc)proc_cmp_max_freq); + +    for (l = tmp; l; l = l->next) { +        p = (Processor*)l->data; +        if (cur_val == -1) { +            cur_val = p->cpu_mhz; +            cur_count = 1; +        } else { +            if(cur_val != p->cpu_mhz) { +                ret = h_strdup_cprintf("%s%dx %.2f %s", ret, strlen(ret) ? " + " : "", cur_count, cur_val, _("MHz") ); +                cur_val = p->cpu_mhz; +                cur_count = 1; +            } else { +                cur_count++; +            } +        } +    } +    ret = h_strdup_cprintf("%s%dx %.2f %s", ret, strlen(ret) ? " + " : "", cur_count, cur_val, _("MHz")); +    g_slist_free(tmp); +    return ret; +} + +gchar *get_processor_frequency_desc(void) +{ +    scan_processors(FALSE); +    return processor_frequency_desc(processors); +} + +gchar *get_processor_max_frequency(void)  { +    GSList *l;      Processor *p; +    float max_freq = 0;      scan_processors(FALSE); -    p = (Processor *)processors->data; -    if (p->cpu_mhz == 0.0f) { +    for (l = processors; l; l = l->next) { +        p = (Processor*)l->data; +        if (p->cpu_mhz > max_freq) +            max_freq = p->cpu_mhz; +    } + +    if (max_freq == 0.0f) {          return g_strdup(N_("Unknown"));      } else { -        return g_strdup_printf("%.0f", p->cpu_mhz); +        return g_strdup_printf("%.2f %s", max_freq, _("MHz") );      }  }  gchar *get_pci_device_description(gchar *pci_id)  {      gchar *description; -     +      if (!_pci_devices) {          scan_pci(FALSE);      } -     +      if ((description = g_hash_table_lookup(_pci_devices, pci_id))) {          return g_strdup(description);      } -     +      return NULL;  }  gchar *get_memory_total(void)  {      scan_memory(FALSE); -    return moreinfo_lookup ("DEV:Total Memory"); //hi_more_info(N_("Total Memory")); -} - -/* information table from: http://elinux.org/RPi_HardwareHistory */ -static struct { -    char *value, *intro, *model, *pcb, *mem, *mfg; -} rpi_boardinfo[] = { -/*  Value        Introduction  Model Name             PCB rev.  Memory       Manufacturer  * - *                             Raspberry Pi %s                                            */ -  { "Beta",      "Q1 2012",    "B (Beta)",            "?",      "256MB",    "(Beta board)" }, -  { "0002",      "Q1 2012",    "B",                   "1.0",    "256MB",    "?" }, -  { "0003",      "Q3 2012",    "B (ECN0001)",         "1.0",    "256MB",    "(Fuses mod and D14 removed)" }, -  { "0004",      "Q3 2012",    "B",                   "2.0",    "256MB",    "Sony"    }, -  { "0005",      "Q4 2012",    "B",                   "2.0",    "256MB",    "Qisda"   }, -  { "0006",      "Q4 2012",    "B",                   "2.0",    "256MB",    "Egoman"  }, -  { "0007",      "Q1 2013",    "A",                   "2.0",    "256MB",    "Egoman"  }, -  { "0008",      "Q1 2013",    "A",                   "2.0",    "256MB",    "Sony"    }, -  { "0009",      "Q1 2013",    "A",                   "2.0",    "256MB",    "Qisda"   }, -  { "000d",      "Q4 2012",    "B",                   "2.0",    "512MB",    "Egoman" }, -  { "000e",      "Q4 2012",    "B",                   "2.0",    "512MB",    "Sony" }, -  { "000f",      "Q4 2012",    "B",                   "2.0",    "512MB",    "Qisda" }, -  { "0010",      "Q3 2014",    "B+",                  "1.0",    "512MB",    "Sony" }, -  { "0011",      "Q2 2014",    "Compute Module 1",    "1.0",    "512MB",    "Sony" }, -  { "0012",      "Q4 2014",    "A+",                  "1.1",    "256MB",    "Sony" }, -  { "0013",      "Q1 2015",    "B+",                  "1.2",    "512MB",    "?" }, -  { "0014",      "Q2 2014",    "Compute Module 1",    "1.0",    "512MB",    "Embest" }, -  { "0015",      "?",          "A+",                  "1.1",    "256MB/512MB",    "Embest" }, -  { "a01040",    "Unknown",    "2 Model B",           "1.0",    "1GB",      "Sony" }, -  { "a01041",    "Q1 2015",    "2 Model B",           "1.1",    "1GB",      "Sony" }, -  { "a21041",    "Q1 2015",    "2 Model B",           "1.1",    "1GB",      "Embest" }, -  { "a22042",    "Q3 2016",    "2 Model B",           "1.2",    "1GB",      "Embest" },  /* (with BCM2837) */ -  { "900021",    "Q3 2016",    "A+",                  "1.1",    "512MB",    "Sony" }, -  { "900032",    "Q2 2016?",    "B+",                 "1.2",    "512MB",    "Sony" }, -  { "900092",    "Q4 2015",    "Zero",                "1.2",    "512MB",    "Sony" }, -  { "900093",    "Q2 2016",    "Zero",                "1.3",    "512MB",    "Sony" }, -  { "920093",    "Q4 2016?",   "Zero",                "1.3",    "512MB",    "Embest" }, -  { "9000c1",    "Q1 2017",    "Zero W",              "1.1",    "512MB",    "Sony" }, -  { "a02082",    "Q1 2016",    "3 Model B",           "1.2",    "1GB",      "Sony" }, -  { "a020a0",    "Q1 2017",    "Compute Module 3 or CM3 Lite",    "1.0",    "1GB",    "Sony" }, -  { "a22082",    "Q1 2016",    "3 Model B",           "1.2",    "1GB",    "Embest" }, -  { "a32082",    "Q4 2016",    "3 Model B",           "1.2",    "1GB",    "Sony Japan" }, -  { NULL, NULL, NULL, NULL, NULL, NULL } -}; - -static gchar *rpi_get_boardname(void) { -    int i = 0, c = 0; -    gchar *ret = NULL; -    gchar *soc = NULL; -    gchar *revision = NULL; -    int overvolt = 0; -    FILE *cpuinfo; -    gchar buffer[128]; - -    cpuinfo = fopen("/proc/cpuinfo", "r"); -    if (!cpuinfo) -        return NULL; -    while (fgets(buffer, 128, cpuinfo)) { -        gchar **tmp = g_strsplit(buffer, ":", 2); -        tmp[0] = g_strstrip(tmp[0]); -        tmp[1] = g_strstrip(tmp[1]); -        get_str("Revision", revision); -        get_str("Hardware", soc); -    } -    fclose(cpuinfo); - -    if (revision == NULL || soc == NULL) { -        g_free(soc); -        g_free(revision); -        return NULL; -    } - -    if (g_str_has_prefix(revision, "1000")) -        overvolt = 1; - -    while (rpi_boardinfo[i].value != NULL) { -        if (overvolt) -            /* +4 to ignore the 1000 prefix */ -            c = g_strcmp0(revision+4, rpi_boardinfo[i].value); -        else -            c = g_strcmp0(revision, rpi_boardinfo[i].value); - -        if (c == 0) { -            ret = g_strdup_printf("Raspberry Pi %s (%s) pcb-rev:%s soc:%s mem:%s mfg-by:%s%s", -                rpi_boardinfo[i].model, rpi_boardinfo[i].intro, -                rpi_boardinfo[i].pcb, soc, -                rpi_boardinfo[i].mem, rpi_boardinfo[i].mfg, -                (overvolt) ? " (over-volted)" : "" ); -            break; -        } -        i++; -    } -    g_free(soc); -    g_free(revision); -    return ret; +    return moreinfo_lookup ("DEV:MemTotal");  }  gchar *get_motherboard(void)  { -    char *board_name, *board_vendor; +    char *board_name, *board_vendor, *product_version; +  #if defined(ARCH_x86) || defined(ARCH_x86_64)      scan_dmi(FALSE);      board_name = moreinfo_lookup("DEV:DMI:Board:Name");      board_vendor = moreinfo_lookup("DEV:DMI:Board:Vendor"); -     -    if (board_name && board_vendor && *board_name && *board_vendor) -       return g_strconcat(board_vendor, " ", board_name, NULL); -    else if (board_name && *board_name) -       return g_strconcat(board_name, _(" (vendor unknown)"), NULL); -    else if (board_vendor && *board_vendor) -       return g_strconcat(board_vendor, _(" (model unknown)"), NULL); -#else -    /* use device tree "model" */ -    if (g_file_get_contents("/proc/device-tree/model", &board_vendor, NULL, NULL)) { - -        /* if a raspberry pi, try and get a more detailed name */ -        if (g_str_has_prefix(board_vendor, "Raspberry Pi")) { -            board_name = rpi_get_boardname(); -            if (board_name != NULL) { -                g_free(board_vendor); -                return board_name; -            } -        } +    product_version = moreinfo_lookup("DEV:DMI:Product:Version#1"); -        return board_vendor; -    } +    if (!board_name || !*board_name) +       board_name = _(" (model unknown)"); +    if (!board_vendor || !*board_vendor) +       board_vendor = _(" (vendor unknown)"); + +    if (product_version && *product_version) +       return g_strdup_printf("%s / %s (%s)", product_version, board_name, board_vendor); + +    return g_strconcat(board_vendor, " ", board_name, NULL);  #endif +    /* use device tree "model" */ +    board_vendor = dtr_get_string("/model", 0); +    if (board_vendor != NULL) +        return board_vendor; +      return g_strdup(_("Unknown"));  }  ShellModuleMethod *hi_exported_methods(void)  {      static ShellModuleMethod m[] = { -        {"getProcessorCount", get_processor_count}, +	{"getProcessorCount", get_processor_count},  	{"getProcessorName", get_processor_name}, -	{"getProcessorFrequency", get_processor_frequency}, +	{"getProcessorDesc", get_processor_desc}, +	{"getProcessorNameAndDesc", get_processor_name_and_desc}, +	{"getProcessorFrequency", get_processor_max_frequency}, +	{"getProcessorFrequencyDesc", get_processor_frequency_desc},  	{"getMemoryTotal", get_memory_total},  	{"getStorageDevices", get_storage_devices},  	{"getPrinters", get_printers}, @@ -344,7 +411,7 @@ ShellModuleMethod *hi_exported_methods(void)  gchar *hi_more_info(gchar * entry)  {      gchar *info = moreinfo_lookup_with_prefix("DEV", entry); -     +      if (info)  	return g_strdup(info); @@ -377,6 +444,13 @@ void scan_spd(gboolean reload)  }  #endif +void scan_dtree(gboolean reload) +{ +    SCAN_START(); +    __scan_dtree(); +    SCAN_END(); +} +  void scan_processors(gboolean reload)  {      SCAN_START(); @@ -462,15 +536,28 @@ gchar *callback_spd()  }  #endif +gchar *callback_dtree() +{ +    return g_strdup_printf("%s" +        "[$ShellParam$]\n" +        "ViewType=1\n", dtree_info); +} +  gchar *callback_memory()  {      return g_strdup_printf("[Memory]\n" -			   "%s\n" -			   "[$ShellParam$]\n" -			   "ViewType=2\n" -			   "LoadGraphSuffix= kB\n" -			   "RescanInterval=2000\n" -			   "%s\n", meminfo, lginterval); +               "%s\n" +               "[$ShellParam$]\n" +               "ViewType=2\n" +               "LoadGraphSuffix= kB\n" +               "RescanInterval=2000\n" +               "ColumnTitle$TextValue=%s\n" +               "ColumnTitle$Extra1=%s\n" +               "ColumnTitle$Value=%s\n" +               "ShowColumnHeaders=true\n" +               "%s\n", meminfo, +               _("Field"), _("Description"), _("Value"), /* column labels */ +               lginterval);  }  gchar *callback_battery() @@ -489,8 +576,20 @@ gchar *callback_pci()  gchar *callback_sensors()  { -    return g_strdup_printf("[$ShellParam$]\n" -			   "ReloadInterval=5000\n" "%s", sensors); +    return g_strdup_printf("[Sensors]\n" +                           "%s\n" +                           "[$ShellParam$]\n" +                           "ViewType=2\n" +                           "LoadGraphSuffix=\n" +                           "ColumnTitle$TextValue=%s\n" +                           "ColumnTitle$Value=%s\n" +                           "ColumnTitle$Extra1=%s\n" +                           "ShowColumnHeaders=true\n" +                           "RescanInterval=5000\n" +                           "%s", +                           sensors, +                           _("Sensor"), _("Value"), _("Type"), /* column labels */ +                           lginterval);  }  gchar *callback_printers() @@ -564,7 +663,7 @@ void hi_module_init(void)          .save_to = "cpuflags.conf",          .get_data = NULL        }; -       +        sync_manager_add_entry(&se);      }  #endif	/* defined(ARCH_x86) */ @@ -606,7 +705,7 @@ const gchar *hi_note_func(gint entry)  {      if (entry == ENTRY_RESOURCES) {          if (root_required_for_resources()) { -            return g_strdup_printf(_("Resource information requires superuser privileges")); +            return g_strdup(_("Resource information requires superuser privileges"));          }      }      return NULL; diff --git a/modules/devices/alpha/processor.c b/modules/devices/alpha/processor.c index f55526f7..c7862232 100644 --- a/modules/devices/alpha/processor.c +++ b/modules/devices/alpha/processor.c @@ -18,6 +18,7 @@  #include "hardinfo.h"  #include "devices.h" +#include "cpu_util.h"  GSList *  processor_scan(void) @@ -25,54 +26,69 @@ processor_scan(void)      Processor *processor;      FILE *cpuinfo;      gchar buffer[128]; +    long long hz = 0; -    cpuinfo = fopen("/proc/cpuinfo", "r"); +    cpuinfo = fopen(PROC_CPUINFO, "r");      if (!cpuinfo) -	return NULL; +        return NULL;      processor = g_new0(Processor, 1);      while (fgets(buffer, 128, cpuinfo)) { -	gchar **tmp = g_strsplit(buffer, ":", 2); +        gchar **tmp = g_strsplit(buffer, ":", 2); -	if (tmp[0] && tmp[1]) { -	    tmp[0] = g_strstrip(tmp[0]); -	    tmp[1] = g_strstrip(tmp[1]); +        if (tmp[0] && tmp[1]) { +            tmp[0] = g_strstrip(tmp[0]); +            tmp[1] = g_strstrip(tmp[1]); -	    get_str("cpu model", processor->model_name); -	    get_float("BogoMIPS", processor->bogomips); -	    get_str("platform string", processor->strmodel); +            get_str("cpu model", processor->model_name); +            get_float("BogoMIPS", processor->bogomips); +            get_str("platform string", processor->strmodel); +            get_str("cycle frequency [Hz]", processor->cycle_frequency_hz_str); -	} -	g_strfreev(tmp); +        } +        g_strfreev(tmp);      } -     + +    fclose(cpuinfo); +      gchar *tmp = g_strconcat("Alpha ", processor->model_name, NULL);      g_free(processor->model_name);      processor->model_name = tmp; -    processor->cpu_mhz = 0.0f; -    fclose(cpuinfo); +    if (processor->cycle_frequency_hz_str) { +        hz = atoll(processor->cycle_frequency_hz_str); +        processor->cpu_mhz = hz; +        processor->cpu_mhz /= 1000000; +    } else +        processor->cpu_mhz = 0.0f;      return g_slist_append(NULL, processor);  } +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors); +} +  gchar *  processor_get_info(GSList *processors)  { -        Processor *processor = (Processor *)processors->data; +    Processor *processor = (Processor *)processors->data; -	return g_strdup_printf("[Processor]\n" -                               "Model=%s\n" -	                       "Platform String=%s\n" -	                       "BogoMIPS=%.2f" -	                       "Byte Order=%s\n", -			       processor->model_name, -			       processor->strmodel, -			       processor->bogomips, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -                               "Little Endian" -#else -                               "Big Endian" -#endif -                              ); +    return g_strdup_printf("[%s]\n" +                        "%s=%s\n" +                        "%s=%s\n" +                        "%s=%.2f %s\n" /* frequency */ +                        "%s=%.2f\n"    /* bogomips */ +                        "%s=%s\n",     /* byte order */ +                    _("Processor"), +                    _("Model"), processor->model_name, +                    _("Platform String"), processor->strmodel, +                    _("Frequency"), processor->cpu_mhz, _("MHz"), +                    _("BogoMips"), processor->bogomips, +                    _("Byte Order"), byte_order_str() +                    );  } diff --git a/modules/devices/arm/arm_data.c b/modules/devices/arm/arm_data.c index 2e2cbe60..60e8ea34 100644 --- a/modules/devices/arm/arm_data.c +++ b/modules/devices/arm/arm_data.c @@ -23,6 +23,13 @@  #include <string.h>  #include "arm_data.h" +#ifndef C_ +#define C_(Ctx, String) String +#endif +#ifndef NC_ +#define NC_(Ctx, String) String +#endif +  /* sources:   *   https://unix.stackexchange.com/a/43563   *   git:linux/arch/arm/kernel/setup.c @@ -32,47 +39,46 @@ static struct {      char *name, *meaning;  } tab_flag_meaning[] = {      /* arm/hw_cap */ -    { "swp",	"SWP instruction (atomic read-modify-write)" }, -    { "half",	"Half-word loads and stores" }, -    { "thumb",	"Thumb (16-bit instruction set)" }, -    { "26bit",	"26-Bit Model (Processor status register folded into program counter)" }, -    { "fastmult",	"32x32->64-bit multiplication" }, -    { "fpa",	"Floating point accelerator" }, -    { "vfp",	"VFP (early SIMD vector floating point instructions)" }, -    { "edsp",	"DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above)" }, -    { "java",	"Jazelle (Java bytecode accelerator)" }, -    { "iwmmxt",	"SIMD instructions similar to Intel MMX" }, -    { "crunch",	"MaverickCrunch coprocessor (if kernel support enabled)" }, -    { "thumbee",	"ThumbEE" }, -    { "neon",	"Advanced SIMD/NEON on AArch32" }, -    { "evtstrm",	"kernel event stream using generic architected timer" }, -    { "vfpv3",	"VFP version 3" }, -    { "vfpv3d16",	"VFP version 3 with 16 D-registers" }, -    { "vfpv4",	"VFP version 4 with fast context switching" }, -    { "vfpd32",	"VFP with 32 D-registers" }, -    { "tls",	"TLS register" }, -    { "idiva",	"SDIV and UDIV hardware division in ARM mode" }, -    { "idivt",	"SDIV and UDIV hardware division in Thumb mode" }, -    { "lpae",	"40-bit Large Physical Address Extension" }, +    { "swp",      NC_("arm-flag", /*/flag:swp*/      "SWP instruction (atomic read-modify-write)") }, +    { "half",     NC_("arm-flag", /*/flag:half*/     "Half-word loads and stores") }, +    { "thumb",    NC_("arm-flag", /*/flag:thumb*/    "Thumb (16-bit instruction set)") }, +    { "26bit",    NC_("arm-flag", /*/flag:26bit*/    "26-Bit Model (Processor status register folded into program counter)") }, +    { "fastmult", NC_("arm-flag", /*/flag:fastmult*/ "32x32->64-bit multiplication") }, +    { "fpa",      NC_("arm-flag", /*/flag:fpa*/      "Floating point accelerator") }, +    { "vfp",      NC_("arm-flag", /*/flag:vfp*/      "VFP (early SIMD vector floating point instructions)") }, +    { "edsp",     NC_("arm-flag", /*/flag:edsp*/     "DSP extensions (the 'e' variant of the ARM9 CPUs, and all others above)") }, +    { "java",     NC_("arm-flag", /*/flag:java*/     "Jazelle (Java bytecode accelerator)") }, +    { "iwmmxt",   NC_("arm-flag", /*/flag:iwmmxt*/   "SIMD instructions similar to Intel MMX") }, +    { "crunch",   NC_("arm-flag", /*/flag:crunch*/   "MaverickCrunch coprocessor (if kernel support enabled)") }, +    { "thumbee",  NC_("arm-flag", /*/flag:thumbee*/  "ThumbEE") }, +    { "neon",     NC_("arm-flag", /*/flag:neon*/     "Advanced SIMD/NEON on AArch32") }, +    { "evtstrm",  NC_("arm-flag", /*/flag:evtstrm*/  "Kernel event stream using generic architected timer") }, +    { "vfpv3",    NC_("arm-flag", /*/flag:vfpv3*/    "VFP version 3") }, +    { "vfpv3d16", NC_("arm-flag", /*/flag:vfpv3d16*/ "VFP version 3 with 16 D-registers") }, +    { "vfpv4",    NC_("arm-flag", /*/flag:vfpv4*/    "VFP version 4 with fast context switching") }, +    { "vfpd32",   NC_("arm-flag", /*/flag:vfpd32*/   "VFP with 32 D-registers") }, +    { "tls",      NC_("arm-flag", /*/flag:tls*/      "TLS register") }, +    { "idiva",    NC_("arm-flag", /*/flag:idiva*/    "SDIV and UDIV hardware division in ARM mode") }, +    { "idivt",    NC_("arm-flag", /*/flag:idivt*/    "SDIV and UDIV hardware division in Thumb mode") }, +    { "lpae",     NC_("arm-flag", /*/flag:lpae*/     "40-bit Large Physical Address Extension") },      /* arm/hw_cap2 */ -    { "pmull",	"64x64->128-bit F2m multiplication (arch>8)" }, -    { "aes",	"Crypto:AES (arch>8)" }, -    { "sha1",	"Crypto:SHA1 (arch>8)" }, -    { "sha2",	"Crypto:SHA2 (arch>8)" }, -    { "crc32",	"CRC32 checksum instructions (arch>8)" }, +    { "pmull",    NC_("arm-flag", /*/flag:pmull*/    "64x64->128-bit F2m multiplication (arch>8)") }, +    { "aes",      NC_("arm-flag", /*/flag:aes*/      "Crypto:AES (arch>8)") }, +    { "sha1",     NC_("arm-flag", /*/flag:sha1*/     "Crypto:SHA1 (arch>8)") }, +    { "sha2",     NC_("arm-flag", /*/flag:sha2*/     "Crypto:SHA2 (arch>8)") }, +    { "crc32",    NC_("arm-flag", /*/flag:crc32*/    "CRC32 checksum instructions (arch>8)") },      /* arm64/hw_cap */ -    { "fp",	"" }, -    { "asimd",	"Advanced SIMD/NEON on AArch64 (arch>8)" }, -    { "atomics",	"" }, -    { "fphp",	"" }, -    { "asimdhp",	"" }, -    { "cpuid",	"" }, -    { "asimdrdm",	"" }, -    { "jscvt",	"" }, -    { "fcma",	"" }, -    { "lrcpc",	"" }, - -    { NULL, NULL}, +    { "fp",       NULL }, +    { "asimd",    NC_("arm-flag", /*/flag:asimd*/    "Advanced SIMD/NEON on AArch64 (arch>8)") }, +    { "atomics",  NULL }, +    { "fphp",     NULL }, +    { "asimdhp",  NULL }, +    { "cpuid",    NULL }, +    { "asimdrdm", NULL }, +    { "jscvt",    NULL }, +    { "fcma",     NULL }, +    { "lrcpc",    NULL }, +    { NULL, NULL }  };  static struct { @@ -108,9 +114,11 @@ static struct {      /*d */ { 0xd01,	"Cortex-A32" },      /*dt*/ { 0xd03,	"Cortex-A53" },      /*d */ { 0xd04,	"Cortex-A35" }, +    /*d */ { 0xd05,	"Cortex-A55" },      /*d */ { 0xd07,	"Cortex-A57 MPCore" },      /*d */ { 0xd08,	"Cortex-A72" },      /*d */ { 0xd09,	"Cortex-A73" }, +    /*d */ { 0xd0a,	"Cortex-A75" },             { 0, NULL},  }; @@ -143,8 +151,11 @@ const char *arm_flag_meaning(const char *flag) {      int i = 0;      if (flag)      while(tab_flag_meaning[i].name != NULL) { -        if (strcmp(tab_flag_meaning[i].name, flag) == 0) -            return tab_flag_meaning[i].meaning; +        if (strcmp(tab_flag_meaning[i].name, flag) == 0) { +            if (tab_flag_meaning[i].meaning != NULL) +                return C_("arm-flag", tab_flag_meaning[i].meaning); +            else return NULL; +        }          i++;      }      return NULL; @@ -220,7 +231,7 @@ char *arm_decoded_name(const char *imp, const char *part, const char *var, const              p = strtol(rev, NULL, 0);              imp_name = (char*) arm_implementer(imp);              part_desc = (char*) arm_part(imp, part); -            arch_name = (char *) arm_arch(arch); +            arch_name = (char*) arm_arch(arch);              if (imp_name || part_desc) {                  if (arch_name != arch)                      sprintf(dnbuff, "%s %s r%dp%d (%s)", diff --git a/modules/devices/arm/processor.c b/modules/devices/arm/processor.c index ad7adf7f..e9446229 100644 --- a/modules/devices/arm/processor.c +++ b/modules/devices/arm/processor.c @@ -18,6 +18,8 @@  #include "hardinfo.h"  #include "devices.h" +#include "cpu_util.h" +#include "dt_util.h"  #include "arm_data.h"  #include "arm_data.c" @@ -34,34 +36,6 @@ static const gchar *arm_mode_str[] = {      "A32 on A64",  }; -static gint get_cpu_int(const gchar* file, gint cpuid) { -    gchar *tmp0 = NULL; -    gchar *tmp1 = NULL; -    gint ret = 0; - -    tmp0 = g_strdup_printf("/sys/devices/system/cpu/cpu%d/%s", cpuid, file); -    g_file_get_contents(tmp0, &tmp1, NULL, NULL); -    if (tmp1) -        ret = atol(tmp1); -    g_free(tmp0); -    g_free(tmp1); -    return ret; -} - -int processor_has_flag(gchar * strflags, gchar * strflag) -{ -    gchar **flags; -    gint ret = 0; -    if (strflags == NULL || strflag == NULL) -        return 0; -    flags = g_strsplit(strflags, " ", 0); -    ret = g_strv_contains((const gchar * const *)flags, strflag); -    g_strfreev(flags); -    return ret; -} - -#define PROC_CPUINFO "/proc/cpuinfo" -  GSList *  processor_scan(void)  { @@ -70,7 +44,6 @@ processor_scan(void)      FILE *cpuinfo;      gchar buffer[128];      gchar *rep_pname = NULL; -    gchar *tmpfreq_str = NULL;      GSList *pi = NULL;      cpuinfo = fopen(PROC_CPUINFO, "r"); @@ -101,7 +74,7 @@ processor_scan(void)              processor->id = atol(tmp[1]);              if (rep_pname) -                processor->model_name = g_strdup(rep_pname); +                processor->linux_name = g_strdup(rep_pname);              g_strfreev(tmp);              continue; @@ -117,11 +90,11 @@ processor_scan(void)              processor->id = 0;              if (rep_pname) -                processor->model_name = g_strdup(rep_pname); +                processor->linux_name = g_strdup(rep_pname);          }          if (processor) { -            get_str("model name", processor->model_name); +            get_str("model name", processor->linux_name);              get_str("Features", processor->flags);              get_float("BogoMIPS", processor->bogomips); @@ -166,29 +139,26 @@ processor_scan(void)          processor = (Processor *) pi->data;          /* strings can't be null or segfault later */ -#define STRIFNULL(f,cs) if (processor->f == NULL) processor->f = g_strdup(cs); -#define UNKIFNULL(f) STRIFNULL(f, "(Unknown)") -#define EMPIFNULL(f) STRIFNULL(f, "") -        STRIFNULL(model_name, "ARM Processor"); -        EMPIFNULL(flags); -        UNKIFNULL(cpu_implementer); -        UNKIFNULL(cpu_architecture); -        UNKIFNULL(cpu_variant); -        UNKIFNULL(cpu_part); -        UNKIFNULL(cpu_revision); - -        processor->decoded_name = arm_decoded_name( +        STRIFNULL(processor->linux_name, _("ARM Processor") ); +        EMPIFNULL(processor->flags); +        UNKIFNULL(processor->cpu_implementer); +        UNKIFNULL(processor->cpu_architecture); +        UNKIFNULL(processor->cpu_variant); +        UNKIFNULL(processor->cpu_part); +        UNKIFNULL(processor->cpu_revision); + +        processor->model_name = arm_decoded_name(              processor->cpu_implementer, processor->cpu_part,              processor->cpu_variant, processor->cpu_revision, -            processor->cpu_architecture, processor->model_name); -        UNKIFNULL(decoded_name); - -        /* freq */ -        processor->cpukhz_cur = get_cpu_int("cpufreq/scaling_cur_freq", processor->id); -        processor->cpukhz_min = get_cpu_int("cpufreq/scaling_min_freq", processor->id); -        processor->cpukhz_max = get_cpu_int("cpufreq/scaling_max_freq", processor->id); -        if (processor->cpukhz_max) -            processor->cpu_mhz = processor->cpukhz_max / 1000; +            processor->cpu_architecture, processor->linux_name); +        UNKIFNULL(processor->model_name); + +        /* topo & freq */ +        processor->cpufreq = cpufreq_new(processor->id); +        processor->cputopo = cputopo_new(processor->id); + +        if (processor->cpufreq->cpukhz_max) +            processor->cpu_mhz = processor->cpufreq->cpukhz_max / 1000;          else              processor->cpu_mhz = 0.0f; @@ -236,78 +206,168 @@ gchar *processor_get_capabilities_from_flags(gchar * strflags)  gchar *  processor_get_detailed_info(Processor *processor)  { -    gchar *tmp_flags, *tmp_imp, *tmp_part, *tmp_arch, *ret; +    gchar *tmp_flags, *tmp_imp, *tmp_part, *tmp_arch, *tmp_cpufreq, *tmp_topology, *ret;      tmp_flags = processor_get_capabilities_from_flags(processor->flags);      tmp_imp = (char*)arm_implementer(processor->cpu_implementer);      tmp_part = (char*)arm_part(processor->cpu_implementer, processor->cpu_part);      tmp_arch = (char*)arm_arch_more(processor->cpu_architecture); -    ret = g_strdup_printf("[Processor]\n" -                           "Linux Name=%s\n" -                           "Decoded Name=%s\n" -                           "Mode=%s\n" -                   "BogoMips=%.2f\n" -                   "Endianesss=" -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -                       "Little Endian" -#else -                       "Big Endian" -#endif -                       "\n" -                       "[Frequency Scaling]\n" -                       "Minimum=%d kHz\n" -                       "Maximum=%d kHz\n" -                       "Current=%d kHz\n" -                       "[ARM]\n" -                       "Implementer=[%s] %s\n" -                       "Part=[%s] %s\n" -                       "Architecture=[%s] %s\n" -                       "Variant=%s\n" -                       "Revision=%s\n" -                       "[Capabilities]\n" +    tmp_topology = cputopo_section_str(processor->cputopo); +    tmp_cpufreq = cpufreq_section_str(processor->cpufreq); + +    ret = g_strdup_printf("[%s]\n" +                       "%s=%s\n"       /* linux name */ +                       "%s=%s\n"       /* decoded name */ +                       "%s=%s\n"       /* mode */ +                       "%s=%.2f %s\n"  /* frequency */ +                       "%s=%.2f\n"     /* bogomips */ +                       "%s=%s\n"       /* byte order */ +                       "%s" /* topology */ +                       "%s" /* frequency scaling */ +                       "[%s]\n"    /* ARM */ +                       "%s=[%s] %s\n"  /* implementer */ +                       "%s=[%s] %s\n"  /* part */ +                       "%s=[%s] %s\n"  /* architecture */ +                       "%s=%s\n"       /* variant */ +                       "%s=%s\n"       /* revision */ +                       "[%s]\n" /* flags */                         "%s" -                       "%s", -                   processor->model_name, -                   processor->decoded_name, -                   arm_mode_str[processor->mode], -                   processor->bogomips, -                   processor->cpukhz_min, -                   processor->cpukhz_max, -                   processor->cpukhz_cur, -                   processor->cpu_implementer, (tmp_imp) ? tmp_imp : "", -                   processor->cpu_part, (tmp_part) ? tmp_part : "", -                   processor->cpu_architecture, (tmp_arch) ? tmp_arch : "", -                   processor->cpu_variant, -                   processor->cpu_revision, -                   tmp_flags, +                       "%s",    /* empty */ +                   _("Processor"), +                   _("Linux Name"), processor->linux_name, +                   _("Decoded Name"), processor->model_name, +                   _("Mode"), arm_mode_str[processor->mode], +                   _("Frequency"), processor->cpu_mhz, _("MHz"), +                   _("BogoMips"), processor->bogomips, +                   _("Byte Order"), byte_order_str(), +                   tmp_topology, +                   tmp_cpufreq, +                   _("ARM"), +                   _("Implementer"), processor->cpu_implementer, (tmp_imp) ? tmp_imp : "", +                   _("Part"), processor->cpu_part, (tmp_part) ? tmp_part : "", +                   _("Architecture"), processor->cpu_architecture, (tmp_arch) ? tmp_arch : "", +                   _("Variant"), processor->cpu_variant, +                   _("Revision"), processor->cpu_revision, +                   _("Capabilities"), tmp_flags,                      "");      g_free(tmp_flags); +    g_free(tmp_cpufreq); +    g_free(tmp_topology); +    return ret; +} +gchar *processor_name(GSList *processors) { +    /* compatible contains a list of compatible hardware, so be careful +     * with matching order. +     * ex: "ti,omap3-beagleboard-xm", "ti,omap3450", "ti,omap3"; +     * matches "omap3 family" first. +     * ex: "brcm,bcm2837", "brcm,bcm2836"; +     * would match 2836 when it is a 2837. +     */ +#define UNKSOC "(Unknown)" +    const struct { +        char *search_str; +        char *vendor; +        char *soc; +    } dt_compat_searches[] = { +        { "brcm,bcm2837", "Broadcom", "BCM2837" }, +        { "brcm,bcm2836", "Broadcom", "BCM2836" }, +        { "brcm,bcm2835", "Broadcom", "BCM2835" }, +        { "ti,omap5432", "Texas Instruments", "OMAP5432" }, +        { "ti,omap5430", "Texas Instruments", "OMAP5430" }, +        { "ti,omap4470", "Texas Instruments", "OMAP4470" }, +        { "ti,omap4460", "Texas Instruments", "OMAP4460" }, +        { "ti,omap4430", "Texas Instruments", "OMAP4430" }, +        { "ti,omap3620", "Texas Instruments", "OMAP3620" }, +        { "ti,omap3450", "Texas Instruments", "OMAP3450" }, +        { "ti,omap5", "Texas Instruments", "OMAP5-family" }, +        { "ti,omap4", "Texas Instruments", "OMAP4-family" }, +        { "ti,omap3", "Texas Instruments", "OMAP3-family" }, +        { "ti,omap2", "Texas Instruments", "OMAP2-family" }, +        { "ti,omap1", "Texas Instruments", "OMAP1-family" }, +        { "qcom,msm8939", "Qualcomm", "Snapdragon 615"}, +        { "qcom,msm", "Qualcomm", "Snapdragon-family"}, +        { "nvidia,tegra" "nVidia", "Tegra-family" }, +        { "bcm,", "Broadcom", UNKSOC }, +        { "nvidia," "nVidia", UNKSOC }, +        { "rockchip," "Rockchip", UNKSOC }, +        { "ti,", "Texas Instruments", UNKSOC }, +        { "qcom,", "Qualcom", UNKSOC }, +        { NULL, NULL } +    }; +    gchar *ret = NULL; +    gchar *compat = NULL; +    int i; + +    compat = dtr_get_string("/compatible", 1); + +    if (compat != NULL) { +        i = 0; +        while(dt_compat_searches[i].search_str != NULL) { +            if (strstr(compat, dt_compat_searches[i].search_str) != NULL) { +                ret = g_strdup_printf("%s %s", dt_compat_searches[i].vendor, dt_compat_searches[i].soc); +                break; +            } +            i++; +        } +    } +    g_free(compat); +    UNKIFNULL(ret); +    return ret; +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_by_counting_names(processors); +} + +gchar *processor_meta(GSList * processors) { +    gchar *meta_soc = processor_name(processors); +    gchar *meta_cpu_desc = processor_describe(processors); +    gchar *meta_cpu_topo = processor_describe_default(processors); +    gchar *meta_clocks = processor_frequency_desc(processors); +    gchar *ret = NULL; +    UNKIFNULL(meta_cpu_desc); +    ret = g_strdup_printf("[%s]\n" +                            "%s=%s\n" +                            "%s=%s\n" +                            "%s=%s\n" +                            "%s=%s\n", +                            _("SOC/Package"), +                            _("Name"), meta_soc, +                            _("Description"), meta_cpu_desc, +                            _("Topology"), meta_cpu_topo, +                            _("Clocks"), meta_clocks ); +    g_free(meta_soc); +    g_free(meta_cpu_desc); +    g_free(meta_cpu_topo); +    g_free(meta_clocks);      return ret;  }  gchar *processor_get_info(GSList * processors)  {      Processor *processor; - -    if (g_slist_length(processors) > 1) {      gchar *ret, *tmp, *hashkey; +    gchar *meta; /* becomes owned by more_info? no need to free? */      GSList *l; -    tmp = g_strdup(""); +    tmp = g_strdup_printf("$CPU_META$%s=\n", _("SOC/Package Information") ); + +    meta = processor_meta(processors); +    moreinfo_add_with_prefix("DEV", "CPU_META", meta);      for (l = processors; l; l = l->next) {          processor = (Processor *) l->data; -        tmp = g_strdup_printf(_("%s$CPU%d$%s=%.2fMHz\n"), +        tmp = g_strdup_printf("%s$CPU%d$%s=%.2f %s\n",                    tmp, processor->id,                    processor->model_name, -                  processor->cpu_mhz); +                  processor->cpu_mhz, _("MHz"));          hashkey = g_strdup_printf("CPU%d", processor->id);          moreinfo_add_with_prefix("DEV", hashkey,                  processor_get_detailed_info(processor)); -           g_free(hashkey); +        g_free(hashkey);      }      ret = g_strdup_printf("[$ShellParam$]\n" @@ -317,8 +377,4 @@ gchar *processor_get_info(GSList * processors)      g_free(tmp);      return ret; -    } - -    processor = (Processor *) processors->data; -    return processor_get_detailed_info(processor);  } diff --git a/modules/devices/cpu_util.c b/modules/devices/cpu_util.c new file mode 100644 index 00000000..f5bddd5c --- /dev/null +++ b/modules/devices/cpu_util.c @@ -0,0 +1,225 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org> + *    This file by Burt P. <pburt0@gmail.com> + * + *    This program 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. + * + *    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; if not, write to the Free Software + *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA + */ + +#include <string.h> +#include "hardinfo.h" +#include "cpu_util.h" + +#include "cpubits.c" + +#define CPU_TOPO_NULL -9877 + +const gchar *byte_order_str() { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +    return _("Little Endian"); +#else +    return _("Big Endian"); +#endif +} + +int processor_has_flag(gchar * strflags, gchar * strflag) +{ +    gchar **flags; +    gint ret = 0; +    if (strflags == NULL || strflag == NULL) +        return 0; +    flags = g_strsplit(strflags, " ", 0); +    ret = g_strv_contains((const gchar * const *)flags, strflag); +    g_strfreev(flags); +    return ret; +} + +gchar* get_cpu_str(const gchar* file, gint cpuid) { +    gchar *tmp0 = NULL; +    gchar *tmp1 = NULL; +    tmp0 = g_strdup_printf("/sys/devices/system/cpu/cpu%d/%s", cpuid, file); +    g_file_get_contents(tmp0, &tmp1, NULL, NULL); +    g_free(tmp0); +    return tmp1; +} + +gint get_cpu_int(const char* item, int cpuid, int null_val) { +    gchar *fc = NULL; +    int ret = null_val; +    fc = get_cpu_str(item, cpuid); +    if (fc) { +        ret = atol(fc); +        g_free(fc); +    } +    return ret; +} + +/* cpubits is 32768 bits long + * core_ids are not unique among physical_ids + * hack up cpubits into 128 packs of 256 cores + * to make cores unique in cpubits */ +#define MAX_CORES_PER_PACK 256 +#define MAX_PACKS 128 + +int cpu_procs_cores_threads(int *p, int *c, int *t) { +    cpubits *threads, *cores, *packs; +    char *tmp; +    int i, m, pack_id, core_id; +    g_file_get_contents("/sys/devices/system/cpu/present", &tmp, NULL, NULL); +    if (tmp != NULL) { +        threads = cpubits_from_str(tmp); +        cores = cpubits_from_str(""); +        packs = cpubits_from_str(""); +        m = cpubits_max(threads); +        for (i = 0; i <= m; i++) { +            pack_id = get_cpu_int("topology/physical_package_id", i, CPU_TOPO_NULL); +            core_id = get_cpu_int("topology/core_id", i, CPU_TOPO_NULL); +            if (pack_id >= 0) { CPUBIT_SET(packs, pack_id); } +            if (core_id >= 0) { CPUBIT_SET(cores, (pack_id * MAX_CORES_PER_PACK) + core_id ); } +        } +        *t = cpubits_count(threads); +        *c = cpubits_count(cores); +        *p = cpubits_count(packs); +        if (!*c) *c = 1; +        if (!*p) *p = 1; +        free(threads); +        free(cores); +        free(packs); +        free(tmp); +        return 1; +    } else { +        *p = *c = *t = -1; +        return 0; +    } +} + +cpufreq_data *cpufreq_new(gint id) +{ +    cpufreq_data *cpufd; +    cpufd = malloc(sizeof(cpufreq_data)); +    if (cpufd) { +        memset(cpufd, 0, sizeof(cpufreq_data)); +        cpufd->id = id; +        cpufreq_update(cpufd, 0); +    } +    return cpufd; +} + +void cpufreq_update(cpufreq_data *cpufd, int cur_only) +{ +    if (cpufd) { +        cpufd->cpukhz_cur = get_cpu_int("cpufreq/scaling_cur_freq", cpufd->id, 0); +        if (cur_only) return; +        cpufd->scaling_driver = get_cpu_str("cpufreq/scaling_driver", cpufd->id); +        cpufd->scaling_governor = get_cpu_str("cpufreq/scaling_governor", cpufd->id); +        cpufd->transition_latency = get_cpu_int("cpufreq/cpuinfo_transition_latency", cpufd->id, 0); +        cpufd->cpukhz_min = get_cpu_int("cpufreq/scaling_min_freq", cpufd->id, 0); +        cpufd->cpukhz_max = get_cpu_int("cpufreq/scaling_max_freq", cpufd->id, 0); +        if (cpufd->scaling_driver == NULL) cpufd->scaling_driver = g_strdup("(Unknown)"); +        if (cpufd->scaling_governor == NULL) cpufd->scaling_governor = g_strdup("(Unknown)"); +    } +} + +void cpufreq_free(cpufreq_data *cpufd) +{ +    if (cpufd) { +        g_free(cpufd->scaling_driver); +        g_free(cpufd->scaling_governor); +    } +    g_free(cpufd); +} + +cpu_topology_data *cputopo_new(gint id) +{ +    cpu_topology_data *cputd; +    cputd = malloc(sizeof(cpu_topology_data)); +    if (cputd) { +        memset(cputd, 0, sizeof(cpu_topology_data)); +        cputd->id = id; +        cputd->socket_id = get_cpu_int("topology/physical_package_id", id, CPU_TOPO_NULL); +        cputd->core_id = get_cpu_int("topology/core_id", id, CPU_TOPO_NULL); +        cputd->book_id = get_cpu_int("topology/book_id", id, CPU_TOPO_NULL); +        cputd->drawer_id = get_cpu_int("topology/drawer_id", id, CPU_TOPO_NULL); +    } +    return cputd; + +} + +void cputopo_free(cpu_topology_data *cputd) +{ +    g_free(cputd); +} + +gchar *cpufreq_section_str(cpufreq_data *cpufd) +{ +    if (cpufd == NULL) +        return g_strdup(""); + +    if (cpufd->cpukhz_min || cpufd->cpukhz_max || cpufd->cpukhz_cur) { +        return g_strdup_printf( +                    "[%s]\n" +                    "%s=%d %s\n" +                    "%s=%d %s\n" +                    "%s=%d %s\n" +                    "%s=%d %s\n" +                    "%s=%s\n" +                    "%s=%s\n", +                   _("Frequency Scaling"), +                   _("Minimum"), cpufd->cpukhz_min, _("kHz"), +                   _("Maximum"), cpufd->cpukhz_max, _("kHz"), +                   _("Current"), cpufd->cpukhz_cur, _("kHz"), +                   _("Transition Latency"), cpufd->transition_latency, _("ns"), +                   _("Governor"), cpufd->scaling_governor, +                   _("Driver"), cpufd->scaling_driver); +    } else { +        return g_strdup_printf( +                    "[%s]\n" +                    "%s=%s\n", +                   _("Frequency Scaling"), +                   _("Driver"), cpufd->scaling_driver); +    } +} + +gchar *cputopo_section_str(cpu_topology_data *cputd) +{ +    static const char na[] = N_("(Not Available)"); +    char sock_str[64] = "", core_str[64] = ""; +    char book_str[64] = "", drawer_str[64] = ""; + +    if (cputd == NULL) +        return g_strdup(""); + +    if (cputd->socket_id != CPU_TOPO_NULL && cputd->socket_id != -1) +        sprintf(sock_str, "%s=%d\n", _("Socket"), cputd->socket_id); +    else +        sprintf(sock_str, "%s=%s\n", _("Socket"), na); + +    if (cputd->core_id != CPU_TOPO_NULL) +        sprintf(core_str, "%s=%d\n", _("Core"), cputd->core_id); +    else +        sprintf(core_str, "%s=%s\n", _("Core"), na); + +    if (cputd->book_id != CPU_TOPO_NULL) +        sprintf(core_str, "%s=%d\n", _("Book"), cputd->book_id); +    if (cputd->book_id != CPU_TOPO_NULL) +        sprintf(core_str, "%s=%d\n", _("Drawer"), cputd->drawer_id); + +    return g_strdup_printf( +                    "[%s]\n" +                    "%s=%d\n" +                    "%s%s%s%s", +                   _("Topology"), +                   _("ID"), cputd->id, +                   sock_str, core_str, book_str, drawer_str ); +} diff --git a/modules/devices/cpubits.c b/modules/devices/cpubits.c new file mode 100644 index 00000000..ba9bffc7 --- /dev/null +++ b/modules/devices/cpubits.c @@ -0,0 +1,113 @@ +/* + * rpiz - https://github.com/bp0/rpiz + * Copyright (C) 2017  Burt P. <pburt0@gmail.com> + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. + * + */ + +#include <stdint.h> + +typedef uint32_t cpubits; +uint32_t cpubits_count(cpubits *b); +cpubits *cpubits_from_str(char *str); +char *cpubits_to_str(cpubits *bits, char *str, int max_len); + +#define CPUBITS_SIZE 4096 /* bytes, multiple of sizeof(uint32_t) */ +#define CPUBIT_SET(BITS, BIT) (BITS[BIT/32] |= (1 << BIT%32)) +#define CPUBIT_GET(BITS, BIT) ((BITS[BIT/32] & (1 << BIT%32)) >> BIT%32) +#define CPUBITS_CLEAR(BITS) memset(BITS, 0, CPUBITS_SIZE) + +uint32_t cpubits_count(cpubits *b) { +    static const uint32_t max = CPUBITS_SIZE * 8; +    uint32_t count = 0, i = 0; +    while (i < max) { +        count += CPUBIT_GET(b, i); +        i++; +    } +    return count; +} + +int cpubits_max(cpubits *b) { +    int i = CPUBITS_SIZE * 8; +    while (i >= 0) { +        if (CPUBIT_GET(b, i)) +            break; +        i--; +    } +    return i; +} + +cpubits *cpubits_from_str(char *str) { +    char *v, *nv, *hy; +    int r0, r1; +    cpubits *newbits = malloc(CPUBITS_SIZE); +    if (newbits) { +        memset(newbits, 0, CPUBITS_SIZE); +        if (str != NULL) { +            v = (char*)str; +            while ( *v != 0 ) { +                nv = strchr(v, ',');                /* strchrnul() */ +                if (nv == NULL) nv = strchr(v, 0);  /* equivalent  */ +                hy = strchr(v, '-'); +                if (hy && hy < nv) { +                    r0 = strtol(v, NULL, 0); +                    r1 = strtol(hy + 1, NULL, 0); +                } else { +                    r0 = r1 = strtol(v, NULL, 0); +                } +                for (; r0 <= r1; r0++) { +                    CPUBIT_SET(newbits, r0); +                } +                v = (*nv == ',') ? nv + 1 : nv; +            } +        } +    } +    return newbits; +} + +char *cpubits_to_str(cpubits *bits, char *str, int max_len) { +    static const uint32_t max = CPUBITS_SIZE * 8; +    uint32_t i = 1, seq_start = 0, seq_last = 0, seq = 0, l = 0; +    char buffer[65536] = ""; +    if (CPUBIT_GET(bits, 0)) { +        seq = 1; +        strcpy(buffer, "0"); +    } +    while (i < max) { +        if (CPUBIT_GET(bits, i) ) { +            seq_last = i; +            if (!seq) { +                seq = 1; +                seq_start = i; +                l = strlen(buffer); +                sprintf(buffer + l, "%s%d", l ? "," : "", i); +            } +        } else { +            if (seq && seq_last != seq_start) { +                l = strlen(buffer); +                sprintf(buffer + l, "-%d", seq_last); +            } +            seq = 0; +        } +        i++; +    } +    if (str == NULL) +        return strdup(buffer); +    else { +        strncpy(str, buffer, max_len); +        return str; +    } +} diff --git a/modules/devices/devicetree.c b/modules/devices/devicetree.c new file mode 100644 index 00000000..6fce066a --- /dev/null +++ b/modules/devices/devicetree.c @@ -0,0 +1,272 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org> + * + *    This program 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. + * + *    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; if not, write to the Free Software + *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA + */ +/* + * Device Tree support by Burt P. <pburt0@gmail.com> + * Sources: + *   http://elinux.org/Device_Tree_Usage + *   http://elinux.org/Device_Tree_Mysteries + */ +#include <unistd.h> +#include <sys/types.h> +#include <stdint.h> +#include "hardinfo.h" +#include "devices.h" +#include "cpu_util.h" +#include "dt_util.h" + +#include "devicetree/rpi_data.c" +#include "devicetree/pmac_data.c" + +dtr *dt; +gchar *dtree_info = NULL; + +gchar *get_node(char *np) { +    gchar *nodes = NULL, *props = NULL, *ret = NULL; +    gchar *tmp = NULL, *pstr = NULL, *lstr = NULL; +    gchar *dir_path; +    gchar *node_path; +    const gchar *fn; +    GDir *dir; +    dtr_obj *node, *child; + +    props = g_strdup_printf("[%s]\n", _("Properties") ); +    nodes = g_strdup_printf("[%s]\n", _("Children") ); +    node = dtr_obj_read(dt, np); +    dir_path = dtr_obj_full_path(node); + +    dir = g_dir_open(dir_path, 0 , NULL); +    if (dir) { +        while((fn = g_dir_read_name(dir)) != NULL) { +            child = dtr_get_prop_obj(dt, node, fn); +            pstr = hardinfo_clean_value(dtr_str(child), 1); +            lstr = hardinfo_clean_label(fn, 0); +            if (dtr_obj_type(child) == DT_NODE) { +                tmp = g_strdup_printf("%s%s=%s\n", +                    nodes, lstr, pstr); +                g_free(nodes); +                nodes = tmp; +            } else { +                tmp = g_strdup_printf("%s%s=%s\n", +                    props, lstr, pstr); +                g_free(props); +                props = tmp; +            } +            dtr_obj_free(child); +            g_free(pstr); +            g_free(lstr); +        } +    } +    g_dir_close(dir); +    g_free(dir_path); + +    lstr = dtr_obj_alias(node); +    pstr = dtr_obj_symbol(node); +    ret = g_strdup_printf("[%s]\n" +                    "%s=%s\n" +                    "%s=%s\n" +                    "%s=%s\n" +                    "%s%s", +                    _("Node"), +                    _("Node Path"), dtr_obj_path(node), +                    _("Alias"), (lstr != NULL) ? lstr : _("(None)"), +                    _("Symbol"), (pstr != NULL) ? pstr : _("(None)"), +                    props, nodes); + +    dtr_obj_free(node); +    g_free(props); +    g_free(nodes); +    return ret; +} + +/* different from  dtr_get_string() in that it re-uses the existing dt */ +char *get_dt_string(char *path, int decode) { +    dtr_obj *obj; +    char *ret = NULL; +    if (decode) { +        obj = dtr_get_prop_obj(dt, NULL, path); +        ret = dtr_str(obj); +        dtr_obj_free(obj); +    } else +        ret = dtr_get_prop_str(dt, NULL, path); +    return ret; +} + +gchar *get_summary() { +    char *model = NULL, *compat = NULL; +    char *tmp[10]; +    char *ret = NULL; + +    model = get_dt_string("/model", 0); +    compat = get_dt_string("/compatible", 1); +    UNKIFNULL(model); +    EMPIFNULL(compat); + +    /* Expand on the DT information from known machines, like RPi. +     * RPi stores a revision value in /proc/cpuinfo that can be used +     * to look up details. This is just a nice place to pull it all +     * together for DT machines, with a nice fallback. +     * PPC Macs could be handled this way too. They store +     * machine identifiers in /proc/cpuinfo. */ +    if ( strstr(model, "Raspberry Pi") != NULL +        || strstr(compat, "raspberrypi") != NULL ) { +        tmp[0] = get_dt_string("/serial-number", 1); +        tmp[1] = get_dt_string("/soc/gpu/compatible", 1); +        tmp[9] = rpi_board_details(); +        tmp[8] = g_strdup_printf( +                "[%s]\n" "%s=%s\n" "%s=%s\n", +                _("Platform"), +                _("Compatible"), compat, +                _("GPU-compatible"), tmp[1] ); +        if (tmp[9] != NULL) { +            ret = g_strdup_printf("%s%s", tmp[9], tmp[8]); +        } else { +            ret = g_strdup_printf( +                "[%s]\n" "%s=%s\n" "%s=%s\n" "%s=%s\n" "%s", +                _("Raspberry Pi or Compatible"), +                _("Model"), model, +                _("Serial Number"), tmp[0], +                _("RCode"), _("No revision code available; unable to lookup model details."), +                tmp[8]); +        } +        free(tmp[0]); free(tmp[1]); +        free(tmp[9]); free(tmp[8]); +    } + +    /* Power Macintosh */ +    if (strstr(compat, "PowerBook") != NULL +         || strstr(compat, "MacRISC") != NULL +         || strstr(compat, "Power Macintosh") != NULL) { +        tmp[9] =  ppc_mac_details(); +        if (tmp[9] != NULL) { +            tmp[0] = get_dt_string("/serial-number", 1); +            ret = g_strdup_printf( +                "%s[%s]\n" "%s=%s\n", tmp[9], +                _("More"), +                _("Serial Number"), tmp[0] ); +            free(tmp[0]); +        } +        free(tmp[9]); +    } + +    /* fallback */ +    if (ret == NULL) { +        tmp[0] = get_dt_string("/serial-number", 1); +        EMPIFNULL(tmp[0]); +        ret = g_strdup_printf( +                "[%s]\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n", +                _("Board"), +                _("Model"), model, +                _("Serial Number"), tmp[0], +                _("Compatible"), compat); +        free(tmp[0]); +    } +    free(model); +    return ret; +} + +void mi_add(const char *key, const char *value) { +    gchar *ckey, *rkey; + +    ckey = hardinfo_clean_label(key, 0); +    rkey = g_strdup_printf("%s:%s", "DTREE", ckey); + +    dtree_info = h_strdup_cprintf("$%s$%s=\n", dtree_info, rkey, ckey); +    moreinfo_add_with_prefix("DEV", rkey, g_strdup(value)); + +    g_free(ckey); +    g_free(rkey); +} + +void add_keys(char *np) { +    gchar *dir_path, *dt_path; +    gchar *ftmp, *ntmp; +    gchar *n_info; +    const gchar *fn; +    GDir *dir; +    dtr_obj *obj; + +    /* add self */ +    obj = dtr_obj_read(dt, np); +    dt_path = dtr_obj_path(obj); +    n_info = get_node(dt_path); +    mi_add(dt_path, n_info); + +    dir_path = g_strdup_printf("%s/%s", dtr_base_path(dt), np); +    dir = g_dir_open(dir_path, 0 , NULL); +    if (dir) { +        while((fn = g_dir_read_name(dir)) != NULL) { +            ftmp = g_strdup_printf("%s/%s", dir_path, fn); +            if ( g_file_test(ftmp, G_FILE_TEST_IS_DIR) ) { +                if (strcmp(np, "/") == 0) +                    ntmp = g_strdup_printf("/%s", fn); +                else +                    ntmp = g_strdup_printf("%s/%s", np, fn); +                add_keys(ntmp); +                g_free(ntmp); +            } +            g_free(ftmp); +        } +    } +    g_dir_close(dir); +} + +char *msg_section(int dump) { +    gchar *aslbl = NULL; +    gchar *messages = dtr_messages(dt); +    gchar *ret = g_strdup_printf("[%s]\n", _("Messages")); +    gchar **lines = g_strsplit(messages, "\n", 0); +    int i = 0; +    while(lines[i] != NULL) { +        aslbl = hardinfo_clean_label(lines[i], 0); +        ret = appf(ret, "%s=\n", aslbl); +        g_free(aslbl); +        i++; +    } +    g_strfreev(lines); +    if (dump) +        printf("%s", messages); +    g_free(messages); +    return ret; +} + +void __scan_dtree() +{ +    dt = dtr_new(NULL); +    gchar *summary = get_summary(); +    gchar *maps = dtr_maps_info(dt); +    gchar *messages = NULL; + +    dtree_info = g_strdup("[Device Tree]\n"); +    mi_add("Summary", summary); +    mi_add("Maps", maps); + +    if(dtr_was_found(dt)) +        add_keys("/"); +    messages = msg_section(0); +    mi_add("Messages", messages); + +    //printf("%s\n", dtree_info); + +    g_free(summary); +    g_free(maps); +    g_free(messages); +    dtr_free(dt); +} diff --git a/modules/devices/devicetree/dt_util.c b/modules/devices/devicetree/dt_util.c new file mode 100644 index 00000000..9678042d --- /dev/null +++ b/modules/devices/devicetree/dt_util.c @@ -0,0 +1,1040 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org> + * + *    This program 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. + * + *    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; if not, write to the Free Software + *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA + */ +/* + * Device Tree support by Burt P. <pburt0@gmail.com> + * Sources: + *   http://elinux.org/Device_Tree_Usage + *   http://elinux.org/Device_Tree_Mysteries + */ +#include <unistd.h> +#include <sys/types.h> +#include <endian.h> +#include "hardinfo.h" +#include "dt_util.h" + +static struct { +    char *name; int type; +} prop_types[] = { +    { "name", DTP_STR }, +    { "compatible", DTP_STR }, +    { "model", DTP_STR }, +    { "reg", DTP_REG }, +    { "clocks", DTP_CLOCKS }, +    { "gpios", DTP_GPIOS }, +    { "cs-gpios", DTP_GPIOS }, +    { "phandle", DTP_PH }, +    { "interrupts", DTP_INTRUPT }, +    { "interrupts-extended", DTP_INTRUPT_EX }, +    { "interrupt-parent", DTP_PH_REF }, +    { "interrupt-controller", DTP_EMPTY }, +    { "regulator-min-microvolt", DTP_UINT }, +    { "regulator-max-microvolt", DTP_UINT }, +    { "clock-frequency", DTP_UINT }, +    { "dmas", DTP_DMAS }, +    { "dma-channels", DTP_UINT }, +    { "dma-requests", DTP_UINT }, +    { NULL, 0 }, +}; + +static struct { +    char *name; uint32_t v; +} default_values[] = { +    { "#address-cells", 2 }, +    { "#size-cells", 1 }, +    { "#dma-cells", 1 }, +    { NULL, 0 }, +}; + +struct _dtr_map { +    uint32_t v;  /* phandle */ +    char *label;  /* alias */ +    char *path; +    struct _dtr_map *next; +}; +typedef struct _dtr_map dtr_map; + +struct _dtr { +    dtr_map *aliases; +    dtr_map *symbols; +    dtr_map *phandles; +    char *base_path; +    char *log; +}; + +struct _dtr_obj { +    char *path; +    union { +        void *data; +        char *data_str; +        dt_uint *data_int; +    }; +    char *name; +    uint32_t length; +    int type; +    char *prefix;        /* if the name has a manufacturer's prefix or null */ +    char *np_name;       /* the name without any prefix. points into .prefix or .name, do not free */ +    const char *alias;  /* null until first dtr_obj_alias(). do not free */ +    const char *symbol; /* null until first dtr_obj_symbol(). do not free */ +    dtr *dt; +}; + +dtr_map *dtr_map_add(dtr_map *map, uint32_t v, const char *label, const char *path) { +    dtr_map *it; +    dtr_map *nmap = malloc(sizeof(dtr_map)); +    memset(nmap, 0, sizeof(dtr_map)); +    nmap->v = v; + +    if (label != NULL) nmap->label = strdup(label); +    if (path != NULL) nmap->path = strdup(path); +    if (map == NULL) +        return nmap; + +    it = map; +    while(it->next != NULL) +        it = it->next; +    it->next = nmap; + +    return nmap; +} + +void dtr_map_free(dtr_map *map) { +    dtr_map *it; +    while(map != NULL) { +        it = map->next; +        free(map->label); +        free(map->path); +        free(map); +        map = it; +    } +} + +/* simple sort for maps + * sv: 1 = sort by v, 0 = sort by label */ +void dtr_map_sort(dtr_map *map, int sv) +{ +    int done = 0, cmp; +    dtr_map *this, *next, *top, *next_top; +    uint32_t tmp_v; +    char *tmp_l, *tmp_p; +    if (map == NULL) return; +    do { +        this = map; +        next_top = NULL; +        while(this != NULL) { +            next = this->next; +            if (this == top) +                break; +            if (next == NULL) +                break; +            if (sv) +                cmp = (this->v > next->v) ? 1 : 0; +            else +                cmp = strcmp(this->label, next->label); +            if (cmp > 0) { +                tmp_v = this->v; this->v = next->v; next->v = tmp_v; +                tmp_l = this->label; this->label = next->label; next->label = tmp_l; +                tmp_p = this->path; this->path = next->path; next->path = tmp_p; +                next_top = this; +            } +            this = next; +        } +        if (next_top == NULL) +            done = 1; +        else +            top = next_top; +    } while (!done); +} + +const char *dtr_phandle_lookup(dtr *s, uint32_t v) { +    dtr_map *phi = s->phandles; +    /* 0 and 0xffffffff are invalid phandle values */ +    /* TODO: perhaps "INVALID" or something */ +    if (v == 0 || v == 0xffffffff) +        return NULL; +    while(phi != NULL) { +        if (phi->v == v) +            return phi->path; +        phi = phi->next; +    } +    return NULL; +} + +const char *dtr_alias_lookup(dtr *s, const char* label) { +    dtr_map *ali = s->aliases; +    while(ali != NULL) { +        if (strcmp(ali->label, label) == 0) +            return ali->path; +        ali = ali->next; +    } +    return NULL; +} + +const char *dtr_alias_lookup_by_path(dtr *s, const char* path) { +    dtr_map *ali = s->aliases; +    while(ali != NULL) { +        if (strcmp(ali->path, path) == 0) +            return ali->label; +        ali = ali->next; +    } +    return NULL; +} + +const char *dtr_symbol_lookup_by_path(dtr *s, const char* path) { +    dtr_map *ali = s->symbols; +    while(ali != NULL) { +        if (strcmp(ali->path, path) == 0) +            return ali->label; +        ali = ali->next; +    } +    return NULL; +} + +void _dtr_read_aliases(dtr *); +void _dtr_read_symbols(dtr *); +void _dtr_map_phandles(dtr *, char *np); + +const char *dtr_find_device_tree_root() { +    char *candidates[] = { +        "/proc/device-tree", +        "/sys/firmware/devicetree/base", +        /* others? */ +        NULL +    }; +    int i = 0; +    while (candidates[i] != NULL) { +        if(access(candidates[i], F_OK) != -1) +            return candidates[i]; +        i++; +    } +    return NULL; +} + +dtr *dtr_new_x(const char *base_path, int fast) { +    dtr *dt = malloc(sizeof(dtr)); +    if (dt != NULL) { +        memset(dt, 0, sizeof(dtr)); +        dt->log = strdup(""); + +        if (base_path == NULL) +            base_path = DTR_ROOT; + +        if (base_path != NULL) +            dt->base_path = strdup(base_path); +        else { +            dtr_msg(dt, "%s", "Device Tree not found."); +            return dt; +        } + +        /* build alias and phandle lists */ +        dt->aliases = NULL; +        dt->symbols = NULL; +        dt->phandles = NULL; +        if (!fast) { +            _dtr_read_aliases(dt); +            _dtr_read_symbols(dt); +            _dtr_map_phandles(dt, ""); +        } +    } +    return dt; +} + +dtr *dtr_new(const char *base_path) { +    return dtr_new_x(base_path, 0); +} + +void dtr_free(dtr *s) { +    if (s != NULL) { +        dtr_map_free(s->aliases); +        dtr_map_free(s->symbols); +        dtr_map_free(s->phandles); +        free(s->base_path); +        free(s->log); +        free(s); +    } +} + +int dtr_was_found(dtr *s) { +    if (s != NULL) { +        if (s->base_path != NULL) +            return 1; +    } +    return 0; +} + +void dtr_msg(dtr *s, char *fmt, ...) { +    gchar *buf, *tmp; +    va_list args; + +    va_start(args, fmt); +    buf = g_strdup_vprintf(fmt, args); +    va_end(args); + +    tmp = g_strdup_printf("%s%s", s->log, buf); +    g_free(s->log); +    s->log = tmp; +} + +char *dtr_messages(dtr *s) { +    if (s != NULL) +        return strdup(s->log); +    else +        return NULL; +} + +const char *dtr_base_path(dtr *s) { +    if (s) +        return s->base_path; +    return NULL; +} + +/*glib, but _dt_obj *prop uses malloc() and std types */ +dtr_obj *dtr_obj_read(dtr *s, const char *dtp) { +    char *full_path; +    char *slash, *coma; +    dtr_obj *obj; + +    if (dtp == NULL) +        return NULL; + +    obj = malloc(sizeof(dtr_obj)); +    if (obj != NULL) { +        memset(obj, 0, sizeof(dtr_obj)); + +        obj->dt = s; +        if (*dtp != '/') { +            /* doesn't start with slash, use alias */ +            obj->path = (char*)dtr_alias_lookup(s, dtp); +            if (obj->path != NULL) +                obj->path = strdup(obj->path); +            else { +                dtr_obj_free(obj); +                return NULL; +            } +        } else +            obj->path = strdup(dtp); + +        /* find name after last slash, or start */ +        slash = strrchr(obj->path, '/'); +        if (slash != NULL) +            obj->name = strdup(slash + 1); +        else +            obj->name = strdup(obj->path); + +        /* find manufacturer prefix */ +        obj->prefix = strdup(obj->name); +        coma = strchr(obj->prefix, ','); +        if (coma != NULL) { +            /* coma -> null; .np_name starts after */ +            *coma = 0; +            obj->np_name = coma + 1; +        } else { +            obj->np_name = obj->name; +            free(obj->prefix); +            obj->prefix = NULL; +        } + +        /* read data */ +        full_path = g_strdup_printf("%s%s", s->base_path, obj->path); +        if ( g_file_test(full_path, G_FILE_TEST_IS_DIR) ) { +            obj->type = DT_NODE; +        } else { +            if (!g_file_get_contents(full_path, (gchar**)&obj->data, (gsize*)&obj->length, NULL)) { +                dtr_obj_free(obj); +                g_free(full_path); +                return NULL; +            } +            obj->type = dtr_guess_type(obj); +        } +        g_free(full_path); + +        return obj; +    } +    return NULL; +} + +void dtr_obj_free(dtr_obj *s) { +    if (s != NULL) { +        free(s->path); +        free(s->name); +        free(s->prefix); +        free(s->data); +        free(s); +    } +} + +int dtr_obj_type(dtr_obj *s) { +    if (s) +        return s->type; +    return DT_TYPE_ERR; +} + +char *dtr_obj_alias(dtr_obj *s) { +    if (s) { +        if (s->alias == NULL) +            s->alias = dtr_alias_lookup_by_path(s->dt, s->path); +        return (char*)s->alias; +    } +    return NULL; +} + +char *dtr_obj_symbol(dtr_obj *s) { +    if (s) { +        if (s->symbol == NULL) +            s->symbol = dtr_symbol_lookup_by_path(s->dt, s->path); +        return (char*)s->symbol; +    } +    return NULL; +} + +char *dtr_obj_path(dtr_obj *s) { +    if (s) +        return s->path; +    return NULL; +} + +char *dtr_obj_full_path(dtr_obj *s) { +    if (s) { +        if (strcmp(s->path, "/") == 0) +            return g_strdup_printf("%s", s->dt->base_path); +        else +            return g_strdup_printf("%s%s", s->dt->base_path, s->path); +    } +    return NULL; +} + +dtr_obj *dtr_get_prop_obj(dtr *s, dtr_obj *node, const char *name) { +    dtr_obj *prop; +    char *ptmp; +    ptmp = g_strdup_printf("%s/%s", (node == NULL) ? "" : node->path, name); +    prop = dtr_obj_read(s, ptmp); +    g_free(ptmp); +    return prop; +} + +char *dtr_get_prop_str(dtr *s, dtr_obj *node, const char *name) { +    dtr_obj *prop; +    char *ptmp; +    char *ret = NULL; + +    ptmp = g_strdup_printf("%s/%s", (node == NULL) ? "" : node->path, name); +    prop = dtr_obj_read(s, ptmp); +    if (prop != NULL && prop->data != NULL) { +        ret = strdup(prop->data_str); +        dtr_obj_free(prop); +    } +    g_free(ptmp); +    return ret; +} + +char *dtr_get_string(const char *p, int decode) { +    dtr *dt = dtr_new_x(NULL, 1); +    dtr_obj *obj; +    char *ret = NULL; +    if (decode) { +        obj = dtr_get_prop_obj(dt, NULL, p); +        ret = dtr_str(obj); +        dtr_obj_free(obj); +    } else +        ret = dtr_get_prop_str(dt, NULL, p); +    dtr_free(dt); +    return ret; +} + +uint32_t dtr_get_prop_u32(dtr *s, dtr_obj *node, const char *name) { +    dtr_obj *prop; +    char *ptmp; +    uint32_t ret = 0; + +    ptmp = g_strdup_printf("%s/%s", (node == NULL) ? "" : node->path, name); +    prop = dtr_obj_read(s, ptmp); +    if (prop != NULL && prop->data != NULL) { +        ret = be32toh(*prop->data_int); +        dtr_obj_free(prop); +    } +    g_free(ptmp); +    return ret; +} + +int dtr_guess_type(dtr_obj *obj) { +    char *tmp, *dash; +    int i = 0, anc = 0, might_be_str = 1; + +    if (obj->length == 0) +        return DTP_EMPTY; + +    /* special #(.*)-cells names are UINT */ +    if (*obj->name == '#') { +        dash = strrchr(obj->name, '-'); +        if (dash != NULL) { +            if (strcmp(dash, "-cells") == 0) +                return DTP_UINT; +        } +    } + +    /* /aliases/* and /__symbols__/* are always strings */ +    if (strncmp(obj->path, "/aliases/", strlen("/aliases/") ) == 0) +        return DTP_STR; +    if (strncmp(obj->path, "/__symbols__/", strlen("/__symbols__/") ) == 0) +        return DTP_STR; + +    /* /__overrides__/* */ +    if (strncmp(obj->path, "/__overrides__/", strlen("/__overrides__/") ) == 0) +        if (strcmp(obj->name, "name") != 0) +            return DTP_OVR; + +    /* lookup known type */ +    while (prop_types[i].name != NULL) { +        if (strcmp(obj->name, prop_types[i].name) == 0) +            return prop_types[i].type; +        i++; +    } + +    /* maybe a string? */ +    for (i = 0; i < obj->length; i++) { +        tmp = obj->data_str + i; +        if ( isalnum(*tmp) ) anc++; /* count the alpha-nums */ +        if ( isprint(*tmp) || *tmp == 0 ) +            continue; +        might_be_str = 0; +        break; +    } +    if (might_be_str && +        ( anc >= obj->length - 2 /* all alpha-nums but ^/ and \0$ */ +          || anc >= 5 ) /*arbitrary*/) +        return DTP_STR; + +    /* multiple of 4 bytes, try list of hex values */ +    if (!(obj->length % 4)) +        return DTP_HEX; + +    return DTP_UNK; +} + +char *dtr_elem_phref(dtr *s, dt_uint e, int show_path) { +    const char *ph_path, *al_label; +    char *ret = NULL; +    ph_path = dtr_phandle_lookup(s, be32toh(e)); +    if (ph_path != NULL) { +        /* TODO: alias or symbol? */ +        al_label = dtr_symbol_lookup_by_path(s, ph_path); +        if (al_label != NULL) { +            if (show_path) +                ret = g_strdup_printf("&%s (%s)", al_label, ph_path); +            else +                ret = g_strdup_printf("&%s", al_label); +        } else { +            if (show_path) +                ret = g_strdup_printf("0x%x (%s)", be32toh(e), ph_path); +        } +    } +    if (ret == NULL) +        ret = dtr_elem_hex(e); +    return ret; +} + +char *dtr_elem_hex(dt_uint e) { +    return g_strdup_printf("0x%x", be32toh(e) ); +} + +char *dtr_elem_byte(uint8_t e) { +    return g_strdup_printf("%x", e); +} + +char *dtr_elem_uint(dt_uint e) { +    return g_strdup_printf("%u", be32toh(e) ); +} + +char *dtr_list_byte(uint8_t *bytes, unsigned long count) { +    char *ret, *dest; +    char buff[4] = "";  /* max element: " 00\0" */ +    uint32_t v; +    unsigned long i, l; +    l = count * 4 + 1; +    ret = malloc(l); +    memset(ret, 0, l); +    strcpy(ret, "["); +    dest = ret + 1; +    for (i = 0; i < count; i++) { +        v = bytes[i]; +        sprintf(buff, "%s%02x", (i) ? " " : "", v); +        l = strlen(buff); +        strncpy(dest, buff, l); +        dest += l; +    } +    strcpy(dest, "]"); +    return ret; +} + +char *dtr_list_hex(dt_uint *list, unsigned long count) { +    char *ret, *dest; +    char buff[12] = "";  /* max element: " 0x00000000\0" */ +    unsigned long i, l; +    l = count * 12 + 1; +    dest = ret = malloc(l); +    memset(ret, 0, l); +    for (i = 0; i < count; i++) { +        sprintf(buff, "%s0x%x", (i) ? " " : "", be32toh(list[i])); +        l = strlen(buff); +        strncpy(dest, buff, l); +        dest += l; +    } +    return ret; +} + +/*cstd, except for g_strescape()*/ +char *dtr_list_str0(const char *data, uint32_t length) { +    char *tmp, *esc, *next_str; +    char ret[1024] = ""; +    uint32_t l, tl; + +    /* treat as null-separated string list */ +    tl = 0; +    strcpy(ret, ""); +    tmp = ret; +    next_str = (char*)data; +    while(next_str != NULL) { +        l = strlen(next_str); +        esc = g_strescape(next_str, NULL); +        sprintf(tmp, "%s\"%s\"", +                strlen(ret) ? ", " : "", esc); +        free(esc); +        tmp += strlen(tmp); +        tl += l + 1; next_str += l + 1; +        if (tl >= length) break; +    } + +    return strdup(ret); +} + +char *dtr_list_override(dtr_obj *obj) { +    /* <phref, string "property:value"> ... */ +    char *ret = NULL; +    char *ph, *str; +    char *src; +    int l, consumed = 0; +    src = obj->data_str; +    while (consumed + 5 <= obj->length) { +        ph = dtr_elem_phref(obj->dt, *(dt_uint*)src, 1); +        src += 4; consumed += 4; +        l = strlen(src) + 1; /* consume the null */ +        str = dtr_list_str0(src, l); +        ret = appf(ret, "<%s -> %s>", ph, str); +        src += l; consumed += l; +        free(ph); +        free(str); +    } +    if (consumed < obj->length) { +        str = dtr_list_byte(src, obj->length - consumed); +        ret = appf(ret, "%s", str); +        free(str); +    } +    return ret; +} + +uint32_t dtr_get_phref_prop(dtr *s, uint32_t phandle, char *prop) { +    const char *ph_path; +    char *tmp; +    uint32_t ret; +    ph_path = dtr_phandle_lookup(s, phandle); +    tmp = g_strdup_printf("%s/%s", ph_path, prop); +    ret = dtr_get_prop_u32(s, NULL, tmp); +    free(tmp); +    return ret; +} + +char *dtr_list_phref(dtr_obj *obj, char *ext_cell_prop) { +    /* <phref, #XXX-cells> */ +    int count = obj->length / 4; +    int i = 0, ext_cells = 0; +    char *ph_path; +    char *ph, *ext, *ret = NULL; +    while (i < count) { +        if (ext_cell_prop == NULL) +            ext_cells = 0; +        else +            ext_cells = dtr_get_phref_prop(obj->dt, be32toh(obj->data_int[i]), ext_cell_prop); +        ph = dtr_elem_phref(obj->dt, obj->data_int[i], 0); i++; +        if (ext_cells > count - i) ext_cells = count - i; +        ext = dtr_list_hex((obj->data_int + i), ext_cells); i+=ext_cells; +        ret = appf(ret, "<%s%s%s>", +            ph, (ext_cells) ? " " : "", ext); +        g_free(ph); +        g_free(ext); +    } +    return ret; +} + +char *dtr_list_interrupts(dtr_obj *obj) { +    char *ext, *ret = NULL; +    uint32_t iparent, icells; +    int count, i = 0; + +    iparent = dtr_inh_find(obj, "interrupt-parent", 0); +    if (!iparent) { +        dtr_msg(obj->dt, "Did not find an interrupt-parent for %s", obj->path); +        goto intr_err; +    } +    icells = dtr_get_phref_prop(obj->dt, iparent, "#interrupt-cells"); +    if (!icells) { +        dtr_msg(obj->dt, "Invalid #interrupt-cells value %d for %s", icells, obj->path); +        goto intr_err; +    } + +    count = obj->length / 4; +    while (i < count) { +        icells = MIN(icells, count - i); +        ext = dtr_list_hex((obj->data_int + i), icells); i+=icells; +        ret = appf(ret, "<%s>", ext); +    } +    return ret; + +intr_err: +    return dtr_list_hex(obj->data_int, obj->length); + +} + +char *dtr_list_reg(dtr_obj *obj) { +    char *tup_str, *ret = NULL; +    uint32_t acells, scells, tup_len; +    uint32_t tups, extra, consumed; /* extra and consumed are bytes */ +    uint32_t *next; + +    acells = dtr_inh_find(obj, "#address-cells", 2); +    scells = dtr_inh_find(obj, "#size-cells", 2); +    tup_len = acells + scells; +    tups = obj->length / (tup_len * 4); +    extra = obj->length % (tup_len * 4); +    consumed = 0; /* bytes */ + +    //printf("list reg: %s\n ... acells: %u, scells: %u, extra: %u\n", obj->path, acells, scells, extra); + +    if (extra) { +        /* error: length is not a multiple of tuples */ +        dtr_msg(obj->dt, "Data length (%u) is not a multiple of (#address-cells:%u + #size-cells:%u) for %s\n", +            obj->length, acells, scells, obj->path); +        return dtr_list_hex(obj->data, obj->length / 4); +    } + +    next = obj->data_int; +    consumed = 0; +    while (consumed + (tup_len * 4) <= obj->length) { +        tup_str = dtr_list_hex(next, tup_len); +        ret = appf(ret, "<%s>", tup_str); +        free(tup_str); +        consumed += (tup_len * 4); +        next += tup_len; +    } + +    //printf(" ... %s\n", ret); +    return ret; +} + +char* dtr_str(dtr_obj *obj) { +    char *ret; +    int type; + +    if (obj == NULL) return NULL; +    type = obj->type; + +    if (type == DTP_PH_REF) { +        if (!DTEX_PHREFS || obj->length != 4) +            type = DTP_HEX; +    } + +    switch(type) { +        case DT_NODE: +            ret = strdup("{node}"); +            break; +        case DTP_EMPTY: +            ret = strdup("{empty}"); +            break; +        case DTP_STR: +            ret = dtr_list_str0(obj->data_str, obj->length); +            break; +        case DTP_OVR: +            ret = dtr_list_override(obj); +            break; +        case DTP_REG: +            /* <#address-cells #size-cells> */ +            ret = dtr_list_reg(obj); +            break; +        case DTP_INTRUPT: +            ret = dtr_list_interrupts(obj); +            break; +        case DTP_INTRUPT_EX: +            /* <phref, #interrupt-cells"> */ +            ret = dtr_list_phref(obj, "#interrupt-cells"); +            break; +        case DTP_CLOCKS: +            /* <phref, #clock-cells"> */ +            ret = dtr_list_phref(obj, "#clock-cells"); +            break; +        case DTP_GPIOS: +            /* <phref, #gpio-cells"> */ +            ret = dtr_list_phref(obj, "#gpio-cells"); +            break; +        case DTP_DMAS: +            /* <phref, #dma-cells"> */ +            ret = dtr_list_phref(obj, "#dma-cells"); +            break; +        case DTP_PH: +        case DTP_HEX: +            if (obj->length % 4) +                ret = dtr_list_byte((uint8_t*)obj->data, obj->length); +            else +                ret = dtr_list_hex(obj->data, obj->length / 4); +            break; +        case DTP_PH_REF: +            ret = dtr_elem_phref(obj->dt, *obj->data_int, 1); +            break; +        case DTP_UINT: +            ret = dtr_elem_uint(*obj->data_int); +            break; +        case DTP_UNK: +        default: +            if (obj->length > 64) /* maybe should use #define at the top */ +                ret = g_strdup_printf(ret, "{data} (%lu bytes)", obj->length); +            else +                ret = dtr_list_byte((uint8_t*)obj->data, obj->length); +            break; +    } + +    return ret; +} + +dtr_obj *dtr_get_parent_obj(dtr_obj *obj) { +    char *slash, *parent; +    dtr_obj *ret = NULL; + +    if (obj == NULL) +        return NULL; + +    parent = strdup(obj->path); +    slash = strrchr(parent, '/'); +    if (slash != NULL) { +        *slash = 0; +        if (strlen(parent) > 0) +            ret = dtr_obj_read(obj->dt, parent); +        else +            ret = dtr_obj_read(obj->dt, "/"); +    } +    free(parent); +    return ret; +} + +/* find the value of a path-inherited property by climbing the path */ +int dtr_inh_find(dtr_obj *obj, char *qprop, int limit) { +    dtr_obj *tobj, *pobj, *qobj; +    uint32_t ret = 0; +    int i, found = 0; + +    if (!limit) limit = 1000; + +    tobj = obj; +    while (tobj != NULL) { +        pobj = dtr_get_parent_obj(tobj); +        if (tobj != obj) +            dtr_obj_free(tobj); +        if (!limit || pobj == NULL) break; +        qobj = dtr_get_prop_obj(obj->dt, pobj, qprop); +        if (qobj != NULL) { +            ret = be32toh(*qobj->data_int); +            found = 1; +            dtr_obj_free(qobj); +            break; +        } +        tobj = pobj; +        limit--; +    } +    dtr_obj_free(pobj); + +    if (!found) { +        i = 0; +        while(default_values[i].name != NULL) { +            if (strcmp(default_values[i].name, qprop) == 0) { +                ret = default_values[i].v; +                dtr_msg(obj->dt, "Using default value %d for %s in %s\n", ret, qprop, obj->path); +                break; +            } +            i++; +        } +    } + +    return ret; +} + +void _dtr_read_aliases(dtr *s) { +    gchar *dir_path; +    GDir *dir; +    const gchar *fn; +    dtr_obj *anode, *prop; +    dtr_map *al; +    anode = dtr_obj_read(s, "/aliases"); + +    dir_path = g_strdup_printf("%s/aliases", s->base_path); +    dir = g_dir_open(dir_path, 0 , NULL); +    if (dir) { +        while((fn = g_dir_read_name(dir)) != NULL) { +            prop = dtr_get_prop_obj(s, anode, fn); +            if (prop->type == DTP_STR) { +                if (*prop->data_str == '/') { +                    al = dtr_map_add(s->aliases, 0, prop->name, prop->data_str); +                    if (s->aliases == NULL) +                        s->aliases = al; +                } +            } +            dtr_obj_free(prop); +        } +    } +    g_dir_close(dir); +    g_free(dir_path); +    dtr_obj_free(anode); +    dtr_map_sort(s->aliases, 0); +} + +void _dtr_read_symbols(dtr *s) { +    gchar *dir_path; +    GDir *dir; +    const gchar *fn; +    dtr_obj *anode, *prop; +    dtr_map *al; +    anode = dtr_obj_read(s, "/__symbols__"); + +    dir_path = g_strdup_printf("%s/__symbols__", s->base_path); +    dir = g_dir_open(dir_path, 0 , NULL); +    if (dir) { +        while((fn = g_dir_read_name(dir)) != NULL) { +            prop = dtr_get_prop_obj(s, anode, fn); +            if (prop->type == DTP_STR) { +                if (*prop->data_str == '/') { +                    al = dtr_map_add(s->symbols, 0, prop->name, prop->data_str); +                    if (s->symbols == NULL) +                        s->symbols = al; +                } +            } +            dtr_obj_free(prop); +        } +    } +    g_dir_close(dir); +    g_free(dir_path); +    dtr_obj_free(anode); +    dtr_map_sort(s->symbols, 0); +} + +/* TODO: rewrite */ +void _dtr_map_phandles(dtr *s, char *np) { +    gchar *dir_path; +    gchar *ftmp, *ntmp, *ptmp; +    const gchar *fn; +    GDir *dir; +    dtr_obj *prop, *ph_prop; +    dtr_map *ph; +    uint32_t phandle; + +    if (np == NULL) np = ""; +    dir_path = g_strdup_printf("%s/%s", s->base_path, np); + +    prop = dtr_obj_read(s, np); +    dir = g_dir_open(dir_path, 0 , NULL); +    if (dir) { +        while((fn = g_dir_read_name(dir)) != NULL) { +            ftmp = g_strdup_printf("%s/%s", dir_path, fn); +            if ( g_file_test(ftmp, G_FILE_TEST_IS_DIR) ) { +                ntmp = g_strdup_printf("%s/%s", np, fn); +                ptmp = g_strdup_printf("%s/phandle", ntmp); +                ph_prop = dtr_obj_read(s, ptmp); +                if (ph_prop != NULL) { +                    ph = dtr_map_add(s->phandles, be32toh(*ph_prop->data_int), NULL, ntmp); +                    if (s->phandles == NULL) +                        s->phandles = ph; +                } +                _dtr_map_phandles(s, ntmp); +                g_free(ptmp); +                g_free(ntmp); +                dtr_obj_free(ph_prop); +            } +            g_free(ftmp); +        } +    } +    g_dir_close(dir); +    dtr_obj_free(prop); +    dtr_map_sort(s->phandles, 1); +} + +/* + * Maybe these should move to devicetree.c, but would have to expose + * struct internals. + */ + +/* kvl: 0 = key is label, 1 = key is v */ +char *dtr_map_info_section(dtr *s, dtr_map *map, char *title, int kvl) { +    gchar *tmp, *ret; +    const gchar *sym; +    ret = g_strdup_printf("[%s]\n", _(title)); +    dtr_map *it = map; +    while(it != NULL) { +        if (kvl) { +            sym = dtr_symbol_lookup_by_path(s, it->path); +            if (sym != NULL) +                tmp = g_strdup_printf("%s0x%x (%s)=%s\n", ret, +                    it->v, sym, it->path); +            else +                tmp = g_strdup_printf("%s0x%x=%s\n", ret, +                    it->v, it->path); +        } else +            tmp = g_strdup_printf("%s%s=%s\n", ret, +                it->label, it->path); +        g_free(ret); +        ret = tmp; +        it = it->next; +    } + +    return ret; +} + +char *dtr_maps_info(dtr *s) { +    gchar *ph_map, *al_map, *sy_map, *ret; + +    ph_map = dtr_map_info_section(s, s->phandles, _("phandle Map"), 1); +    al_map = dtr_map_info_section(s, s->aliases, _("Alias Map"), 0); +    sy_map = dtr_map_info_section(s, s->symbols, _("Symbol Map"), 0); +    ret = g_strdup_printf("%s%s%s", ph_map, sy_map, al_map); +    g_free(ph_map); +    g_free(al_map); +    g_free(sy_map); +    return ret; +} + +char *appf(char *src, char *fmt, ...) { +    gchar *buf, *ret; +    va_list args; + +    va_start(args, fmt); +    buf = g_strdup_vprintf(fmt, args); +    va_end(args); + +    if (src != NULL) { +        ret = g_strdup_printf("%s%s%s", src, sp_sep(src), buf); +        g_free(buf); +        g_free(src); +    } else +        ret = buf; + +    return ret; +} + diff --git a/modules/devices/devicetree/pmac_data.c b/modules/devices/devicetree/pmac_data.c new file mode 100644 index 00000000..b236aef1 --- /dev/null +++ b/modules/devices/devicetree/pmac_data.c @@ -0,0 +1,98 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org> + * + *    This program 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. + * + *    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; if not, write to the Free Software + *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA + */ + +#include "cpu_util.h" /* for PROC_CPUINFO */ + +static gchar *ppc_mac_details(void) { +    int i = 0; +    gchar *ret = NULL; +    gchar *platform = NULL; +    gchar *model = NULL; +    gchar *machine = NULL; +    gchar *motherboard = NULL; +    gchar *detected_as = NULL; +    gchar *pmac_flags = NULL; +    gchar *l2_cache = NULL; +    gchar *pmac_gen = NULL; + +    FILE *cpuinfo; +    gchar buffer[128]; + +    cpuinfo = fopen(PROC_CPUINFO, "r"); +    if (!cpuinfo) +        return NULL; +    while (fgets(buffer, 128, cpuinfo)) { +        gchar **tmp = g_strsplit(buffer, ":", 2); +        if (tmp[1] == NULL) { +            g_strfreev(tmp); +            continue; +        } +        tmp[0] = g_strstrip(tmp[0]); +        tmp[1] = g_strstrip(tmp[1]); +        get_str("platform", platform); +        get_str("model", model); +        get_str("machine", machine); +        get_str("motherboard", motherboard); +        get_str("detected as", detected_as); +        get_str("pmac flags", pmac_flags); +        get_str("L2 cache", l2_cache); +        get_str("pmac-generation", pmac_gen); +    } +    fclose(cpuinfo); + +    if (machine == NULL) +        goto pmd_exit; + +    UNKIFNULL(platform); +    UNKIFNULL(model); +    UNKIFNULL(motherboard); +    UNKIFNULL(detected_as); +    UNKIFNULL(pmac_flags); +    UNKIFNULL(l2_cache); +    UNKIFNULL(pmac_gen); + +    ret = g_strdup_printf("[%s]\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n", +                _("Apple Power Macintosh"), +                _("Platform"), platform, +                _("Model"), model, +                _("Machine"), machine, +                _("Motherboard"), motherboard, +                _("Detected as"), detected_as, +                _("PMAC Flags"), pmac_flags, +                _("L2 Cache"), l2_cache, +                _("PMAC Generation"), pmac_gen ); + +pmd_exit: +    g_free(platform); +    g_free(model); +    g_free(machine); +    g_free(motherboard); +    g_free(detected_as); +    g_free(pmac_flags); +    g_free(l2_cache); +    g_free(pmac_gen); +    return ret; +} diff --git a/modules/devices/devicetree/rpi_data.c b/modules/devices/devicetree/rpi_data.c new file mode 100644 index 00000000..d0132e3a --- /dev/null +++ b/modules/devices/devicetree/rpi_data.c @@ -0,0 +1,166 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2003-2007 Leandro A. F. Pereira <leandro@hardinfo.org> + *    This file from: rpiz - https://github.com/bp0/rpiz + *    Copyright (C) 2017  Burt P. <pburt0@gmail.com> + * + *    This program 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. + * + *    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; if not, write to the Free Software + *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA + */ + +static char unk[] = "(Unknown)"; + +/* information table from: http://elinux.org/RPi_HardwareHistory */ +static struct { +    char *value, *intro, *model, *pcb, *mem, *mfg, *soc; +} rpi_boardinfo[] = { +/*  Value        Introduction  Model Name             PCB rev.  Memory(spec)   Manufacturer  SOC(spec) * + *                             Raspberry Pi %s                                                         */ +  { unk,         unk,          unk,                   unk,      unk,        unk,             NULL }, +  { "Beta",      "Q1 2012",    "B (Beta)",            unk,      "256MB",    "(Beta board)",  NULL }, +  { "0002",      "Q1 2012",    "B",                   "1.0",    "256MB",    unk,             "BCM2835" }, +  { "0003",      "Q3 2012",    "B (ECN0001)",         "1.0",    "256MB",    "(Fuses mod and D14 removed)",   NULL }, +  { "0004",      "Q3 2012",    "B",                   "2.0",    "256MB",    "Sony",          NULL }, +  { "0005",      "Q4 2012",    "B",                   "2.0",    "256MB",    "Qisda",         NULL }, +  { "0006",      "Q4 2012",    "B",                   "2.0",    "256MB",    "Egoman",        NULL }, +  { "0007",      "Q1 2013",    "A",                   "2.0",    "256MB",    "Egoman",        NULL }, +  { "0008",      "Q1 2013",    "A",                   "2.0",    "256MB",    "Sony",          NULL }, +  { "0009",      "Q1 2013",    "A",                   "2.0",    "256MB",    "Qisda",         NULL }, +  { "000d",      "Q4 2012",    "B",                   "2.0",    "512MB",    "Egoman",        NULL }, +  { "000e",      "Q4 2012",    "B",                   "2.0",    "512MB",    "Sony",          NULL }, +  { "000f",      "Q4 2012",    "B",                   "2.0",    "512MB",    "Qisda",         NULL }, +  { "0010",      "Q3 2014",    "B+",                  "1.0",    "512MB",    "Sony",          NULL }, +  { "0011",      "Q2 2014",    "Compute Module 1",    "1.0",    "512MB",    "Sony",          NULL }, +  { "0012",      "Q4 2014",    "A+",                  "1.1",    "256MB",    "Sony",          NULL }, +  { "0013",      "Q1 2015",    "B+",                  "1.2",    "512MB",    unk,             NULL }, +  { "0014",      "Q2 2014",    "Compute Module 1",    "1.0",    "512MB",    "Embest",        NULL }, +  { "0015",      unk,          "A+",                  "1.1",    "256MB/512MB",    "Embest",      NULL  }, +  { "a01040",    unk,          "2 Model B",           "1.0",    "1GB",      "Sony",          "BCM2836" }, +  { "a01041",    "Q1 2015",    "2 Model B",           "1.1",    "1GB",      "Sony",          "BCM2836" }, +  { "a21041",    "Q1 2015",    "2 Model B",           "1.1",    "1GB",      "Embest",        "BCM2836" }, +  { "a22042",    "Q3 2016",    "2 Model B",           "1.2",    "1GB",      "Embest",        "BCM2837" },  /* (with BCM2837) */ +  { "900021",    "Q3 2016",    "A+",                  "1.1",    "512MB",    "Sony",          NULL }, +  { "900032",    "Q2 2016?",    "B+",                 "1.2",    "512MB",    "Sony",          NULL }, +  { "900092",    "Q4 2015",    "Zero",                "1.2",    "512MB",    "Sony",          NULL }, +  { "900093",    "Q2 2016",    "Zero",                "1.3",    "512MB",    "Sony",          NULL }, +  { "920093",    "Q4 2016?",   "Zero",                "1.3",    "512MB",    "Embest",        NULL }, +  { "9000c1",    "Q1 2017",    "Zero W",              "1.1",    "512MB",    "Sony",          NULL }, +  { "a02082",    "Q1 2016",    "3 Model B",           "1.2",    "1GB",      "Sony",          "BCM2837" }, +  { "a020a0",    "Q1 2017",    "Compute Module 3 or CM3 Lite",  "1.0",    "1GB",    "Sony",          NULL }, +  { "a22082",    "Q1 2016",    "3 Model B",           "1.2",    "1GB",      "Embest",        "BCM2837" }, +  { "a32082",    "Q4 2016",    "3 Model B",           "1.2",    "1GB",      "Sony Japan",    NULL  }, +  { NULL, NULL, NULL, NULL, NULL, NULL, NULL } +}; + + +/* return number of chars to skip */ +static int rpi_ov_check(const char *r_code) { +    /* sources differ. prefix is either 1000... or just 1... */ +    //if (strncmp(r, "1000", 4) == 0) +    //    return 4; +    if (strncmp(r_code, "1", 1) == 0) +        return 1; +    return 0; +} + +static int rpi_code_match(const char* code0, const char* code1) { +    int c0, c1; +    if (code0 == NULL || code1 == NULL) return 0; +    c0 = strtol(code0, NULL, 16); +    c1 = strtol(code1, NULL, 16); +    if (c0 && c1) +        return (c0 == c1) ? 1 : 0; +    else +        return (strcmp(code0, code1) == 0) ? 1 : 0; +} + +static int rpi_find_board(const char *r_code) { +    int i = 0; +    char *r = (char*)r_code; +    if (r_code == NULL) +        return 0; +    /* ignore the overvolt prefix */ +    r += rpi_ov_check(r_code); +    while (rpi_boardinfo[i].value != NULL) { +        if (rpi_code_match(r, rpi_boardinfo[i].value)) +            return i; + +        i++; +    } +    return 0; +} + +/* ------------------------- */ + +#include "cpu_util.h" /* for PROC_CPUINFO */ + +static gchar *rpi_board_details(void) { +    int i = 0; +    gchar *ret = NULL; +    gchar *soc = NULL; +    gchar *serial = NULL; +    gchar *revision = NULL; +    int ov = 0; +    FILE *cpuinfo; +    gchar buffer[128]; + +    cpuinfo = fopen(PROC_CPUINFO, "r"); +    if (!cpuinfo) +        return NULL; +    while (fgets(buffer, 128, cpuinfo)) { +        gchar **tmp = g_strsplit(buffer, ":", 2); +        if (tmp[1] == NULL) { +            g_strfreev(tmp); +            continue; +        } +        tmp[0] = g_strstrip(tmp[0]); +        tmp[1] = g_strstrip(tmp[1]); +        get_str("Revision", revision); +        get_str("Hardware", soc); +        get_str("Serial", serial); +    } +    fclose(cpuinfo); + +    if (revision == NULL || soc == NULL) { +        g_free(soc); +        g_free(revision); +        return NULL; +    } + +    ov = rpi_ov_check(revision); +    i = rpi_find_board(revision); +    ret = g_strdup_printf("[%s]\n" +                "%s=%s %s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n" +                "%s=%s\n", +                _("Raspberry Pi"), +                _("Board Name"), _("Raspberry Pi"), rpi_boardinfo[i].model, +                _("PCB Revision"), rpi_boardinfo[i].pcb, +                _("Introduction"), rpi_boardinfo[i].intro, +                _("Manufacturer"), rpi_boardinfo[i].mfg, +                _("RCode"), rpi_boardinfo[i].value, +                _("SOC (spec)"), rpi_boardinfo[i].soc, +                _("Memory (spec)"), rpi_boardinfo[i].mem, +                _("Serial Number"), serial, +                _("Permanent overvolt bit"), (ov) ? C_("rpi-ov-bit", "Set") : C_("rpi-ov-bit", "Not set") ); + +    g_free(soc); +    g_free(revision); +    return ret; +} diff --git a/modules/devices/devmemory.c b/modules/devices/devmemory.c index 7131536c..080e2bbe 100644 --- a/modules/devices/devmemory.c +++ b/modules/devices/devmemory.c @@ -23,10 +23,10 @@ GHashTable *memlabels = NULL;  void scan_memory_do(void)  { -    gchar **keys, *tmp; +    gchar **keys, *tmp, *tmp_label;      static gint offset = -1;      gint i; -     +      if (offset == -1) {          /* gah. linux 2.4 adds three lines of data we don't need in             /proc/meminfo */ @@ -38,38 +38,42 @@ void scan_memory_do(void)              offset = 0;          }      } -     +      g_file_get_contents("/proc/meminfo", &meminfo, NULL, NULL); -     +      keys = g_strsplit(meminfo, "\n", 0);      g_free(meminfo);      g_free(lginterval); -     +      meminfo = g_strdup("");      lginterval = g_strdup(""); -     +      for (i = offset; keys[i]; i++) {          gchar **newkeys = g_strsplit(keys[i], ":", 0); -         +          if (!newkeys[0]) {              g_strfreev(newkeys);              break;          } -         + +        g_strstrip(newkeys[0]);          g_strstrip(newkeys[1]); -         -        if ((tmp = g_hash_table_lookup(memlabels, newkeys[0]))) { -            g_free(newkeys[0]); -            newkeys[0] = g_strdup(tmp); -        } -         + +        /* try to find a localizable label */ +        tmp = g_hash_table_lookup(memlabels, newkeys[0]); +        if (tmp) +            tmp_label = _(tmp); +        else +            tmp_label = ""; /* or newkeys[0] */ +        /* although it doesn't matter... */ +          moreinfo_add_with_prefix("DEV", newkeys[0], g_strdup(newkeys[1])); -        tmp = g_strconcat(meminfo, newkeys[0], "=", newkeys[1], "\n", NULL); +        tmp = g_strconcat(meminfo, newkeys[0], "=", newkeys[1], "|", tmp_label, "\n", NULL);          g_free(meminfo);          meminfo = tmp; -         +          tmp = g_strconcat(lginterval,                            "UpdateInterval$", newkeys[0], "=1000\n", NULL);          g_free(lginterval); @@ -86,21 +90,21 @@ void init_memory_labels(void)          char *proc_label;          char *real_label;      } proc2real[] = { -        { "MemTotal", N_("Total Memory") }, -        { "MemFree", N_("Free Memory") }, -        { "SwapCached",	N_("Cached Swap") }, -        { "HighTotal", N_("High Memory") }, -        { "HighFree", N_("Free High Memory") }, -        { "LowTotal", N_("Low Memory") }, -        { "LowFree", N_("Free Low Memory") }, -        { "SwapTotal", N_("Virtual Memory") }, -        { "SwapFree", N_("Free Virtual Memory") }, +        { "MemTotal",   N_("Total Memory") }, +        { "MemFree",    N_("Free Memory") }, +        { "SwapCached", N_("Cached Swap") }, +        { "HighTotal",  N_("High Memory") }, +        { "HighFree",   N_("Free High Memory") }, +        { "LowTotal",   N_("Low Memory") }, +        { "LowFree",    N_("Free Low Memory") }, +        { "SwapTotal",  N_("Virtual Memory") }, +        { "SwapFree",   N_("Free Virtual Memory") },          { NULL },      };      gint i;      memlabels = g_hash_table_new(g_str_hash, g_str_equal); -     +      for (i = 0; proc2real[i].proc_label; i++) {          g_hash_table_insert(memlabels, proc2real[i].proc_label,              _(proc2real[i].real_label)); diff --git a/modules/devices/dmi.c b/modules/devices/dmi.c index 61cea65d..5f87df13 100644 --- a/modules/devices/dmi.c +++ b/modules/devices/dmi.c @@ -22,7 +22,7 @@  #include <sys/types.h>  #include "devices.h" -               +  typedef struct _DMIInfo		DMIInfo;  struct _DMIInfo { @@ -35,10 +35,14 @@ DMIInfo dmi_info_table[] = {    { "$BIOS",		NULL,					NULL },    { "Date",		"/sys/class/dmi/id/bios_date",		"bios-release-date" },    { "Vendor",		"/sys/class/dmi/id/bios_vendor",	"bios-vendor" }, -  { "Version",		"/sys/class/dmi/id/bios_version",	"bios-version" }, +  { "Version#0",	"/sys/class/dmi/id/bios_version",	"bios-version" },    { "$Board",		NULL,					NULL },    { "Name",		"/sys/class/dmi/id/board_name",		"baseboard-product-name" },    { "Vendor",		"/sys/class/dmi/id/board_vendor",	"baseboard-manufacturer" }, +  { "$Product",		NULL,					NULL }, +  { "Name",		"/sys/class/dmi/id/product_name",	"system-product-name" }, +  { "Family",		"/sys/class/dmi/id/product_family",     "system-product-family" }, +  { "Version#1",	"/sys/class/dmi/id/product_version",    "system-product-version" },  };  gchar *dmi_info = NULL; @@ -62,16 +66,16 @@ gboolean dmi_get_info_dmidecode()      g_free(dmi_info);      dmi_info = NULL;    } -   +    for (i = 0; i < G_N_ELEMENTS(dmi_info_table); i++) {      info = &dmi_info_table[i]; -     +      if (*(info->name) == '$') {        group = info->name + 1;        dmi_info = h_strdup_cprintf("[%s]\n", dmi_info, group);      } else {        gchar *temp; -       +        if (!info->param)          continue; @@ -84,7 +88,7 @@ gboolean dmi_get_info_dmidecode()            dmi_failed = TRUE;            break;          } -         +          add_to_moreinfo(group, info->name, buffer);          const gchar *url = vendor_get_url(buffer); @@ -115,14 +119,14 @@ gboolean dmi_get_info_dmidecode()          dmi_failed = TRUE;          break;        } -    }                                 +    }    } -   +    if (dmi_failed) {      g_free(dmi_info);      dmi_info = NULL;    } -   +    return !dmi_failed;  } @@ -132,17 +136,17 @@ gboolean dmi_get_info_sys()    gchar buffer[256];    const gchar *group = NULL;    DMIInfo *info; -  gboolean dmi_failed = FALSE; +  gboolean dmi_succeeded = FALSE;    gint i; -   +    if (dmi_info) {      g_free(dmi_info);      dmi_info = NULL;    } -   +    for (i = 0; i < G_N_ELEMENTS(dmi_info_table); i++) {      info = &dmi_info_table[i]; -     +      if (*(info->name) == '$') {        group = info->name + 1;        dmi_info = h_strdup_cprintf("[%s]\n", dmi_info, group); @@ -152,7 +156,7 @@ gboolean dmi_get_info_sys()          fclose(dmi_file);          add_to_moreinfo(group, info->name, buffer); -         +          const gchar *url = vendor_get_url(buffer);          if (url) {            const gchar *vendor = vendor_get_name(buffer); @@ -176,31 +180,34 @@ gboolean dmi_get_info_sys()                                        info->name,                                        g_strstrip(buffer));          } +        dmi_succeeded = TRUE;        } else { -        dmi_failed = TRUE; -        break; +        dmi_info = h_strdup_cprintf("%s=%s\n", +                                    dmi_info, +                                    info->name, +                                    _("(Not available; Perhaps try running HardInfo as root.)") );        } -    }                                 +    }    } -   -  if (dmi_failed) { + +  if (!dmi_succeeded) {      g_free(dmi_info);      dmi_info = NULL;    } -   -  return !dmi_failed; + +  return dmi_succeeded;  }  void __scan_dmi()  {    gboolean dmi_ok; -   +    dmi_ok = dmi_get_info_sys(); -   +    if (!dmi_ok) {      dmi_ok = dmi_get_info_dmidecode();    } -   +    if (!dmi_ok) {      dmi_info = g_strdup("[No DMI information]\n"                          "There was an error retrieving the information.=\n" diff --git a/modules/devices/ia64/processor.c b/modules/devices/ia64/processor.c index 55e5e3a8..c4d06a71 100644 --- a/modules/devices/ia64/processor.c +++ b/modules/devices/ia64/processor.c @@ -18,61 +18,198 @@  #include "hardinfo.h"  #include "devices.h" +#include "cpu_util.h"  GSList *  processor_scan(void)  { -    Processor *processor; +    GSList *procs = NULL; +    Processor *processor = NULL;      FILE *cpuinfo;      gchar buffer[128]; +    gchar *rep_pname = NULL; +    GSList *pi = NULL; -    cpuinfo = fopen("/proc/cpuinfo", "r"); +    cpuinfo = fopen(PROC_CPUINFO, "r");      if (!cpuinfo) -	return NULL; +        return NULL; -    processor = g_new0(Processor, 1); +#define CHECK_FOR(k) (g_str_has_prefix(tmp[0], k))      while (fgets(buffer, 128, cpuinfo)) { -	gchar **tmp = g_strsplit(buffer, ":", 2); +        gchar **tmp = g_strsplit(buffer, ":", 2); +        if (tmp[0] && tmp[1]) { +            tmp[0] = g_strstrip(tmp[0]); +            tmp[1] = g_strstrip(tmp[1]); +        } else { +            g_strfreev(tmp); +            continue; +        } + +        get_str("Processor", rep_pname); + +        if ( CHECK_FOR("processor") ) { +            /* finish previous */ +            if (processor) { +                procs = g_slist_append(procs, processor); +            } + +            /* start next */ +            processor = g_new0(Processor, 1); +            processor->id = atol(tmp[1]); + +            if (rep_pname) +                processor->model_name = g_strdup(rep_pname); -	if (tmp[0] && tmp[1]) { -	    tmp[0] = g_strstrip(tmp[0]); -	    tmp[1] = g_strstrip(tmp[1]); +            g_strfreev(tmp); +            continue; +        } -	    get_str("vendor", processor->model_name); -	    get_str("arch", processor->vendor_id); -	    get_str("family", processor->strmodel); -	    get_float("BogoMIPS", processor->bogomips); +        if (!processor && +            (  CHECK_FOR("vendor") +            || CHECK_FOR("arch") +            || CHECK_FOR("family") ) ) { -	} -	g_strfreev(tmp); +            /* single proc/core may not have "processor : n" */ +            processor = g_new0(Processor, 1); +            processor->id = 0; + +            if (rep_pname) +                processor->model_name = g_strdup(rep_pname); +        } + +        if (processor) { +            get_str("vendor", processor->vendor_id); +            get_str("archrev", processor->archrev); +            get_str("arch", processor->arch); +            get_str("family", processor->family); +            get_str("features", processor->features); +            get_int("model", processor->model); +            get_int("revision", processor->revision); +            get_float("BogoMIPS", processor->bogomips); +            get_float("cpu MHz", processor->cpu_mhz); +            get_int("cpu regs", processor->cpu_regs); +        } +        g_strfreev(tmp);      } -    processor->cpu_mhz = 0.0f; -     +    if (processor) +        procs = g_slist_append(procs, processor); + +    g_free(rep_pname);      fclose(cpuinfo); -    return g_slist_append(NULL, processor); +    /* TODO: redup */ + +    /* data not from /proc/cpuinfo */ +    for (pi = procs; pi; pi = pi->next) { +        processor = (Processor *) pi->data; + +        /* strings can't be null or segfault later */ +        STRIFNULL(processor->model_name, _("IA64 Processor") ); +        UNKIFNULL(processor->vendor_id); +        STRIFNULL(processor->arch, "IA-64"); +        STRIFNULL(processor->archrev, "0"); +        UNKIFNULL(processor->family); +        UNKIFNULL(processor->features); + +        /* topo & freq */ +        processor->cpufreq = cpufreq_new(processor->id); +        processor->cputopo = cputopo_new(processor->id); + +        if (processor->cpufreq->cpukhz_max) +            processor->cpu_mhz = processor->cpufreq->cpukhz_max / 1000; + +    } + +    return procs; +} + +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors);  }  gchar * -processor_get_info(GSList *processors) +processor_get_detailed_info(Processor *processor)  { -        Processor *processor = (Processor *)processors->data; -         -	return g_strdup_printf("[Processor]\n" -                               "Model=%s\n" -	                       "Architecture=%s\n" -	                       "Family=%sMHz\n" -			       "BogoMIPS=%s\n" -	                       "Byte Order=%s\n", -			       processor->model_name, -			       processor->vendor_id, -			       processor->strmodel, -			       processor->bogomips, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -                               "Little Endian" -#else -                               "Big Endian" -#endif -                              ); +    gchar *tmp_cpufreq, *tmp_topology, *ret; + +    tmp_topology = cputopo_section_str(processor->cputopo); +    tmp_cpufreq = cpufreq_section_str(processor->cpufreq); + +    ret = g_strdup_printf("[%s]\n" +                        "%s=%s\n"      /* name */ +                        "%s=%s\n"      /* vendor */ +                        "%s=%s\n"      /* arch */ +                        "%s=%s\n"      /* archrev */ +                        "%s=%s\n"      /* family */ +                        "%s=%d\n"      /* model no. */ +                        "%s=%d\n"      /* revision */ +                        "%s=%.2f %s\n" /* frequency */ +                        "%s=%.2f\n"    /* bogomips */ +                        "%s=%s\n"      /* byte order */ +                        "%s=%d\n"      /* regs */ +                        "%s=%s\n"      /* features */ +                        "%s" /* topology */ +                        "%s" /* frequency scaling */ +                        "%s",/* empty */ +                    _("Processor"), +                    _("Name"), processor->model_name, +                    _("Vendor"), processor->vendor_id, +                    _("Architecture"), processor->arch, +                    _("Architecture Revision"), processor->archrev, +                    _("Family"), processor->family, +                    _("Model"), processor->model, +                    _("Revision"), processor->revision, +                    _("Frequency"), processor->cpu_mhz, _("MHz"), +                    _("BogoMips"), processor->bogomips, +                    _("Byte Order"), byte_order_str(), +                    _("CPU regs"), processor->cpu_regs, +                    _("Features"), processor->features, +                    tmp_topology, +                    tmp_cpufreq, +                    ""); +    g_free(tmp_cpufreq); +    g_free(tmp_topology); +    return ret; +} + +gchar *processor_get_info(GSList * processors) +{ +    Processor *processor; + +    if (g_slist_length(processors) > 1) { +    gchar *ret, *tmp, *hashkey; +    GSList *l; + +    tmp = g_strdup(""); + +    for (l = processors; l; l = l->next) { +        processor = (Processor *) l->data; + +        tmp = g_strdup_printf("%s$CPU%d$%s=%.2f %s\n", +                  tmp, processor->id, +                  processor->model_name, +                  processor->cpu_mhz, _("MHz")); + +        hashkey = g_strdup_printf("CPU%d", processor->id); +        moreinfo_add_with_prefix("DEV", hashkey, +                processor_get_detailed_info(processor)); +           g_free(hashkey); +    } + +    ret = g_strdup_printf("[$ShellParam$]\n" +                  "ViewType=1\n" +                  "[Processors]\n" +                  "%s", tmp); +    g_free(tmp); + +    return ret; +    } + +    processor = (Processor *) processors->data; +    return processor_get_detailed_info(processor);  } diff --git a/modules/devices/inputdevices.c b/modules/devices/inputdevices.c index d3f8847f..cf1728a9 100644 --- a/modules/devices/inputdevices.c +++ b/modules/devices/inputdevices.c @@ -85,55 +85,55 @@ __scan_input_devices(void)  	    if (name && strstr(name, "PC Speaker")) {  	      d = 3;		// INPUT_PCSPKR  	    } -	 -	    tmp = g_strdup_printf("INP%d", ++n); -	    input_list = h_strdup_cprintf("$%s$%s=\n", -					 input_list, -					 tmp, name); -	    input_icons = h_strdup_cprintf("Icon$%s$%s=%s\n", -				 	  input_icons, -					  tmp, name, -					  input_devices[d].icon); -	    gchar *strhash = g_strdup_printf("[Device Information]\n" -					     "Name=%s\n" -					     "Type=%s\n" -					     "Bus=0x%x\n", -					     name, -					     input_devices[d].name, -					     bus); - -	    const gchar *url = vendor_get_url(name); -	    if (url) { -	    	strhash = h_strdup_cprintf("Vendor=%s (%s)\n", -					  strhash, -					  vendor_get_name(name), -					  url); -	    } else { -	    	strhash = h_strdup_cprintf("Vendor=%x\n", -					  strhash, -					  vendor); -	    } -	    strhash = h_strdup_cprintf("Product=0x%x\n" -				      "Version=0x%x\n", -				      strhash, product, version); -	     -            if (phys && phys[1] != 0) { -                 strhash = h_strdup_cprintf("Connected to=%s\n", -                                            strhash, phys); -            } - -	    if (phys && strstr(phys, "ir")) { -		 strhash = h_strdup_cprintf("InfraRed port=yes\n", -				 	     strhash); -	    } -	     -	    moreinfo_add_with_prefix("DEV", tmp, strhash); -	    g_free(tmp); +        tmp = g_strdup_printf("INP%d", ++n); +        input_list = h_strdup_cprintf("$%s$%s=\n", +                     input_list, +                     tmp, name); +        input_icons = h_strdup_cprintf("Icon$%s$%s=%s\n", +                      input_icons, +                      tmp, name, +                      input_devices[d].icon); + +        const gchar *v_url = (gchar*)vendor_get_url(name); +        const gchar *v_name = (gchar*)vendor_get_name(name); +        gchar *v_str = NULL; +        if (v_url != NULL) +            v_str = g_strdup_printf("[0x%x] %s (%s)", vendor, v_name, v_url); +        else +            v_str = g_strdup_printf("0x%x", vendor); +        v_str = hardinfo_clean_value(v_str, 1); +        name = hardinfo_clean_value(name, 1); + +        gchar *strhash = g_strdup_printf("[%s]\n" +                /* Name */   "%s=%s\n" +                /* Type */   "%s=%s\n" +                /* Bus */    "%s=0x%x\n" +                /* Vendor */ "%s=%s\n" +                /* Product */"%s=0x%x\n" +                /* Version */"%s=0x%x\n", +                        _("Device Information"), +                        _("Name"), name, +                        _("Type"), input_devices[d].name, +                        _("Bus"), bus, +                        _("Vendor"), v_str, +                        _("Product"), product, +                        _("Version"), version ); -	    g_free(phys); -	    g_free(name); -	} +        if (phys && phys[1] != 0) { +             strhash = h_strdup_cprintf("%s=%s\n", strhash, _("Connected to"), phys); +        } + +        if (phys && strstr(phys, "ir")) { +            strhash = h_strdup_cprintf("%s=%s\n", strhash, _("InfraRed port"), _("Yes") ); +        } + +        moreinfo_add_with_prefix("DEV", tmp, strhash); +        g_free(tmp); +        g_free(v_str); +        g_free(phys); +        g_free(name); +    }      }      fclose(dev); diff --git a/modules/devices/m68k/processor.c b/modules/devices/m68k/processor.c index d9902428..e030732a 100644 --- a/modules/devices/m68k/processor.c +++ b/modules/devices/m68k/processor.c @@ -18,6 +18,7 @@  #include "hardinfo.h"  #include "devices.h" +#include "cpu_util.h"  GSList *  processor_scan(void) @@ -26,54 +27,66 @@ processor_scan(void)      FILE *cpuinfo;      gchar buffer[128]; -    cpuinfo = fopen("/proc/cpuinfo", "r"); +    cpuinfo = fopen(PROC_CPUINFO, "r");      if (!cpuinfo) -	return NULL; +        return NULL;      processor = g_new0(Processor, 1);      while (fgets(buffer, 128, cpuinfo)) { -	gchar **tmp = g_strsplit(buffer, ":", 2); +        gchar **tmp = g_strsplit(buffer, ":", 2); -	if (tmp[0] && tmp[1]) { -	    tmp[0] = g_strstrip(tmp[0]); -	    tmp[1] = g_strstrip(tmp[1]); +        if (tmp[0] && tmp[1]) { +            tmp[0] = g_strstrip(tmp[0]); +            tmp[1] = g_strstrip(tmp[1]); -	    get_str("CPU", processor->model_name); -	    get_float("Clocking", processor->cpu_mhz); -	    get_float("bogomips", processor->bogomips); - -	    get_str("FPU", processor->has_fpu); -	} -	g_strfreev(tmp); +            get_str("CPU", processor->model_name); +            get_str("MMU", processor->mmu_name); +            get_str("FPU", processor->fpu_name); +            get_float("Clocking", processor->cpu_mhz); +            get_float("BogoMips", processor->bogomips); +            get_str("Calibration", processor->calibration); +        } +        g_strfreev(tmp);      } -     +      gchar *tmp;      tmp = g_strconcat("Motorola ", processor->model_name, NULL);      g_free(processor->model_name);      processor->model_name = tmp; -     +      fclose(cpuinfo);      return g_slist_append(NULL, processor);  } +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors); +} +  gchar *  processor_get_info(GSList *processors)  { -        Processor *processor = (Processor *)processors->data; -         -	return g_strdup_printf("[Processor]\n" -	                       "Name=%s\n" -			       "Frequency=%.2fMHz\n" -			       "BogoMips=%.2f\n" -			       "Byte Order=%s\n", -			       processor->model_name, -			       processor->cpu_mhz, -			       processor->bogomips, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -                               "Little Endian" -#else -                               "Big Endian" -#endif -                               ); +    Processor *processor = (Processor *)processors->data; + +    return g_strdup_printf("[%s]\n" +                        "%s=%s\n"      /* cpu */ +                        "%s=%s\n"      /* mmu */ +                        "%s=%s\n"      /* fpu */ +                        "%s=%.2f %s\n" /* frequency */ +                        "%s=%.2f\n"    /* bogomips */ +                        "%s=%s\n"      /* byte order */ +                        "%s=%s\n",     /* calibration */ +                    _("Processor"), +                    _("Model"), processor->model_name, +                    _("MMU"), processor->mmu_name, +                    _("FPU"), processor->fpu_name, +                    _("Frequency"), processor->cpu_mhz, _("MHz"), +                    _("BogoMips"), processor->bogomips, +                    _("Byte Order"), byte_order_str(), +                    _("Calibration"), processor->calibration +                        );  } diff --git a/modules/devices/mips/processor.c b/modules/devices/mips/processor.c index 86c9b958..b31af7dd 100644 --- a/modules/devices/mips/processor.c +++ b/modules/devices/mips/processor.c @@ -18,6 +18,7 @@  #include "hardinfo.h"  #include "devices.h" +#include "cpu_util.h"  GSList *  processor_scan(void) @@ -26,24 +27,24 @@ processor_scan(void)      FILE *cpuinfo;      gchar buffer[128]; -    cpuinfo = fopen("/proc/cpuinfo", "r"); +    cpuinfo = fopen(PROC_CPUINFO, "r");      if (!cpuinfo) -	return NULL; +        return NULL;      processor = g_new0(Processor, 1);      while (fgets(buffer, 128, cpuinfo)) { -	gchar **tmp = g_strsplit(buffer, ":", 2); +        gchar **tmp = g_strsplit(buffer, ":", 2); -	if (tmp[0] && tmp[1]) { -	    tmp[0] = g_strstrip(tmp[0]); -	    tmp[1] = g_strstrip(tmp[1]); +        if (tmp[0] && tmp[1]) { +            tmp[0] = g_strstrip(tmp[0]); +            tmp[1] = g_strstrip(tmp[1]); -	    get_str("system type", processor->model_name); -	    get_str("cpu model", processor->vendor_id); -	    get_float("cpu MHz", processor->cpu_mhz); -	    get_float("BogoMIPS", processor->bogomips); -	} -	g_strfreev(tmp); +            get_str("system type", processor->vendor_id); +            get_str("cpu model", processor->model_name); +            get_float("cpu MHz", processor->cpu_mhz); +            get_float("BogoMIPS", processor->bogomips); +        } +        g_strfreev(tmp);      }      fclose(cpuinfo); @@ -51,25 +52,30 @@ processor_scan(void)      return g_slist_append(NULL, processor);  } +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors); +} +  gchar *  processor_get_info(GSList *processors)  { -        Processor *processor = (Processor *)processors->data; -         -	return g_strdup_printf("[Processor]\n" -	                       "System Type=%s\n" -	                       "CPU Model=%s\n" -                               "Frequency=%.2fMHz\n" -			       "BogoMIPS=%.2f\n" -			       "Byte Order=%s\n", -			       processor->model_name, -			       processor->vendor_id, -			       processor->cpu_mhz, -			       processor->bogomips, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -                               "Little Endian" -#else -                               "Big Endian" -#endif -			       ); +    Processor *processor = (Processor *)processors->data; + +    return g_strdup_printf("[%s]\n" +                        "%s=%s\n" +                        "%s=%s\n" +                        "%s=%.2f %s\n" /* frequency */ +                        "%s=%.2f\n"    /* bogomips */ +                        "%s=%s\n",     /* byte order */ +                    _("Processor"), +                    _("Model"), processor->model_name, +                    _("System Type"), processor->vendor_id, +                    _("Frequency"), processor->cpu_mhz, _("MHz"), +                    _("BogoMips"), processor->bogomips, +                    _("Byte Order"), byte_order_str() +                   );  } diff --git a/modules/devices/parisc/processor.c b/modules/devices/parisc/processor.c index 83672126..9ca38d12 100644 --- a/modules/devices/parisc/processor.c +++ b/modules/devices/parisc/processor.c @@ -18,70 +18,193 @@  #include "hardinfo.h"  #include "devices.h" +#include "cpu_util.h"  GSList * -processors_scan(void) +processor_scan(void)  { -    Processor *processor; +    GSList *procs = NULL; +    Processor *processor = NULL;      FILE *cpuinfo;      gchar buffer[128]; +    gchar *rep_pname = NULL; +    GSList *pi = NULL; -    cpuinfo = fopen("/proc/cpuinfo", "r"); +    cpuinfo = fopen(PROC_CPUINFO, "r");      if (!cpuinfo) -	return NULL; +        return NULL; -    processor = g_new0(Processor, 1); +#define CHECK_FOR(k) (g_str_has_prefix(tmp[0], k))      while (fgets(buffer, 128, cpuinfo)) { -	gchar **tmp = g_strsplit(buffer, ":", 2); - -	if (tmp[0] && tmp[1]) { -	    tmp[0] = g_strstrip(tmp[0]); -	    tmp[1] = g_strstrip(tmp[1]); - -	    get_str("cpu family", processor->model_name); -	    get_str("cpu", processor->vendor_id); -	    get_float("cpu MHz", processor->cpu_mhz); -	    get_float("bogomips", processor->bogomips); -	     -	    get_str("model name", processor->strmodel); -	     -	    get_int("I-cache", processor->has_fpu); -	    get_int("D-cache", processor->flags); - -	} -	g_strfreev(tmp); +        gchar **tmp = g_strsplit(buffer, ":", 2); +        if (tmp[0] && tmp[1]) { +            tmp[0] = g_strstrip(tmp[0]); +            tmp[1] = g_strstrip(tmp[1]); +        } else { +            g_strfreev(tmp); +            continue; +        } + +        get_str("Processor", rep_pname); + +        if ( CHECK_FOR("processor") ) { +            /* finish previous */ +            if (processor) { +                procs = g_slist_append(procs, processor); +            } + +            /* start next */ +            processor = g_new0(Processor, 1); +            processor->id = atol(tmp[1]); + +            if (rep_pname) +                processor->model_name = g_strdup(rep_pname); + +            g_strfreev(tmp); +            continue; +        } + +        if (!processor && +            (  CHECK_FOR("cpu family") +            || CHECK_FOR("cpu MHz") +            || CHECK_FOR("cpu") ) ) { + +            /* single proc/core may not have "processor : n" */ +            processor = g_new0(Processor, 1); +            processor->id = 0; + +            if (rep_pname) +                processor->model_name = g_strdup(rep_pname); +        } + +        if (processor) { +            get_str("cpu family", processor->cpu_family); +            get_float("cpu MHz", processor->cpu_mhz); +            get_str("cpu", processor->model_name); +            get_float("bogomips", processor->bogomips); +            get_str("model name", processor->strmodel); +            get_str("I-cache", processor->icache_str); +            get_str("D-cache", processor->dcache_str); +            get_str("hversion", processor->hversion); +            get_str("sversion", processor->sversion); +        } +        g_strfreev(tmp);      } +    if (processor) +        procs = g_slist_append(procs, processor); + +    g_free(rep_pname);      fclose(cpuinfo); -    return g_slist_append(NULL, processor); +    /* TODO: redup */ + +    /* data not from /proc/cpuinfo */ +    for (pi = procs; pi; pi = pi->next) { +        processor = (Processor *) pi->data; + +        /* strings can't be null or segfault later */ +        STRIFNULL(processor->model_name, _("PA-RISC Processor") ); +        STRIFNULL(processor->cpu_family, "PA-RISC"); +        UNKIFNULL(processor->strmodel); + +        /* topo & freq */ +        processor->cpufreq = cpufreq_new(processor->id); +        processor->cputopo = cputopo_new(processor->id); + +        if (processor->cpufreq->cpukhz_max) +            processor->cpu_mhz = processor->cpufreq->cpukhz_max / 1000; + +    } + +    return procs; +} + +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors);  }  gchar * -processor_get_info(GSList *processors) +processor_get_detailed_info(Processor *processor) +{ +    gchar *tmp_cpufreq, *tmp_topology, *ret; + +    tmp_topology = cputopo_section_str(processor->cputopo); +    tmp_cpufreq = cpufreq_section_str(processor->cpufreq); + +    ret = g_strdup_printf("[%s]\n" +                        "%s=%s\n" +                        "%s=%s\n" +                        "%s=%s\n"      /* model name */ +                        "%s=%.2f %s\n" /* frequency */ +                        "%s=%.2f\n"    /* bogomips */ +                        "%s=%s\n"      /* byte order */ +                        "%s=%s\n"      /* hversion */ +                        "%s=%s\n"      /* sversion */ +                        "[%s]\n" +                        "I-Cache=%s\n" +                        "D-Cache=%s\n" +                        "%s" /* topology */ +                        "%s" /* frequency scaling */ +                        "%s",/* empty */ +                   _("Processor"), +                   _("Model"), processor->model_name, +                   _("Architecture"), processor->cpu_family, +                   _("System"), processor->strmodel, +                   _("Frequency"), processor->cpu_mhz, _("MHz"), +                   _("BogoMips"), processor->bogomips, +                   _("Byte Order"), byte_order_str(), +                   _("HVersion"), processor->hversion, +                   _("SVersion"), processor->sversion, +                   _("Cache"), +                   processor->icache_str, +                   processor->dcache_str, +                   tmp_topology, +                   tmp_cpufreq, +                    ""); + +    g_free(tmp_cpufreq); +    g_free(tmp_topology); +    return ret; +} + +gchar *processor_get_info(GSList * processors)  { -        Processor *processor = (Processor *)processors->data; -         -	return  g_strdup_printf("[Processor]\n" -	                       "CPU Family=%s\n" -	                       "CPU=%s\n" -                               "Frequency=%.2fMHz\n" -			       "Bogomips=%.2f\n" -			       "Model Name=%s\n" -			       "Byte Order=%s\n" -			       "[Cache]\n" -			       "I-Cache=%s\n" -			       "D-Cache=%s\n", -			       processor->model_name, -			       processor->vendor_id, -			       processor->cpu_mhz, -			       processor->bogomips, -			       processor->strmodel, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -                               "Little Endian", -#else -                               "Big Endian", -#endif -			       processor->has_fpu, -			       processor->flags); +    Processor *processor; + +    if (g_slist_length(processors) > 1) { +    gchar *ret, *tmp, *hashkey; +    GSList *l; + +    tmp = g_strdup(""); + +    for (l = processors; l; l = l->next) { +        processor = (Processor *) l->data; + +        tmp = g_strdup_printf("%s$CPU%d$%s=%.2f %s\n", +                  tmp, processor->id, +                  processor->model_name, +                  processor->cpu_mhz, _("MHz")); + +        hashkey = g_strdup_printf("CPU%d", processor->id); +        moreinfo_add_with_prefix("DEV", hashkey, +                processor_get_detailed_info(processor)); +           g_free(hashkey); +    } + +    ret = g_strdup_printf("[$ShellParam$]\n" +                  "ViewType=1\n" +                  "[Processors]\n" +                  "%s", tmp); +    g_free(tmp); + +    return ret; +    } + +    processor = (Processor *) processors->data; +    return processor_get_detailed_info(processor);  } diff --git a/modules/devices/pci.c b/modules/devices/pci.c index 91ff914d..c1965a63 100644 --- a/modules/devices/pci.c +++ b/modules/devices/pci.c @@ -40,13 +40,13 @@ scan_pci_do(void)      gchar buffer[256], *buf, *strhash = NULL, *strdevice = NULL;      gchar *category = NULL, *name = NULL, *icon, *lspci_path, *command_line = NULL;      gint n = 0, x = 0; -     +      if ((lspci_path = find_program("lspci")) == NULL) {        goto pci_error;      } else {        command_line = g_strdup_printf("%s -v", lspci_path);      } -     +      if (!_pci_devices) {        _pci_devices = g_hash_table_new(g_str_hash, g_str_equal);      } @@ -60,11 +60,11 @@ scan_pci_do(void)        }      } else {        gchar *tmp; -       +        tmp = g_strdup_printf("%s -i '%s'", command_line, buf);        g_free(buf);        buf = tmp; -       +        DEBUG("using updated PCI IDs (from %s)", buf);        if (!(lspci = popen(tmp, "r"))) {          g_free(buf); @@ -103,30 +103,31 @@ scan_pci_do(void)  	    g_strfreev(list);  	    if (irq) -		strdevice = h_strdup_cprintf("IRQ=%d\n", strdevice, irq); +		strdevice = h_strdup_cprintf("%s=%d\n", strdevice, _("IRQ"), irq);  	    if (freq) -		strdevice = h_strdup_cprintf("Frequency=%dMHz\n", strdevice, freq); +		strdevice = h_strdup_cprintf("%s=%d %s\n", strdevice, _("Frequency"), freq, _("MHz") );  	    if (latency) -		strdevice = h_strdup_cprintf("Latency=%d\n", strdevice, latency); +		strdevice = h_strdup_cprintf("%s=%d\n", strdevice, _("Latency"), latency); -	    strdevice = h_strdup_cprintf("Bus Master=%s\n", strdevice, bus_master ? "Yes" : "No"); +	    strdevice = h_strdup_cprintf("%s=%s\n", strdevice, _("Bus Master"), bus_master ? _("Yes") : _("No") );  	} else if (!strncmp(buf, "Kernel modules", 14)) {  	    WALK_UNTIL(' ');  	    WALK_UNTIL(':');  	    buf++; -	     -	    strdevice = h_strdup_cprintf("Kernel modules=%s\n", strdevice, buf); + +	    strdevice = h_strdup_cprintf("%s=%s\n", strdevice, _("Kernel modules"), buf);  	} else if (!strncmp(buf, "Subsystem", 9)) {  	    WALK_UNTIL(' ');  	    buf++;  	    const gchar *oem_vendor_url = vendor_get_url(buf); -            if (oem_vendor_url)  -                strdevice = h_strdup_cprintf("OEM Vendor=%s (%s)\n", +            if (oem_vendor_url) +                strdevice = h_strdup_cprintf(_("%s=%s (%s)\n"),                                              strdevice, +                                            _("OEM Vendor"),                                              vendor_get_name(buf),                                              oem_vendor_url);  	} else if (!strncmp(buf, "Capabilities", 12) -		   && !strstr(buf, "only to root") &&  +		   && !strstr(buf, "only to root") &&  		      !strstr(buf, "access denied")) {  	    WALK_UNTIL(' ');  	    WALK_UNTIL(']'); @@ -144,13 +145,13 @@ scan_pci_do(void)  	    WALK_UNTIL('[');  	    sscanf(buf, "[size=%d%c", &mem, &unit); -	    strdevice = h_strdup_cprintf("Memory#%d=%d%cB (%s%s)\n", -					strdevice, ++x, +	    strdevice = h_strdup_cprintf("%s#%d=%d%cB (%s%s)\n", +					strdevice, _("Memory"), ++x,  					mem,  					(unit == ']') ? ' ' : unit,  					_32bit ? "32-bit, " : "", -					prefetch ? "prefetchable" : -					"non-prefetchable"); +					prefetch ? _("prefetchable") : +					_("non-prefetchable") );  	} else if (!strncmp(buf, "I/O ports at", 12)) {  	    guint io_addr, io_size; @@ -158,8 +159,8 @@ scan_pci_do(void)  	    sscanf(buf, "I/O ports at %x [size=%d]", &io_addr, &io_size);  	    strdevice = -		h_strdup_cprintf("I/O ports at#%d=0x%x - 0x%x\n", -				strdevice, ++x, io_addr, +		h_strdup_cprintf("%s#%d=0x%x - 0x%x\n", +				strdevice, _("I/O ports at"), ++x, io_addr,  				io_addr + io_size - 1);  	} else if ((buf[0] >= '0' && buf[0] <= '9') && (buf[4] == ':' || buf[2] == ':')) {  	    gint bus, device, function, domain; @@ -197,51 +198,57 @@ scan_pci_do(void)              else if (strstr(category, "Multimedia")) icon = "media";              else if (strstr(category, "USB")) icon = "usb";              else icon = "pci"; -             +  	    name = g_strdup(buf);              g_hash_table_insert(_pci_devices,                                  g_strdup_printf("0000:%02x:%02x.%x", bus, device, function),                                  name); -	    strhash = g_strdup_printf("PCI%d", n); -	    strdevice = g_strdup_printf("[Device Information]\n" -					"Name=%s\n" -					"Class=%s\n" -					"Domain=%d\n" -					"Bus, device, function=%d, %d, %d\n", -					name, category, domain, bus, -					device, function); -             +        strhash = g_strdup_printf("PCI%d", n); +        strdevice = g_strdup_printf("[%s]\n" +               /* Name */   "%s=%s\n" +               /* Class */  "%s=%s\n" +               /* Domain */ "%s=%d\n" +               /* Bus, device, function */ +                            "%s=%d, %d, %d\n", +                    _("Device Information"), +                    _("Name"), name, +                    _("Class"), category, +                    _("Domain"), domain, +                    _("Bus, device, function"), +                    bus, device, function); +              const gchar *url = vendor_get_url(name);              if (url) { -                strdevice = h_strdup_cprintf("Vendor=%s (%s)\n", +                strdevice = h_strdup_cprintf("%s=%s (%s)\n",                                              strdevice, +                                            _("Vendor"),                                              vendor_get_name(name),                                              url);              } -             +              g_hash_table_insert(_pci_devices,                                  g_strdup_printf("0000:%02x:%02x.%x", bus, device, function),                                  g_strdup(name)); -             +  	    pci_list = h_strdup_cprintf("$PCI%d$%s=%s\n", pci_list, n, category, name);  	    n++;  	}      } -     +      if (pclose(lspci)) {  pci_error:          /* error (no pci, perhaps?) */ -        pci_list = g_strconcat(pci_list, "No PCI devices found=\n", NULL); +        pci_list = g_strconcat(pci_list, _("No PCI devices found"), "=\n", NULL);      } else if (strhash) { -	/* insert the last device */ +        /* insert the last device */          moreinfo_add_with_prefix("DEV", strhash, strdevice);          g_free(strhash);          g_free(category);          g_free(name);      } -     +      g_free(lspci_path);      g_free(command_line);  } diff --git a/modules/devices/ppc/processor.c b/modules/devices/ppc/processor.c index a7988f97..3360a136 100644 --- a/modules/devices/ppc/processor.c +++ b/modules/devices/ppc/processor.c @@ -18,68 +18,189 @@  #include "hardinfo.h"  #include "devices.h" +#include "cpu_util.h"  GSList *  processor_scan(void)  { -    Processor *processor; +    GSList *procs = NULL; +    Processor *processor = NULL;      FILE *cpuinfo;      gchar buffer[128]; +    gchar *rep_pname = NULL; +    GSList *pi = NULL; -    cpuinfo = fopen("/proc/cpuinfo", "r"); +    cpuinfo = fopen(PROC_CPUINFO, "r");      if (!cpuinfo) -	return NULL; +    return NULL; -    processor = g_new0(Processor, 1); +#define CHECK_FOR(k) (g_str_has_prefix(tmp[0], k))      while (fgets(buffer, 128, cpuinfo)) { -	gchar **tmp = g_strsplit(buffer, ":", 2); +        gchar **tmp = g_strsplit(buffer, ":", 2); +        if (tmp[0] && tmp[1]) { +            tmp[0] = g_strstrip(tmp[0]); +            tmp[1] = g_strstrip(tmp[1]); +        } else { +            g_strfreev(tmp); +            continue; +        } + +        get_str("Processor", rep_pname); + +        if ( CHECK_FOR("processor") ) { +            /* finish previous */ +            if (processor) { +                procs = g_slist_append(procs, processor); +            } + +            /* start next */ +            processor = g_new0(Processor, 1); +            processor->id = atol(tmp[1]); + +            if (rep_pname) +                processor->model_name = g_strdup(rep_pname); -	if (tmp[0] && tmp[1]) { -	    tmp[0] = g_strstrip(tmp[0]); -	    tmp[1] = g_strstrip(tmp[1]); +            g_strfreev(tmp); +            continue; +        } -	    get_str("cpu", processor->model_name); -	    get_str("machine", processor->vendor_id); -	    get_int("L2 cache", processor->cache_size); -	    get_float("clock", processor->cpu_mhz); -	    get_float("bogomips", processor->bogomips); +        if (!processor && +            (  CHECK_FOR("cpu") +            || CHECK_FOR("clock") +            || CHECK_FOR("revision") ) ) { -	} -	g_strfreev(tmp); +            /* single proc/core may not have "processor : n" */ +            processor = g_new0(Processor, 1); +            processor->id = 0; + +            if (rep_pname) +                processor->model_name = g_strdup(rep_pname); +        } + +        if (processor) { +            get_str("cpu", processor->model_name); +            get_str("revision", processor->revision); +            get_float("clock", processor->cpu_mhz); +            get_float("BogoMIPS", processor->bogomips); +        } +        g_strfreev(tmp);      } -     -    gchar *tmp = g_strdup_printf("PowerPC %s (%.2fMHz)", -                                 processor->model_name, -                                 processor->cpu_mhz); -    g_free(processor->model_name); -    processor->model_name = tmp; +    if (processor) +        procs = g_slist_append(procs, processor); + +    g_free(rep_pname);      fclose(cpuinfo); -    return g_slist_append(NULL, processor); +    /* re-duplicate missing data for /proc/cpuinfo variant that de-duplicated it */ +#define REDUP(f) if (dproc->f && !processor->f) processor->f = g_strdup(dproc->f); +    Processor *dproc; +    GSList *l; +    l = procs = g_slist_reverse(procs); +    while (l) { +        processor = l->data; +        if (processor->model_name) { +            dproc = processor; +        } else if (dproc) { +            REDUP(model_name); +            REDUP(revision); +        } +        l = g_slist_next(l); +    } +    procs = g_slist_reverse(procs); + +    /* data not from /proc/cpuinfo */ +    for (pi = procs; pi; pi = pi->next) { +        processor = (Processor *) pi->data; + +        /* strings can't be null or segfault later */ +        STRIFNULL(processor->model_name, _("POWER Processor") ); +        UNKIFNULL(processor->revision); + +        /* topo & freq */ +        processor->cpufreq = cpufreq_new(processor->id); +        processor->cputopo = cputopo_new(processor->id); + +        if (processor->cpufreq->cpukhz_max) +            processor->cpu_mhz = processor->cpufreq->cpukhz_max / 1000; + +    } + +    return procs; +} + +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors);  }  gchar * -processor_get_info(GSList *processors) +processor_get_detailed_info(Processor *processor)  { -        Processor *processor = (Processor *)processors->data; -         -	return g_strdup_printf("[Processor]\n" -	                       "Machine=%s\n" -	                       "CPU=%s\n" -	                       "L2 Cache=%dkB\n" -	                       "Frequency=%.2fMHz\n" -	                       "BogoMips=%.2f\n" -	                       "Byte Order=%s\n", -			       processor->vendor_id, -			       processor->model_name, -			       processor->cache_size, -			       processor->cpu_mhz, -			       processor->bogomips, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -                               "Little Endian" -#else -                               "Big Endian" -#endif -                              ); +    gchar *tmp_cpufreq, *tmp_topology, *ret; + +    tmp_topology = cputopo_section_str(processor->cputopo); +    tmp_cpufreq = cpufreq_section_str(processor->cpufreq); + +    ret = g_strdup_printf("[%s]\n" +                   "%s=%s\n"  /* model */ +                   "%s=%s\n"  /* revision */ +                   "%s=%.2f %s\n" /* frequency */ +                   "%s=%.2f\n"    /* bogomips */ +                   "%s=%s\n"      /* byte order */ +                   "%s" /* topology */ +                   "%s" /* frequency scaling */ +                   "%s",/* empty */ +                   _("Processor"), +                   _("Model"), processor->model_name, +                   _("Revision"), processor->revision, +                   _("Frequency"), processor->cpu_mhz, _("MHz"), +                   _("BogoMips"), processor->bogomips, +                   _("Byte Order"), byte_order_str(), +                   tmp_topology, +                   tmp_cpufreq, +                    ""); +    g_free(tmp_cpufreq); +    g_free(tmp_topology); +    return ret; +} + +gchar *processor_get_info(GSList * processors) +{ +    Processor *processor; + +    if (g_slist_length(processors) > 1) { +    gchar *ret, *tmp, *hashkey; +    GSList *l; + +    tmp = g_strdup(""); + +    for (l = processors; l; l = l->next) { +        processor = (Processor *) l->data; + +        tmp = g_strdup_printf("%s$CPU%d$%s=%.2f %s\n", +                  tmp, processor->id, +                  processor->model_name, +                  processor->cpu_mhz, _("MHz")); + +        hashkey = g_strdup_printf("CPU%d", processor->id); +        moreinfo_add_with_prefix("DEV", hashkey, +                processor_get_detailed_info(processor)); +           g_free(hashkey); +    } + +    ret = g_strdup_printf("[$ShellParam$]\n" +                  "ViewType=1\n" +                  "[Processors]\n" +                  "%s", tmp); +    g_free(tmp); + +    return ret; +    } + +    processor = (Processor *) processors->data; +    return processor_get_detailed_info(processor);  } diff --git a/modules/devices/riscv/processor.c b/modules/devices/riscv/processor.c new file mode 100644 index 00000000..afddf89d --- /dev/null +++ b/modules/devices/riscv/processor.c @@ -0,0 +1,233 @@ +/* + *    HardInfo - Displays System Information + *    Copyright (C) 2003-2006 Leandro A. F. Pereira <leandro@hardinfo.org> + * + *    This program 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. + * + *    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; if not, write to the Free Software + *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA + */ + +/* source: https://github.com/riscv/riscv-linux/blob/riscv-next/arch/riscv/kernel/cpu.c */ + +#include "hardinfo.h" +#include "devices.h" +#include "cpu_util.h" + +#include "riscv_data.h" +#include "riscv_data.c" + +GSList * +processor_scan(void) +{ +    GSList *procs = NULL; +    Processor *processor = NULL; +    FILE *cpuinfo; +    gchar buffer[128]; +    gchar *rep_pname = NULL; +    gchar *tmpfreq_str = NULL; +    GSList *pi = NULL; + +    cpuinfo = fopen(PROC_CPUINFO, "r"); +    if (!cpuinfo) +    return NULL; + +#define CHECK_FOR(k) (g_str_has_prefix(tmp[0], k)) +    while (fgets(buffer, 128, cpuinfo)) { +        gchar **tmp = g_strsplit(buffer, ":", 2); +        if (tmp[0] && tmp[1]) { +            tmp[0] = g_strstrip(tmp[0]); +            tmp[1] = g_strstrip(tmp[1]); +        } else { +            g_strfreev(tmp); +            continue; +        } + +        //get_str("Processor", rep_pname); + +        if ( CHECK_FOR("hart") ) { +            /* finish previous */ +            if (processor) { +                procs = g_slist_append(procs, processor); +            } + +            /* start next */ +            processor = g_new0(Processor, 1); +            processor->id = atol(tmp[1]); + +            if (rep_pname) +                processor->model_name = g_strdup(rep_pname); + +            g_strfreev(tmp); +            continue; +        } + +        if (!processor && +            (  CHECK_FOR("mmu") +            || CHECK_FOR("isa") +            || CHECK_FOR("uarch") ) ) { + +            /* single proc/core may not have "hart : n" */ +            processor = g_new0(Processor, 1); +            processor->id = 0; + +            if (rep_pname) +                processor->model_name = g_strdup(rep_pname); +        } + +        if (processor) { +            get_str("mmu", processor->mmu); +            get_str("isa", processor->isa); +            get_str("uarch", processor->uarch); +        } +        g_strfreev(tmp); +    } + +    if (processor) +        procs = g_slist_append(procs, processor); + +    g_free(rep_pname); +    fclose(cpuinfo); + +    /* TODO: redup */ + +    /* data not from /proc/cpuinfo */ +    for (pi = procs; pi; pi = pi->next) { +        processor = (Processor *) pi->data; + +        /* strings can't be null or segfault later */ +        STRIFNULL(processor->model_name, _("RISC-V Processor") ); +        UNKIFNULL(processor->mmu); +        UNKIFNULL(processor->isa); +        UNKIFNULL(processor->uarch); + +        processor->flags = riscv_isa_to_flags(processor->isa); + +        /* topo & freq */ +        processor->cpufreq = cpufreq_new(processor->id); +        processor->cputopo = cputopo_new(processor->id); + +        if (processor->cpufreq->cpukhz_max) +            processor->cpu_mhz = processor->cpufreq->cpukhz_max / 1000; +        else +            processor->cpu_mhz = 0.0f; +    } + +    return procs; +} + +gchar *processor_get_capabilities_from_flags(gchar * strflags) +{ +    gchar **flags, **old; +    gchar *tmp = NULL; +    gint j = 0; + +    flags = g_strsplit(strflags, " ", 0); +    old = flags; + +    while (flags[j]) { +        const gchar *meaning = riscv_ext_meaning( flags[j] ); + +        if (meaning) { +            tmp = h_strdup_cprintf("%s=%s\n", tmp, flags[j], meaning); +        } else { +            tmp = h_strdup_cprintf("%s=\n", tmp, flags[j]); +        } +        j++; +    } +    if (tmp == NULL || g_strcmp0(tmp, "") == 0) +        tmp = g_strdup_printf("%s=%s\n", "empty", _("Empty List")); + +    g_strfreev(old); +    return tmp; +} + +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors); +} + +gchar * +processor_get_detailed_info(Processor *processor) +{ +    gchar *tmp_flags, *tmp_cpufreq, *tmp_topology, *ret; +    tmp_flags = processor_get_capabilities_from_flags(processor->flags); +    tmp_topology = cputopo_section_str(processor->cputopo); +    tmp_cpufreq = cpufreq_section_str(processor->cpufreq); + +    ret = g_strdup_printf("[%s]\n" +                   "%s=%s\n"  /* model */ +                   "%s=%s\n"  /* isa */ +                   "%s=%s\n"  /* uarch */ +                   "%s=%s\n"  /* mmu */ +                   "%s=%.2f %s\n" /* frequency */ +                   "%s=%s\n"      /* byte order */ +                   "%s" /* topology */ +                   "%s" /* frequency scaling */ +                   "[%s]\n" /* extensions */ +                   "%s" +                   "%s",/* empty */ +                   _("Processor"), +                   _("Model"), processor->model_name, +                   _("Architecture"), processor->isa, +                   _("uarch"), processor->uarch, +                   _("MMU"), processor->mmu, +                   _("Frequency"), processor->cpu_mhz, _("MHz"), +                   _("Byte Order"), byte_order_str(), +                   tmp_topology, +                   tmp_cpufreq, +                   _("Capabilities"), tmp_flags, +                    ""); +    g_free(tmp_flags); +    g_free(tmp_cpufreq); +    g_free(tmp_topology); +    return ret; +} + +gchar *processor_get_info(GSList * processors) +{ +    Processor *processor; + +    if (g_slist_length(processors) > 1) { +    gchar *ret, *tmp, *hashkey; +    GSList *l; + +    tmp = g_strdup(""); + +    for (l = processors; l; l = l->next) { +        processor = (Processor *) l->data; + +        tmp = g_strdup_printf("%s$CPU%d$%s=%.2f %s\n", +                  tmp, processor->id, +                  processor->model_name, +                  processor->cpu_mhz, _("MHz")); + +        hashkey = g_strdup_printf("CPU%d", processor->id); +        moreinfo_add_with_prefix("DEV", hashkey, +                processor_get_detailed_info(processor)); +           g_free(hashkey); +    } + +    ret = g_strdup_printf("[$ShellParam$]\n" +                  "ViewType=1\n" +                  "[Processors]\n" +                  "%s", tmp); +    g_free(tmp); + +    return ret; +    } + +    processor = (Processor *) processors->data; +    return processor_get_detailed_info(processor); +} diff --git a/modules/devices/riscv/riscv_data.c b/modules/devices/riscv/riscv_data.c new file mode 100644 index 00000000..4ae68ef4 --- /dev/null +++ b/modules/devices/riscv/riscv_data.c @@ -0,0 +1,212 @@ +/* + * rpiz - https://github.com/bp0/rpiz + * Copyright (C) 2017  Burt P. <pburt0@gmail.com> + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "riscv_data.h" + +#ifndef C_ +#define C_(Ctx, String) String +#endif +#ifndef NC_ +#define NC_(Ctx, String) String +#endif + +static struct { +    char *name, *meaning; +} tab_ext_meaning[] = { +    { "RV32",  NC_("rv-ext", /*/ext:RV32*/  "RISC-V 32-bit") }, +    { "RV64",  NC_("rv-ext", /*/ext:RV64*/  "RISC-V 64-bit") }, +    { "RV128", NC_("rv-ext", /*/ext:RV128*/ "RISC-V 128-bit") }, +    { "E",     NC_("rv-ext", /*/ext:E*/ "Base embedded integer instructions (15 registers)") }, +    { "I",     NC_("rv-ext", /*/ext:I*/ "Base integer instructions (31 registers)") }, +    { "M",     NC_("rv-ext", /*/ext:M*/ "Hardware integer multiply and divide") }, +    { "A",     NC_("rv-ext", /*/ext:A*/ "Atomic memory operations") }, +    { "C",     NC_("rv-ext", /*/ext:C*/ "Compressed 16-bit instructions") }, +    { "F",     NC_("rv-ext", /*/ext:F*/ "Floating-point instructions, single-precision") }, +    { "D",     NC_("rv-ext", /*/ext:D*/ "Floating-point instructions, double-precision") }, +    { "Q",     NC_("rv-ext", /*/ext:Q*/ "Floating-point instructions, quad-precision") }, +    { "B",     NC_("rv-ext", /*/ext:B*/ "Bit manipulation instructions") }, +    { "V",     NC_("rv-ext", /*/ext:V*/ "Vector operations") }, +    { "T",     NC_("rv-ext", /*/ext:T*/ "Transactional memory") }, +    { "P",     NC_("rv-ext", /*/ext:P*/ "Packed SIMD instructions") }, +    { "L",     NC_("rv-ext", /*/ext:L*/ "Decimal floating-point instructions") }, +    { "J",     NC_("rv-ext", /*/ext:J*/ "Dynamically translated languages") }, +    { "N",     NC_("rv-ext", /*/ext:N*/ "User-level interrupts") }, +    { NULL, NULL } +}; + +static char all_extensions[1024] = ""; + +#define APPEND_EXT(f) strcat(all_extensions, f); strcat(all_extensions, " "); +const char *riscv_ext_list() { +    int i = 0, built = 0; +    built = strlen(all_extensions); +    if (!built) { +        while(tab_ext_meaning[i].name != NULL) { +            APPEND_EXT(tab_ext_meaning[i].name); +            i++; +        } +    } +    return all_extensions; +} + +const char *riscv_ext_meaning(const char *ext) { +    int i = 0, l = 0; +    char *c = NULL; +    if (ext) { +        c = strchr(ext, ':'); /* allow extension:version, ignore version */ +        if (c != NULL) +            l = c - ext; +        else +            l = strlen(ext); +        while(tab_ext_meaning[i].name != NULL) { +            if (strncasecmp(tab_ext_meaning[i].name, ext, l) == 0) { +                if (tab_ext_meaning[i].meaning != NULL) +                    return C_("rv-ext", tab_ext_meaning[i].meaning); +                else return NULL; +            } +            i++; +        } +    } +    return NULL; +} + +/* see RISC-V spec 2.2: Chapter 22: ISA Subset Naming Conventions */ + +/* Spec says case-insensitve, but I prefer single-letter extensions + * capped and version string (like "2p1") with a lowercase p. */ +#define RV_FIX_CASE(fstr,vo) \ +    p = fstr; while (*p != 0 && *p != ':') { if (!vo) *p = toupper(*p); p++; } \ +    if (*p == ':') while (*p != 0) { if (*p == 'P') *p = 'p'; p++; } + +static int riscv_isa_next(const char *isap, char *flag) { +    char *p = NULL, *start = NULL; +    char *next_sep = NULL, *next_digit = NULL; +    int skip_len = 0, tag_len = 0, ver_len = 0; +    char ext_str[32], ver_str[32]; + +    if (isap == NULL) +        return 0; + +    /* find start by skipping any '_' */ +    start = (char*)isap; +    while (*start != 0 && *start == '_') { start++; skip_len++; }; +    if (*start == 0) +        return 0; + +    /* find next '_' or \0 */ +    p = start; while (*p != 0 && *p != '_') { p++; }; next_sep = p; + +    /* find next digit that may be a version, find length of version */ +    p = start; while (*p != 0 && !isdigit(*p)) { p++; }; +    if (isdigit(*p)) next_digit = p; +    if (next_digit) { +        while (*p != 0 && (isdigit(*p) || *p == 'p' || *p == 'P') ) { +            if ((*p == 'p' || *p == 'P') && !isdigit(*(p+1)) ) +                break; +            ver_len++; +            p++; +        } +    } + +    /* is next version nearer than next separator */ +    p = start; +    if (next_digit && next_digit < next_sep) +        tag_len = next_digit - p; +    else { +        tag_len = next_sep - p; +        ver_len = 0; +    } + +    switch(*p) { +        case 'S': case 's': /* supervisor extension */ +        case 'X': case 'x': /* custom extension */ +            /* custom supervisor extension (SX..) handled by S */ +            break; +        default: /* single character (standard) extension */ +            tag_len = 1; +            if (next_digit != p+1) ver_len = 0; +            break; +    } + +    memset(ext_str, 0, 32); +    memset(ver_str, 0, 32); +    if (ver_len) { +        strncpy(ext_str, p, tag_len); +        strncpy(ver_str, next_digit, ver_len); +        sprintf(flag, "%s:%s", ext_str, ver_str); +        if (tag_len == 1) { +            RV_FIX_CASE(flag, 0); +        } else { +            RV_FIX_CASE(flag, 1); +        } +        return skip_len + tag_len + ver_len; +    } else { +        strncpy(ext_str, p, tag_len); +        sprintf(flag, "%s", ext_str); +        if (tag_len == 1) { RV_FIX_CASE(flag, 0); } +        return skip_len + tag_len; +    } +} + +#define FSTR_SIZE 1024 +#define RV_CHECK_FOR(e) ( strncasecmp(ps, e, 2) == 0 ) +#define ADD_EXT_FLAG(ext) el = strlen(ext); strncpy(pd, ext, el); strncpy(pd + el, " ", 1); pd += el + 1; +char *riscv_isa_to_flags(const char *isa) { +    char *flags = NULL, *ps = (char*)isa, *pd = NULL; +    char flag_buf[64] = ""; +    int isa_len = 0, tl = 0, el = 0; /* el used in macro */ + +    if (isa) { +        isa_len = strlen(isa); +        flags = malloc(FSTR_SIZE); +        if (flags) { +            memset(flags, 0, FSTR_SIZE); +            ps = (char*)isa; +            pd = flags; +            if ( RV_CHECK_FOR("RV") ) +            { ps += 2; } +            if ( RV_CHECK_FOR("32") ) +            { ADD_EXT_FLAG("RV32"); ps += 2; } +            else if ( RV_CHECK_FOR("64") ) +            { ADD_EXT_FLAG("RV64"); ps += 2; } +            else if ( RV_CHECK_FOR("128") ) +            { ADD_EXT_FLAG("RV128"); ps += 3; } + +            while( (tl = riscv_isa_next(ps, flag_buf)) ) { +                if (flag_buf[0] == 'G') { /* G = IMAFD */ +                    flag_buf[0] = 'I'; ADD_EXT_FLAG(flag_buf); +                    flag_buf[0] = 'M'; ADD_EXT_FLAG(flag_buf); +                    flag_buf[0] = 'A'; ADD_EXT_FLAG(flag_buf); +                    flag_buf[0] = 'F'; ADD_EXT_FLAG(flag_buf); +                    flag_buf[0] = 'D'; ADD_EXT_FLAG(flag_buf); +                } else { +                    ADD_EXT_FLAG(flag_buf); +                } +                ps += tl; +                if (ps - isa >= isa_len) break; /* just in case */ +            } +        } +    } +    return flags; +} diff --git a/modules/devices/riscv/riscv_data.h b/modules/devices/riscv/riscv_data.h new file mode 100644 index 00000000..1d3a0a48 --- /dev/null +++ b/modules/devices/riscv/riscv_data.h @@ -0,0 +1,33 @@ +/* + * rpiz - https://github.com/bp0/rpiz + * Copyright (C) 2017  Burt P. <pburt0@gmail.com> + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. + * + */ + +#ifndef _RISCVDATA_H_ +#define _RISCVDATA_H_ + +/* convert RISC-V ISA string to flags list */ +char *riscv_isa_to_flags(const char *isa); + +/* all known extensions as flags list */ +const char *riscv_ext_list(void); + +/* get meaning of flag */ +const char *riscv_ext_meaning(const char *ext); + +#endif diff --git a/modules/devices/s390/processor.c b/modules/devices/s390/processor.c index 99f1c8bd..cf45c33c 100644 --- a/modules/devices/s390/processor.c +++ b/modules/devices/s390/processor.c @@ -18,61 +18,163 @@  #include "hardinfo.h"  #include "devices.h" +#include "string.h" +#include "cpu_util.h"  GSList *  processor_scan(void)  { -    Processor *processor; +    GSList *procs = NULL; +    Processor *processor = NULL;      FILE *cpuinfo;      gchar buffer[128]; +    gchar *vendor_id = NULL; +    gint   num_procs = 0; +    gfloat bogomips = 0.0f; +    GSList *pi = NULL; -    cpuinfo = fopen("/proc/cpuinfo", "r"); +    cpuinfo = fopen(PROC_CPUINFO, "r");      if (!cpuinfo) -	return NULL; +    return NULL; -    processor = g_new0(Processor, 1); +#define CHECK_FOR(k) (g_str_has_prefix(tmp[0], k))      while (fgets(buffer, 128, cpuinfo)) { -	gchar **tmp = g_strsplit(buffer, ":", 2); +        gchar **tmp = g_strsplit(buffer, ":", 2); +        if (tmp[0] && tmp[1]) { +            tmp[0] = g_strstrip(tmp[0]); +            tmp[1] = g_strstrip(tmp[1]); +        } else { +            g_strfreev(tmp); +            continue; +        } + +        get_str("vendor_id", vendor_id); +        get_int("# processors", num_procs); +        get_int("bogomips per cpu", bogomips); + +        if ( CHECK_FOR("processor") ) { +            /* finish previous */ +            if (processor) { +                procs = g_slist_append(procs, processor); +            } + +            /* start next */ +            processor = g_new0(Processor, 1); +            if (strlen(tmp[0]) >= 10) +                processor->id = atol(tmp[0] + 10); /* processor n: ... */ +            else +                processor->id = 0; /* idk */ +            processor->proc_str = g_strdup(tmp[1]); -	if (tmp[0] && tmp[1]) { -	    tmp[0] = g_strstrip(tmp[0]); -	    tmp[1] = g_strstrip(tmp[1]); +            if (vendor_id) +                processor->model_name = g_strdup(vendor_id); +            if (bogomips) +                processor->bogomips = bogomips; -	    get_str("vendor_id", processor->vendor_id); -	    get_float("# processors", processor->cache_size); -	    get_int("bogomips per cpu", processor->bogomips); +            g_strfreev(tmp); +            continue; +        } -	} -	g_strfreev(tmp); +        g_strfreev(tmp);      } -    processor->cpu_mhz = 0.0f; -     -    processor->model_name = g_strconcat("S390 ", processor->vendor_id, NULL); -    g_free(processor->vendor_id); +    if (processor) +        procs = g_slist_append(procs, processor); +    g_free(vendor_id);      fclose(cpuinfo); -    return g_slist_append(NULL, processor); +    /* data not from /proc/cpuinfo */ +    for (pi = procs; pi; pi = pi->next) { +        processor = (Processor *) pi->data; + +        /* strings can't be null or segfault later */ +        STRIFNULL(processor->model_name, _("S390 Processor") ); +        UNKIFNULL(processor->proc_str); + +        /* topo & freq */ +        processor->cpufreq = cpufreq_new(processor->id); +        processor->cputopo = cputopo_new(processor->id); + +        if (processor->cpufreq->cpukhz_max) +            processor->cpu_mhz = processor->cpufreq->cpukhz_max / 1000; +        else +            processor->cpu_mhz = 0.0f; + +    } + +    return procs; +} + +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors);  }  gchar * -processor_get_info(GSList *processors) +processor_get_detailed_info(Processor *processor) +{ +    gchar *tmp_cpufreq, *tmp_topology, *ret; +    tmp_topology = cputopo_section_str(processor->cputopo); +    tmp_cpufreq = cpufreq_section_str(processor->cpufreq); + +    ret = g_strdup_printf("[%s]\n" +                        "%s=%s\n"      /* model */ +                        "%s=%s\n"      /* proc string */ +                        "%s=%.2f\n"    /* bogomips */ +                        "%s=%s\n"      /* byte order */ +                        "%s"  /* topology */ +                        "%s", /* frequency scaling */ +                        _("Processor"), +                        _("Model"), processor->model_name, +                        _("ID String"), processor->proc_str, +                        _("BogoMips"), processor->bogomips, +                        _("Byte Order"), byte_order_str(), +                        tmp_topology, +                        tmp_cpufreq +                        ); +    g_free(tmp_cpufreq); +    g_free(tmp_topology); +    return ret; +} + +gchar *processor_get_info(GSList * processors)  { -        Processor *processor = (Processor *)processors->data; -         -	return g_strdup_printf("[Processor]\n" -                               "Model=%s\n" -	                       "Processors=%d\n" -	                       "BogoMips per CPU=%.2f" -	                       "Byte Order=%s\n", -			       processor->model_name, -			       processor->cache_size, -			       processor->bogomips, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -                               "Little Endian" -#else -                               "Big Endian" -#endif -                              ); +    Processor *processor; + +    if (g_slist_length(processors) > 1) { +    gchar *ret, *tmp, *hashkey; +    GSList *l; + +    tmp = g_strdup(""); + +    for (l = processors; l; l = l->next) { +        processor = (Processor *) l->data; + +        tmp = g_strdup_printf("%s$CPU%d$%s=%.2f %s\n", +                  tmp, processor->id, +                  processor->model_name, +                  processor->cpu_mhz, _("MHz")); + +        hashkey = g_strdup_printf("CPU%d", processor->id); +        moreinfo_add_with_prefix("DEV", hashkey, +                processor_get_detailed_info(processor)); +           g_free(hashkey); +    } + +    ret = g_strdup_printf("[$ShellParam$]\n" +                  "ViewType=1\n" +                  "[Processors]\n" +                  "%s", tmp); +    g_free(tmp); + +    return ret; +    } + +    processor = (Processor *) processors->data; +    return processor_get_detailed_info(processor);  } + diff --git a/modules/devices/sensors.c b/modules/devices/sensors.c index 84e89361..c9d78ff7 100644 --- a/modules/devices/sensors.c +++ b/modules/devices/sensors.c @@ -27,8 +27,7 @@ gchar *sensors = NULL;  GHashTable *sensor_compute = NULL;  GHashTable *sensor_labels = NULL; -static void read_sensor_labels(gchar * driver) -{ +static void read_sensor_labels(gchar *driver) {      FILE *conf;      gchar buf[256], *line, *p;      gboolean lock = FALSE; @@ -38,7 +37,8 @@ static void read_sensor_labels(gchar * driver)      conf = fopen("/etc/sensors3.conf", "r");      /* If it fails, try to open sensors.conf */ -    if (!conf) conf = fopen("/etc/sensors.conf", "r"); +    if (!conf) +        conf = fopen("/etc/sensors.conf", "r");      if (!conf) {          /* Cannot open config file. */ @@ -46,117 +46,129 @@ static void read_sensor_labels(gchar * driver)      }      while (fgets(buf, 256, conf)) { -	line = buf; - -	remove_linefeed(line); -	strend(line, '#'); - -	if (*line == '\0') { -	    continue; -	} else if (lock && strstr(line, "label")) {	/* label lines */ -	    gchar **names = g_strsplit(strstr(line, "label") + 5, " ", 0); -	    gchar *name = NULL, *value = NULL; - -	    for (i = 0; names[i]; i++) { -		if (names[i][0] == '\0') -		    continue; - -		if (!name) -		    name = g_strdup(names[i]); -		else if (!value) -		    value = g_strdup(names[i]); -		else -		    value = g_strconcat(value, " ", names[i], NULL); -	    } - -	    remove_quotes(value); -	    g_hash_table_insert(sensor_labels, name, value); - -	    g_strfreev(names); -	} else if (lock && strstr(line, "ignore")) {	/* ignore lines */ -	    p = strstr(line, "ignore") + 6; -	    if (!strchr(p, ' ')) -		continue; - -	    while (*p == ' ') -		p++; -	    g_hash_table_insert(sensor_labels, g_strdup(p), "ignore"); -	} else if (lock && strstr(line, "compute")) {	/* compute lines */ -	    gchar **formulas = -		g_strsplit(strstr(line, "compute") + 7, " ", 0); -	    gchar *name = NULL, *formula = NULL; - -	    for (i = 0; formulas[i]; i++) { -		if (formulas[i][0] == '\0') -		    continue; -		if (formulas[i][0] == ',') -		    break; - -		if (!name) -		    name = g_strdup(formulas[i]); -		else if (!formula) -		    formula = g_strdup(formulas[i]); -		else -		    formula = g_strconcat(formula, formulas[i], NULL); -	    } - -	    g_strfreev(formulas); -	    g_hash_table_insert(sensor_compute, name, -				math_string_to_postfix(formula)); -	} else if (g_str_has_prefix(line, "chip")) {	/* chip lines (delimiter) */ -	    if (lock == FALSE) { -		gchar **chips = g_strsplit(line, " ", 0); - -		for (i = 1; chips[i]; i++) { -		    strend(chips[i], '*'); - -                     if (g_str_has_prefix(chips[i] + 1, driver)) { -			lock = TRUE; -			break; -		    } -		} - -		g_strfreev(chips); -	    } else { -		break; -	    } -	} +        line = buf; + +        remove_linefeed(line); +        strend(line, '#'); + +        if (*line == '\0') { +            continue; +        } else if (lock && strstr(line, "label")) { /* label lines */ +            gchar **names = g_strsplit(strstr(line, "label") + 5, " ", 0); +            gchar *name = NULL, *value = NULL; + +            for (i = 0; names[i]; i++) { +                if (names[i][0] == '\0') +                    continue; + +                if (!name) +                    name = g_strdup(names[i]); +                else if (!value) +                    value = g_strdup(names[i]); +                else +                    value = g_strconcat(value, " ", names[i], NULL); +            } + +            remove_quotes(value); +            g_hash_table_insert(sensor_labels, name, value); + +            g_strfreev(names); +        } else if (lock && strstr(line, "ignore")) { /* ignore lines */ +            p = strstr(line, "ignore") + 6; +            if (!strchr(p, ' ')) +                continue; + +            while (*p == ' ') +                p++; +            g_hash_table_insert(sensor_labels, g_strdup(p), "ignore"); +        } else if (lock && strstr(line, "compute")) { /* compute lines */ +            gchar **formulas = g_strsplit(strstr(line, "compute") + 7, " ", 0); +            gchar *name = NULL, *formula = NULL; + +            for (i = 0; formulas[i]; i++) { +                if (formulas[i][0] == '\0') +                    continue; +                if (formulas[i][0] == ',') +                    break; + +                if (!name) +                    name = g_strdup(formulas[i]); +                else if (!formula) +                    formula = g_strdup(formulas[i]); +                else +                    formula = g_strconcat(formula, formulas[i], NULL); +            } + +            g_strfreev(formulas); +            g_hash_table_insert(sensor_compute, name, +                                math_string_to_postfix(formula)); +        } else if (g_str_has_prefix(line, +                                    "chip")) { /* chip lines (delimiter) */ +            if (lock == FALSE) { +                gchar **chips = g_strsplit(line, " ", 0); + +                for (i = 1; chips[i]; i++) { +                    strend(chips[i], '*'); + +                    if (g_str_has_prefix(chips[i] + 1, driver)) { +                        lock = TRUE; +                        break; +                    } +                } + +                g_strfreev(chips); +            } else { +                break; +            } +        }      }      fclose(conf);  } -static gchar *get_sensor_label(gchar * sensor) -{ +static void add_sensor(const char *type, +                       const char *sensor, +                       const char *driver, +                       double value, +                       const char *unit) { +    char key[64]; + +    sensors = h_strdup_cprintf("%s/%s=%.2f%s|%s\n", sensors, +        driver, sensor, value, unit, type); + +    snprintf(key, sizeof(key), "%s/%s", driver, sensor); +    moreinfo_add_with_prefix("DEV", key, g_strdup_printf("%.2f%s", value, unit)); + +    lginterval = h_strdup_cprintf("UpdateInterval$%s=1000\n", lginterval, key); +} + +static gchar *get_sensor_label(gchar *sensor) {      gchar *ret;      ret = g_hash_table_lookup(sensor_labels, sensor);      if (!ret) -	ret = g_strdup(sensor); +        ret = g_strdup(sensor);      else -	ret = g_strdup(ret); +        ret = g_strdup(ret);      return ret;  } -static float adjust_sensor(gchar * name, float value) -{ +static float adjust_sensor(gchar *name, float value) {      GSList *postfix;      postfix = g_hash_table_lookup(sensor_compute, name);      if (!postfix) -	return value; +        return value;      return math_postfix_eval(postfix, value);  } -static char *get_sensor_path(int number, const char *prefix) -{ +static char *get_sensor_path(int number, const char *prefix) {      return g_strdup_printf("/sys/class/hwmon/hwmon%d/%s", number, prefix);  } -static char *determine_driver_for_hwmon_path(char *path) -{ +static char *determine_driver_for_hwmon_path(char *path) {      char *tmp, *driver;      tmp = g_strdup_printf("%s/device/driver", path); @@ -190,165 +202,171 @@ struct HwmonSensor {      const char *friendly_name;      const char *path_format;      const char *key_format; -    const char *value_format; +    const char *unit;      const float adjust_ratio;      const int begin_at;  };  static const struct HwmonSensor hwmon_sensors[] = { -    { "Cooling Fans",   "%s/fan%d_input",  "fan%d",  "%s (%s)=%.0fRPM\n",       1.0,    1 }, -    { "Temperature",    "%s/temp%d_input", "temp%d", "%s (%s)=%.2f\302\260C\n", 1000.0, 1 }, -    { "Voltage Values", "%s/in%d_input",   "in%d",   "%s (%s)=%.3fV\n",         1000.0, 0 }, -    { NULL,             NULL,              NULL,     NULL,                      0.0,    0 }, +    { +        "Fan", +        "%s/fan%d_input", +        "fan%d", +        "RPM", +        1.0, +        1 +    }, +    { +        "Temperature", +        "%s/temp%d_input", +        "temp%d", +        "\302\260C", +        1000.0, +        1 +    }, +    { +        "Voltage", +        "%s/in%d_input", +        "in%d", +        "V", +        1000.0, +        0 +    }, +    { }  }; -static const char *hwmon_prefix[] = { "device", "", NULL }; +static const char *hwmon_prefix[] = {"device", "", NULL}; -static void read_sensors_hwmon(void) -{ +static void read_sensors_hwmon(void) {      int hwmon, count;      gchar *path_hwmon, *path_sensor, *tmp, *driver, *name, *mon;      const char **prefix; -     +      for (prefix = hwmon_prefix; *prefix; prefix++) { -		hwmon = 0; -		path_hwmon = get_sensor_path(hwmon, *prefix); -		while (path_hwmon && g_file_test(path_hwmon, G_FILE_TEST_EXISTS)) { -			const struct HwmonSensor *sensor; - -			driver = determine_driver_for_hwmon_path(path_hwmon); -			DEBUG("hwmon%d has driver=%s", hwmon, driver); - -			if (!sensor_labels) { -				read_sensor_labels(driver); -			} - -			for (sensor = hwmon_sensors; sensor->friendly_name; sensor++) { -				char *output = NULL; -				DEBUG("current sensor type=%s", sensor->friendly_name); - -					for (count = sensor->begin_at;; count++) { -						path_sensor = g_strdup_printf(sensor->path_format, path_hwmon, count); -						DEBUG("should be reading from %s", path_sensor); -						if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL)) { -							g_free(path_sensor); -							if (count<256) -								continue; // brute-force find all -							else -								break;  -						} - -						mon = g_strdup_printf(sensor->key_format, count); -						name = get_sensor_label(mon); -						if (!g_str_equal(name, "ignore")) { -							output = h_strdup_cprintf(sensor->value_format, -													  output, name, driver, -													  adjust_sensor(mon, -																	atof(tmp) / sensor->adjust_ratio)); -						} - -						g_free(tmp); -						g_free(mon); -						g_free(name); -						g_free(path_sensor); -					} - -					if (output) { -						sensors = g_strconcat(sensors, "[", sensor->friendly_name, "]\n", output, "\n", NULL); -						g_free(output); -					} -			} - -			g_free(path_hwmon); -			g_free(driver); - -			path_hwmon = get_sensor_path(++hwmon, *prefix); -		} - -		g_free(path_hwmon); -	} +        hwmon = 0; +        path_hwmon = get_sensor_path(hwmon, *prefix); +        while (path_hwmon && g_file_test(path_hwmon, G_FILE_TEST_EXISTS)) { +            const struct HwmonSensor *sensor; + +            driver = determine_driver_for_hwmon_path(path_hwmon); +            DEBUG("hwmon%d has driver=%s", hwmon, driver); + +            if (!sensor_labels) { +                read_sensor_labels(driver); +            } + +            for (sensor = hwmon_sensors; sensor->friendly_name; sensor++) { +                DEBUG("current sensor type=%s", sensor->friendly_name); + +                for (count = sensor->begin_at;; count++) { +                    path_sensor = +                        g_strdup_printf(sensor->path_format, path_hwmon, count); +                    DEBUG("should be reading from %s", path_sensor); +                    if (!g_file_get_contents(path_sensor, &tmp, NULL, NULL)) { +                        g_free(path_sensor); +                        if (count < 256) +                            continue; // brute-force find all +                        else +                            break; +                    } + +                    mon = g_strdup_printf(sensor->key_format, count); +                    name = get_sensor_label(mon); +                    if (!g_str_equal(name, "ignore")) { +                        float adjusted = adjust_sensor(mon, +                            atof(tmp) / sensor->adjust_ratio); + +                        add_sensor(sensor->friendly_name, +                                   name, +                                   driver, +                                   adjusted, +                                   sensor->unit); +                    } + +                    g_free(tmp); +                    g_free(mon); +                    g_free(name); +                    g_free(path_sensor); +                } +            } + +            g_free(path_hwmon); +            g_free(driver); + +            path_hwmon = get_sensor_path(++hwmon, *prefix); +        } + +        g_free(path_hwmon); +    }  } -static void read_sensors_acpi(void) -{ +static void read_sensors_acpi(void) {      const gchar *path_tz = "/proc/acpi/thermal_zone";      if (g_file_test(path_tz, G_FILE_TEST_EXISTS)) { -	GDir *tz; - -	if ((tz = g_dir_open(path_tz, 0, NULL))) { -	    const gchar *entry; -	    gchar *temp = g_strdup(""); - -	    while ((entry = g_dir_read_name(tz))) { -		gchar *path = -		    g_strdup_printf("%s/%s/temperature", path_tz, entry); -		gchar *contents; +        GDir *tz; -		if (g_file_get_contents(path, &contents, NULL, NULL)) { -		    int temperature; +        if ((tz = g_dir_open(path_tz, 0, NULL))) { +            const gchar *entry; -		    sscanf(contents, "temperature: %d C", &temperature); +            while ((entry = g_dir_read_name(tz))) { +                gchar *path = +                    g_strdup_printf("%s/%s/temperature", path_tz, entry); +                gchar *contents; -		    temp = h_strdup_cprintf("\n%s=%d\302\260C\n", -					      temp, entry, temperature); +                if (g_file_get_contents(path, &contents, NULL, NULL)) { +                    int temperature; -		    g_free(contents); -		} -	    } +                    sscanf(contents, "temperature: %d C", &temperature); -	    if (*temp != '\0') -    	        sensors = -	    	    h_strdup_cprintf("\n[ACPI Thermal Zone]\n%s", -	    	                    sensors, temp); +                    add_sensor("Temperature", +                               entry, +                               "ACPI Thermal Zone", +                               temperature, +                               "\302\260C"); +                } +            } -	    g_dir_close(tz); -	} +            g_dir_close(tz); +        }      } -  } -static void read_sensors_sys_thermal(void) -{ +static void read_sensors_sys_thermal(void) {      const gchar *path_tz = "/sys/class/thermal";      if (g_file_test(path_tz, G_FILE_TEST_EXISTS)) { -	GDir *tz; - -	if ((tz = g_dir_open(path_tz, 0, NULL))) { -	    const gchar *entry; -	    gchar *temp = g_strdup(""); +        GDir *tz; -	    while ((entry = g_dir_read_name(tz))) { -		gchar *path = -		    g_strdup_printf("%s/%s/temp", path_tz, entry); -		gchar *contents; +        if ((tz = g_dir_open(path_tz, 0, NULL))) { +            const gchar *entry; +            gchar *temp = g_strdup(""); -		if (g_file_get_contents(path, &contents, NULL, NULL)) { -		    int temperature; +            while ((entry = g_dir_read_name(tz))) { +                gchar *path = g_strdup_printf("%s/%s/temp", path_tz, entry); +                gchar *contents; -		    sscanf(contents, "%d", &temperature); +                if (g_file_get_contents(path, &contents, NULL, NULL)) { +                    int temperature; -		    temp = h_strdup_cprintf("\n%s=%.2f\302\260C\n", -					      temp, entry, (1.0*temperature/1000)); +                    sscanf(contents, "%d", &temperature); -		    g_free(contents); -		} -	    } +                    add_sensor("Temperature", +                               entry, +                               "thermal", +                               temperature / 1000.0, +                               "\302\260C"); -	    if (*temp != '\0') -    	        sensors = -	    	    h_strdup_cprintf("\n[ACPI Thermal Zone (sysfs)]\n%s", -	    	                    sensors, temp); +                    g_free(contents); +                } +            } -	    g_dir_close(tz); -	} +            g_dir_close(tz); +        }      } -  } -static void read_sensors_omnibook(void) -{ +static void read_sensors_omnibook(void) {      const gchar *path_ob = "/proc/omnibook/temperature";      gchar *contents; @@ -357,88 +375,79 @@ static void read_sensors_omnibook(void)          sscanf(contents, "CPU temperature: %d C", &temperature); -        sensors = h_strdup_cprintf("\n[Omnibook]\n" -                                  "CPU temperature=%d\302\260C\n", -                                  sensors, temperature); +        add_sensor("Temperature", +                   "CPU", +                   "omnibook", +                   temperature, +                   "\302\260C\n");          g_free(contents);      }  } -static void read_sensors_hddtemp(void) -{ +static void read_sensors_hddtemp(void) {      Socket *s; -    static gchar *old = NULL;      gchar buffer[1024];      gint len = 0; -    if ((s = sock_connect("127.0.0.1", 7634))) { -	while (!len) -	    len = sock_read(s, buffer, sizeof(buffer)); -        sock_close(s); - -	if (len > 2 && buffer[0] == '|' && buffer[1] == '/') { -	    gchar **disks; -	    int i; - -	    g_free(old); - -	    old = g_strdup("[Hard Disk Temperature]\n"); - -	    disks = g_strsplit(buffer, "\n", 0); -	    for (i = 0; disks[i]; i++) { -		gchar **fields = g_strsplit(disks[i] + 1, "|", 5); - -		/* -		 * 0 -> /dev/hda -		 * 1 -> FUJITSU MHV2080AH -		 * 2 -> 41 -		 * 3 -> C -		 */ -		old = h_strdup_cprintf("\n%s (%s)=%s\302\260%s\n", -				      old, -				      fields[1], fields[0], -				      fields[2], fields[3]); - -		g_strfreev(fields); -	    } +    if (!(s = sock_connect("127.0.0.1", 7634))) +        return; -	    g_strfreev(disks); -	} -    } else { -	g_free(old); -	old = NULL; -    } +    while (!len) +        len = sock_read(s, buffer, sizeof(buffer)); +    sock_close(s); + +    if (len > 2 && buffer[0] == '|' && buffer[1] == '/') { +        gchar **disks; +        int i; + +        disks = g_strsplit(buffer, "\n", 0); +        for (i = 0; disks[i]; i++) { +            gchar **fields = g_strsplit(disks[i] + 1, "|", 5); + +            /* +             * 0 -> /dev/hda +             * 1 -> FUJITSU MHV2080AH +             * 2 -> 41 +             * 3 -> C +             */ +            const gchar *unit = strcmp(fields[3], "C") +                ? "\302\260C" : "\302\260F"; +            add_sensor("Hard Drive", +                       fields[1], +                       "hddtemp", +                       atoi(fields[2]), +                       unit); + +            g_strfreev(fields); +        } -    if (old) { -	sensors = g_strconcat(sensors, "\n", old, NULL); +        g_strfreev(disks);      }  } -void scan_sensors_do(void) -{ +void scan_sensors_do(void) {      g_free(sensors); -      sensors = g_strdup(""); +    g_free(lginterval); +    lginterval = g_strdup(""); +      read_sensors_hwmon();      read_sensors_acpi();      read_sensors_sys_thermal();      read_sensors_omnibook();      read_sensors_hddtemp(); -      /* FIXME: Add support for  ibm acpi and more sensors */  } -void sensors_init(void) -{ -    sensor_labels = g_hash_table_new_full(g_str_hash, g_str_equal, -					  g_free, g_free); +void sensors_init(void) { +    sensor_labels = +        g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);      sensor_compute = g_hash_table_new(g_str_hash, g_str_equal);  } -void sensors_shutdown(void) -{ +void sensors_shutdown(void) {      g_hash_table_destroy(sensor_labels);      g_hash_table_destroy(sensor_compute);  } diff --git a/modules/devices/sh/processor.c b/modules/devices/sh/processor.c index cbd9a60a..9da2f9b0 100644 --- a/modules/devices/sh/processor.c +++ b/modules/devices/sh/processor.c @@ -18,6 +18,7 @@  #include "hardinfo.h"  #include "devices.h" +#include "cpu_util.h"  GSList *  processor_scan(void) @@ -26,50 +27,67 @@ processor_scan(void)      FILE *cpuinfo;      gchar buffer[128]; -    cpuinfo = fopen("/proc/cpuinfo", "r"); +    cpuinfo = fopen(PROC_CPUINFO, "r");      if (!cpuinfo) -	return NULL; +        return NULL;      processor = g_new0(Processor, 1);      while (fgets(buffer, 128, cpuinfo)) { -	gchar **tmp = g_strsplit(buffer, ":", 2); +        gchar **tmp = g_strsplit(buffer, ":", 2); -	if (tmp[0] && tmp[1]) { -	    tmp[0] = g_strstrip(tmp[0]); -	    tmp[1] = g_strstrip(tmp[1]); +        if (tmp[0] && tmp[1]) { +            tmp[0] = g_strstrip(tmp[0]); +            tmp[1] = g_strstrip(tmp[1]); -	    get_str("machine", processor->model_name); -	    get_str("cpu type", processor->vendor_id); -	    get_float("bogomips", processor->bogomips); -	    processor->cpu_mhz = processor->bogomips; -	} -	g_strfreev(tmp); +            get_str("machine", processor->vendor_id); +            get_str("cpu type", processor->model_name); +            get_str("cpu family", processor->family); +            get_float("cpu clock", processor->cpu_mhz); +            get_float("bus clock", processor->bus_mhz); +            get_float("module clock", processor->mod_mhz); +            get_float("bogomips", processor->bogomips); +        } +        g_strfreev(tmp);      }      fclose(cpuinfo); +    STRIFNULL(processor->model_name, _("SuperH Processor")); +    UNKIFNULL(processor->vendor_id); +      return g_slist_append(NULL, processor);  } +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors); +} +  gchar *  processor_get_info(GSList *processors)  { -        Processor *processor = (Processor *)processors->data; -         -	return g_strdup_printf("[Processor]\n" -	                       "System Type=%s\n" -	                       "CPU Model=%s\n" -                               "Frequency=%.2fMHz\n" -			       "BogoMIPS=%.2f\n" -			       "Byte Order=%s\n", -			       processor->model_name, -			       processor->vendor_id, -			       processor->cpu_mhz, -			       processor->bogomips, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -                               "Little Endian" -#else -                               "Big Endian" -#endif -			       ); +    Processor *processor = (Processor *)processors->data; + +    return g_strdup_printf("[%s]\n" +                        "%s=%s\n"      /* cpu type */ +                        "%s=%s\n"      /* machine */ +                        "%s=%s\n"      /* family */ +                        "%s=%.2f %s\n" /* frequency */ +                        "%s=%.2f %s\n" /* bus frequency */ +                        "%s=%.2f %s\n" /* module frequency */ +                        "%s=%.2f\n"    /* bogomips */ +                        "%s=%s\n",     /* byte order */ +                    _("Processor"), +                    _("Name"), processor->model_name, +                    _("Machine"), processor->vendor_id, +                    _("Family"), processor->family, +                    _("Frequency"), processor->cpu_mhz, _("MHz"), +                    _("Bus Frequency"), processor->bus_mhz, _("MHz"), +                    _("Module Frequency"), processor->mod_mhz, _("MHz"), +                    _("BogoMips"), processor->bogomips, +                    _("Byte Order"), byte_order_str() +                   );  } diff --git a/modules/devices/sparc/processor.c b/modules/devices/sparc/processor.c index 594117a7..32c7aa94 100644 --- a/modules/devices/sparc/processor.c +++ b/modules/devices/sparc/processor.c @@ -18,6 +18,7 @@  #include "hardinfo.h"  #include "devices.h" +#include "cpu_util.h"  GSList *  processor_scan(void) @@ -26,22 +27,23 @@ processor_scan(void)      FILE *cpuinfo;      gchar buffer[128]; -    cpuinfo = fopen("/proc/cpuinfo", "r"); +    cpuinfo = fopen(PROC_CPUINFO, "r");      if (!cpuinfo) -	return NULL; +        return NULL;      processor = g_new0(Processor, 1);      while (fgets(buffer, 128, cpuinfo)) { -	gchar **tmp = g_strsplit(buffer, ":", 2); +        gchar **tmp = g_strsplit(buffer, ":", 2); -	if (tmp[0] && tmp[1]) { -	    tmp[0] = g_strstrip(tmp[0]); -	    tmp[1] = g_strstrip(tmp[1]); +        if (tmp[0] && tmp[1]) { +            tmp[0] = g_strstrip(tmp[0]); +            tmp[1] = g_strstrip(tmp[1]); -	    get_str("cpu", processor->model_name); -	    get_str("fpu", processor->has_fpu); -	} -	g_strfreev(tmp); +            get_str("cpucaps", processor->cpucaps); +            get_str("cpu", processor->model_name); +            get_str("fpu", processor->has_fpu); +        } +        g_strfreev(tmp);      }      fclose(cpuinfo); @@ -51,14 +53,28 @@ processor_scan(void)      return g_slist_append(NULL, processor);  } +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} + +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors); +} +  gchar *  processor_get_info(GSList *processors)  { -        Processor *processor = (Processor *)processors->data; -         -	return g_strdup_printf("[Processor]\n" -	                       "CPU=%s\n" -	                       "FPU=%s\n", -			       processor->model_name, -			       processor->has_fpu); +    Processor *processor = (Processor *)processors->data; + +    return g_strdup_printf("[%s]\n" +                           "%s=%s\n"   /* cpu */ +                           "%s=%s\n"   /* fpu */ +                           "%s=%s\n"   /* byte order */ +                           "%s=%s\n",  /* caps */ +                   _("Processor"), +                   _("CPU"), processor->model_name, +                   _("FPU"), processor->has_fpu, +                   _("Byte Order"), byte_order_str(), +                   _("Capabilities"), processor->cpucaps +                   );  } diff --git a/modules/devices/spd-decode.c b/modules/devices/spd-decode.c index ac1dd52b..2db4895b 100644 --- a/modules/devices/spd-decode.c +++ b/modules/devices/spd-decode.c @@ -11,12 +11,12 @@   * it under the terms of the GNU General Public License as published by   * the Free Software Foundation; either version 2 of the License, or   * (at your option) any later version. - *  + *   * 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; if not, write to the Free Software   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -1497,13 +1497,16 @@ void scan_spd_do(void)      g_slist_free(dimm_list);      g_free(spd_info); -    spd_info = g_strdup_printf("[SPD]\n" -			       "%s\n" -			       "[$ShellParam$]\n" -			       "ViewType=1\n" -			       "ColumnTitle$TextValue=Bank\n" -			       "ColumnTitle$Extra1=Size\n" -			       "ColumnTitle$Extra2=Manufacturer\n" -			       "ColumnTitle$Value=Model\n" "ShowColumnHeaders=true\n", list); +    spd_info = g_strdup_printf("[%s]\n" +                   "%s\n" +                   "[$ShellParam$]\n" +                   "ViewType=1\n" +                   "ColumnTitle$TextValue=%s\n" /* Bank */ +                   "ColumnTitle$Extra1=%s\n" /* Size */ +                   "ColumnTitle$Extra2=%s\n" /* Manufacturer */ +                   "ColumnTitle$Value=%s\n" /* Model */ +                   "ShowColumnHeaders=true\n", +                   _("SPD"), list, +                   _("Bank"), _("Size"), _("Manufacturer"), _("Model") );      g_free(list);  } diff --git a/modules/devices/usb.c b/modules/devices/usb.c index 3a93a3b6..e5088bd2 100644 --- a/modules/devices/usb.c +++ b/modules/devices/usb.c @@ -41,51 +41,59 @@ void __scan_usb_sysfs_add_device(gchar * endpoint, int n)      version = h_sysfs_read_float(endpoint, "version");      if (!(mxpwr = h_sysfs_read_string(endpoint, "bMaxPower"))) { -    	mxpwr = g_strdup("0 mA"); +    	mxpwr = g_strdup_printf("%d %s", 0 , _("mA") );      }      if (!(manufacturer = h_sysfs_read_string(endpoint, "manufacturer"))) { -    	manufacturer = g_strdup("Unknown"); +    	manufacturer = g_strdup(_("(Unknown)"));      }      if (!(product = h_sysfs_read_string(endpoint, "product"))) { -	if (classid == 9) { -	    product = g_strdup_printf("USB %.2f Hub", version); -	} else { -	    product = g_strdup_printf("Unknown USB %.2f Device (class %d)", version, classid); -	} +        if (classid == 9) { +            product = g_strdup_printf(_(/*/%.2f is version*/ "USB %.2f Hub"), version); +        } else { +            product = g_strdup_printf(_("Unknown USB %.2f Device (class %d)"), version, classid); +        }      } -    const gchar *url = vendor_get_url(manufacturer); -    if (url) { -	tmp = g_strdup_printf("%s (%s)", vendor_get_name(manufacturer), url); -	 -	g_free(manufacturer); -	manufacturer = tmp; +    const gchar *v_url = vendor_get_url(manufacturer); +    const gchar *v_name = vendor_get_name(manufacturer); +    gchar *v_str; +    if (v_url != NULL) { +        v_str = g_strdup_printf("%s (%s)", v_name, v_url); +    } else { +        v_str = g_strdup_printf("%s", manufacturer);      }      tmp = g_strdup_printf("USB%d", n);      usb_list = h_strdup_cprintf("$%s$%s=\n", usb_list, tmp, product); -    strhash = g_strdup_printf("[Device Information]\n" -			      "Product=%s\n" -			      "Manufacturer=%s\n" -			      "Speed=%.2fMbit/s\n" -			      "Max Current=%s\n" -			      "[Misc]\n" -			      "USB Version=%.2f\n" -			      "Class=0x%x\n" -			      "Vendor=0x%x\n" -			      "Product ID=0x%x\n" -			      "Bus=%d\n", -			      product, -			      manufacturer, -			      speed, -			      mxpwr, -			      version, classid, vendor, prodid, bus); +    strhash = g_strdup_printf("[%s]\n" +             /* Product */      "%s=%s\n" +             /* Manufacturer */ "%s=%s\n" +             /* Speed */        "%s=%.2f %s\n" +             /* Max Current */  "%s=%s\n" +                  "[%s]\n" +             /* USB Version */  "%s=%.2f\n" +             /* Class */        "%s=0x%x\n" +             /* Vendor */       "%s=0x%x\n" +             /* Product ID */   "%s=0x%x\n" +             /* Bus */          "%s=%d\n", +                  _("Device Information"), +                  _("Product"), product, +                  _("Manufacturer"), v_str, +                  _("Speed"), speed, _("Mbit/s"), +                  _("Max Current"), mxpwr, +                  _("Misc"), +                  _("USB Version"), version, +                  _("Class"), classid, +                  _("Vendor ID"), vendor, +                  _("Product ID"), prodid, +                  _("Bus"), bus);      moreinfo_add_with_prefix("DEV", tmp, strhash);      g_free(tmp); +    g_free(v_str);      g_free(manufacturer);      g_free(product);      g_free(mxpwr); @@ -106,7 +114,7 @@ gboolean __scan_usb_sysfs(void)         moreinfo_del_with_prefix("DEV:USB");  	g_free(usb_list);      } -    usb_list = g_strdup("[USB Devices]\n"); +    usb_list = g_strdup_printf("[%s]\n", _("USB Devices"));      while ((filename = (gchar *) g_dir_read_name(sysfs))) {  	gchar *endpoint = @@ -145,7 +153,7 @@ gboolean __scan_usb_procfs(void)  	moreinfo_del_with_prefix("DEV:USB");  	g_free(usb_list);      } -    usb_list = g_strdup("[USB Devices]\n"); +    usb_list = g_strdup_printf("[%s]\n", _("USB Devices"));      while (fgets(buffer, 128, dev)) {  	tmp = buffer; @@ -179,50 +187,68 @@ gboolean __scan_usb_procfs(void)  	    if (product && *product == '\0') {  		g_free(product);  		if (classid == 9) { -		    product = g_strdup_printf("USB %.2f Hub", ver); +		    product = g_strdup_printf(_("USB %.2f Hub"), ver);  		} else { -		    product = g_strdup_printf("Unknown USB %.2f Device (class %d)", ver, classid); +		    product = g_strdup_printf(_("Unknown USB %.2f Device (class %d)"), ver, classid);  		}  	    } -	    if (classid == 9) {	/* hub */ -		usb_list = h_strdup_cprintf("[%s#%d]\n", usb_list, product, n); -	    } else {		/* everything else */ -		usb_list = h_strdup_cprintf("$%s$%s=\n", usb_list, tmp, product); - -		const gchar *url = vendor_get_url(manuf); -		if (url) { -		    gchar *tmp = g_strdup_printf("%s (%s)", vendor_get_name(manuf), -						 url); -		    g_free(manuf); -		    manuf = tmp; -		} - -		gchar *strhash = g_strdup_printf("[Device Information]\n" "Product=%s\n", -						 product); -		if (manuf && strlen(manuf)) -		    strhash = h_strdup_cprintf("Manufacturer=%s\n", strhash, manuf); - -		strhash = h_strdup_cprintf("[Port #%d]\n" -					   "Speed=%.2fMbit/s\n" -					   "Max Current=%s\n" -					   "[Misc]\n" -					   "USB Version=%.2f\n" -					   "Revision=%.2f\n" -					   "Class=0x%x\n" -					   "Vendor=0x%x\n" -					   "Product ID=0x%x\n" -					   "Bus=%d\n" "Level=%d\n", -					   strhash, port, speed, mxpwr, ver, rev, classid, vendor, prodid, bus, level); - -		moreinfo_add_with_prefix("DEV", tmp, strhash); -		g_free(tmp); -	    } +        if (classid == 9) {	/* hub */ +            usb_list = h_strdup_cprintf("[%s#%d]\n", usb_list, product, n); +        } else {		/* everything else */ +            usb_list = h_strdup_cprintf("$%s$%s=\n", usb_list, tmp, product); + +        EMPIFNULL(manuf); +        const gchar *v_url = vendor_get_url(manuf); +        const gchar *v_name = vendor_get_name(manuf); +        gchar *v_str = NULL; +        if (strlen(manuf)) { +            if (v_url != NULL) +                v_str = g_strdup_printf("%s (%s)", v_name, v_url); +            else +                v_str = g_strdup_printf("%s", manuf); +        } +        UNKIFNULL(v_str); +        UNKIFNULL(product); + +        gchar *strhash = g_strdup_printf("[%s]\n" "%s=%s\n" "%s=%s\n", +                        _("Device Information"), +                        _("Product"), product, +                        _("Manufacturer"), v_str); + +        strhash = h_strdup_cprintf("[%s #%d]\n" +                  /* Speed */       "%s=%.2f %s\n" +                  /* Max Current */ "%s=%s\n" +                       "[%s]\n" +                  /* USB Version */ "%s=%.2f\n" +                  /* Revision */    "%s=%.2f\n" +                  /* Class */       "%s=0x%x\n" +                  /* Vendor */      "%s=0x%x\n" +                  /* Product ID */  "%s=0x%x\n" +                  /* Bus */         "%s=%d\n" +                  /* Level */       "%s=%d\n", +                       strhash, +                       _("Port"), port, +                       _("Speed"), speed, _("Mbit/s"), +                       _("Max Current"), mxpwr, +                       _("Misc"), +                       _("USB Version"), ver, +                       _("Revision"), rev, +                       _("Class"), classid, +                       _("Vendor ID"), vendor, +                       _("Product ID"), prodid, +                       _("Bus"), bus, +                       _("Level"), level); + +        moreinfo_add_with_prefix("DEV", tmp, strhash); +        g_free(v_str); +        g_free(tmp); +        }  	    g_free(manuf);  	    g_free(product); -	    manuf = g_strdup(""); -	    product = g_strdup(""); +	    manuf = NULL; +	    product = NULL;  	    port = classid = 0;  	}      } @@ -274,35 +300,63 @@ void __scan_usb_lsusb_add_device(char *buffer, int bufsize, FILE * lsusb, int us      }      if (dev_class && strstr(dev_class, "0 (Defined at Interface level)")) { -	g_free(dev_class); -	if (int_class) { -	    dev_class = int_class; -	} else { -	    dev_class = g_strdup("Unknown"); -	} +        g_free(dev_class); +        if (int_class) { +            dev_class = int_class; +        } else { +            dev_class = g_strdup(_("(Unknown)")); +        }      } else -	dev_class = g_strdup("Unknown"); +    dev_class = g_strdup(_("(Unknown)"));      tmp = g_strdup_printf("USB%d", usb_device_number);      usb_list = h_strdup_cprintf("$%s$%s=\n", usb_list, tmp, name); -    strhash = g_strdup_printf("[Device Information]\n" -			      "Product=%s\n" -			      "Manufacturer=%s\n" -			      "Max Current=%s\n" -			      "[Misc]\n" -			      "USB Version=%s\n" -			      "Class=%s\n" -			      "Vendor=0x%x\n" -			      "Product ID=0x%x\n" -			      "Bus=%d\n", -			      product ? g_strstrip(product) : "Unknown", -			      vendor ? g_strstrip(vendor) : "Unknown", -			      max_power ? g_strstrip(max_power) : "Unknown", -			      version ? g_strstrip(version) : "Unknown", -			      dev_class ? g_strstrip(dev_class) : "Unknown", vendor_id, product_id, bus); +    const gchar *v_url = vendor_get_url(vendor); +    const gchar *v_name = vendor_get_name(vendor); +    gchar *v_str; +    if (v_url != NULL) { +        v_str = g_strdup_printf("%s (%s)", v_name, v_url); +    } else { +        v_str = g_strdup_printf("%s", g_strstrip(vendor) ); +    } + +    if (max_power != NULL) { +        int mA = atoi(g_strstrip(max_power)); +        gchar *trent_steel = g_strdup_printf("%d %s", mA, _("mA")); +        g_free(max_power); +        max_power = trent_steel; +    } + +    UNKIFNULL(product); +    UNKIFNULL(v_str); +    UNKIFNULL(max_power); +    UNKIFNULL(version); +    UNKIFNULL(dev_class); + +    strhash = g_strdup_printf("[%s]\n" +             /* Product */      "%s=%s\n" +             /* Manufacturer */ "%s=%s\n" +             /* Max Current */  "%s=%s\n" +                            "[%s]\n" +             /* USB Version */ "%s=%s\n" +             /* Class */       "%s=%s\n" +             /* Vendor ID */   "%s=0x%x\n" +             /* Product ID */  "%s=0x%x\n" +             /* Bus */         "%s=%d\n", +                _("Device Information"), +                _("Product"), g_strstrip(product), +                _("Vendor"), v_str, +                _("Max Current"), g_strstrip(max_power), +                _("Misc"), +                _("USB Version"), g_strstrip(version), +                _("Class"), g_strstrip(dev_class), +                _("Vendor ID"), vendor_id, +                _("Product ID"), product_id, +                _("Bus"), bus);      moreinfo_add_with_prefix("DEV", tmp, strhash); +    g_free(v_str);      g_free(vendor);      g_free(product);      g_free(max_power); @@ -356,25 +410,25 @@ gboolean __scan_usb_lsusb(void)      if (usb_list) {         moreinfo_del_with_prefix("DEV:USB"); -	g_free(usb_list); +        g_free(usb_list);      } -    usb_list = g_strdup("[USB Devices]\n"); +    usb_list = g_strdup_printf("[%s]\n", _("USB Devices"));      while (fgets(buffer, sizeof(buffer), temp_lsusb)) {          if (g_str_has_prefix(buffer, "Bus ")) {             __scan_usb_lsusb_add_device(buffer, sizeof(buffer), temp_lsusb, ++usb_device_number);          }      } -     +      fclose(temp_lsusb); -     +      return usb_device_number > 0;  }  void __scan_usb(void)  {      if (!__scan_usb_procfs()) { -	if (!__scan_usb_sysfs()) { +        if (!__scan_usb_sysfs()) {               __scan_usb_lsusb();          }      } diff --git a/modules/devices/x86/processor.c b/modules/devices/x86/processor.c index 25dc6c4a..ad3c7ca4 100644 --- a/modules/devices/x86/processor.c +++ b/modules/devices/x86/processor.c @@ -18,6 +18,10 @@  #include "hardinfo.h"  #include "devices.h" +#include "cpu_util.h" + +#include "x86_data.h" +#include "x86_data.c"  /*   * This function is partly based on x86cpucaps @@ -148,10 +152,10 @@ static gchar *__cache_get_info_as_string(Processor *processor)      for (cache_list = processor->cache; cache_list; cache_list = cache_list->next) {          cache = (ProcessorCache *)cache_list->data; -        result = h_strdup_cprintf("Level %d (%s)=%d-way set-associative, %d sets, %dKB size\n", +        result = h_strdup_cprintf(_("Level %d (%s)=%d-way set-associative, %d sets, %dKB size\n"),                                    result,                                    cache->level, -                                  cache->type, +                                  C_("cache-type", cache->type),                                    cache->ways_of_associativity,                                    cache->number_of_sets,                                    cache->size); @@ -160,6 +164,14 @@ static gchar *__cache_get_info_as_string(Processor *processor)      return result;  } +/* This is not used directly, but creates translatable strings for + * the type string returned from /sys/.../cache */ +static const char* cache_types[] = { +    NC_("cache-type", /*/cache type, as appears in: Level 1 (Data)*/ "Data"), +    NC_("cache-type", /*/cache type, as appears in: Level 1 (Instruction)*/ "Instruction"), +    NC_("cache-type", /*/cache type, as appears in: Level 2 (Unified)*/ "Unified") +}; +  static void __cache_obtain_info(Processor *processor)  {      ProcessorCache *cache; @@ -214,33 +226,6 @@ fail:      g_free(endpoint);  } -int processor_has_flag(gchar * strflags, gchar * strflag) -{ -    gchar **flags; -    gint ret = 0; -    if (strflags == NULL || strflag == NULL) -        return 0; -    flags = g_strsplit(strflags, " ", 0); -    ret = g_strv_contains((const gchar * const *)flags, strflag); -    g_strfreev(flags); -    return ret; -} - -static gint get_cpu_int(const gchar* file, gint cpuid) { -    gchar *tmp0 = NULL; -    gchar *tmp1 = NULL; -    gint ret = 0; - -    tmp0 = g_strdup_printf("/sys/devices/system/cpu/cpu%d/%s", cpuid, file); -    g_file_get_contents(tmp0, &tmp1, NULL, NULL); -    if (tmp1) -        ret = atol(tmp1); - -    g_free(tmp0); -    g_free(tmp1); -    return ret; -} -  GSList *processor_scan(void)  {      GSList *procs = NULL, *l = NULL; @@ -248,7 +233,7 @@ GSList *processor_scan(void)      FILE *cpuinfo;      gchar buffer[512]; -    cpuinfo = fopen("/proc/cpuinfo", "r"); +    cpuinfo = fopen(PROC_CPUINFO, "r");      if (!cpuinfo)          return NULL; @@ -280,6 +265,7 @@ GSList *processor_scan(void)              get_str("flags", processor->flags);              get_str("bugs", processor->bugs);              get_str("power management", processor->pm); +            get_str("microcode", processor->microcode);              get_int("cache size", processor->cache_size);              get_float("cpu MHz", processor->cpu_mhz);              get_float("bogomips", processor->bogomips); @@ -290,6 +276,7 @@ GSList *processor_scan(void)              get_str("hlt_bug", processor->bug_hlt);              get_str("f00f_bug", processor->bug_f00f);              get_str("coma_bug", processor->bug_coma); +            /* sep_bug? */              get_int("model", processor->model);              get_int("cpu family", processor->family); @@ -298,6 +285,8 @@ GSList *processor_scan(void)          g_strfreev(tmp);      } +    fclose(cpuinfo); +      /* finish last */      if (processor)          procs = g_slist_append(procs, processor); @@ -305,9 +294,17 @@ GSList *processor_scan(void)      for (l = procs; l; l = l->next) {          processor = (Processor *) l->data; +        STRIFNULL(processor->microcode, _("(Not Available)") ); +          get_processor_strfamily(processor);          __cache_obtain_info(processor); +#define NULLIFNOTYES(f) if (processor->f) if (strcmp(processor->f, "yes") != 0) { g_free(processor->f); processor->f = NULL; } +        NULLIFNOTYES(bug_fdiv); +        NULLIFNOTYES(bug_hlt); +        NULLIFNOTYES(bug_f00f); +        NULLIFNOTYES(bug_coma); +          if (processor->bugs == NULL || g_strcmp0(processor->bugs, "") == 0) {              g_free(processor->bugs);              /* make bugs list on old kernels that don't offer one */ @@ -337,291 +334,38 @@ GSList *processor_scan(void)              g_strchug(processor->pm);          } -        /* freq */ -        processor->cpukhz_cur = get_cpu_int("cpufreq/scaling_cur_freq", processor->id); -        processor->cpukhz_min = get_cpu_int("cpufreq/scaling_min_freq", processor->id); -        processor->cpukhz_max = get_cpu_int("cpufreq/scaling_max_freq", processor->id); -        if (processor->cpukhz_max) -            processor->cpu_mhz = processor->cpukhz_max / 1000; -    } - -    fclose(cpuinfo); - -    return procs; -} - -/* - * Sources: - * - Linux' cpufeature.h - * - http://gentoo-wiki.com/Cpuinfo - * - Intel IA-32 Architecture Software Development Manual - * - https://unix.stackexchange.com/questions/43539/what-do-the-flags-in-proc-cpuinfo-mean - */ -static struct { -    char *name, *meaning; -} flag_meaning[] = { -	{ "3dnow",	"3DNow! Technology"				}, -	{ "3dnowext",	"Extended 3DNow! Technology"			}, -	{ "fpu",	"Floating Point Unit"				}, -	{ "vme",	"Virtual 86 Mode Extension"			}, -	{ "de",		"Debug Extensions - I/O breakpoints"		}, -	{ "pse",	"Page Size Extensions (4MB pages)"		}, -	{ "tsc",	"Time Stamp Counter and RDTSC instruction"	}, -	{ "msr",	"Model Specific Registers"			}, -	{ "pae",	"Physical Address Extensions"			}, -	{ "mce",	"Machine Check Architecture"			}, -	{ "cx8",	"CMPXCHG8 instruction"				}, -	{ "apic",	"Advanced Programmable Interrupt Controller"	}, -	{ "sep",	"Fast System Call (SYSENTER/SYSEXIT)"		}, -	{ "mtrr",	"Memory Type Range Registers"			}, -	{ "pge",	"Page Global Enable"				}, -	{ "mca",	"Machine Check Architecture"			}, -	{ "cmov",	"Conditional Move instruction"			}, -	{ "pat",	"Page Attribute Table"				}, -	{ "pse36",	"36bit Page Size Extensions"			}, -	{ "psn",	"96 bit Processor Serial Number"		}, -	{ "mmx",	"MMX technology"				}, -	{ "mmxext",	"Extended MMX Technology"			}, -	{ "cflush",	"Cache Flush"					}, -	{ "dtes",	"Debug Trace Store"				}, -	{ "fxsr",	"FXSAVE and FXRSTOR instructions"		}, -	{ "kni",	"Streaming SIMD instructions"			}, -	{ "xmm",	"Streaming SIMD instructions"			}, -	{ "ht",		"HyperThreading"				}, -	{ "mp",		"Multiprocessing Capable"			}, -	{ "sse",	"SSE instructions"				}, -	{ "sse2",	"SSE2 (WNI) instructions"			}, -	{ "acc",	"Automatic Clock Control"			}, -	{ "ia64",	"IA64 Instructions"				}, -	{ "syscall",	"SYSCALL and SYSEXIT instructions"		}, -	{ "nx",		"No-execute Page Protection"			}, -	{ "xd",		"Execute Disable"				}, -	{ "clflush",	"Cache Line Flush instruction"			}, -	{ "acpi",	"Thermal Monitor and Software Controlled Clock"	}, -	{ "dts",	"Debug Store"					}, -	{ "ss",		"Self Snoop"					}, -	{ "tm",		"Thermal Monitor"				}, -	{ "pbe",	"Pending Break Enable"				}, -	{ "pb",		"Pending Break Enable"				}, -	{ "pn",		"Processor serial number"			}, -	{ "ds",		"Debug Store"					}, -	{ "xmm2",	"Streaming SIMD Extensions-2"			}, -	{ "xmm3",	"Streaming SIMD Extensions-3"			}, -	{ "selfsnoop",	"CPU self snoop"				}, -	{ "rdtscp",	"RDTSCP"					}, -	{ "recovery",	"CPU in recovery mode"				}, -	{ "longrun",	"Longrun power control"				}, -	{ "lrti",	"LongRun table interface"			}, -	{ "cxmmx",	"Cyrix MMX extensions"				}, -	{ "k6_mtrr",	"AMD K6 nonstandard MTRRs"			}, -	{ "cyrix_arr",	"Cyrix ARRs (= MTRRs)"				}, -	{ "centaur_mcr","Centaur MCRs (= MTRRs)"			}, -	{ "constant_tsc","TSC ticks at a constant rate"			}, -	{ "up",		"smp kernel running on up"			}, -	{ "fxsave_leak","FXSAVE leaks FOP/FIP/FOP"			}, -	{ "arch_perfmon","Intel Architectural PerfMon"			}, -	{ "pebs",	"Precise-Event Based Sampling"			}, -	{ "bts",	"Branch Trace Store"				}, -	{ "sync_rdtsc",	"RDTSC synchronizes the CPU"			}, -	{ "rep_good",	"rep microcode works well on this CPU"		}, -	{ "mwait",	"Monitor/Mwait support"				}, -	{ "ds_cpl",	"CPL Qualified Debug Store"			}, -	{ "est",	"Enhanced SpeedStep"				}, -	{ "tm2",	"Thermal Monitor 2"				}, -	{ "cid",	"Context ID"					}, -	{ "xtpr",	"Send Task Priority Messages"			}, -	{ "xstore",	"on-CPU RNG present (xstore insn)"		}, -	{ "xstore_en",	"on-CPU RNG enabled"				}, -	{ "xcrypt",	"on-CPU crypto (xcrypt insn)"			}, -	{ "xcrypt_en",	"on-CPU crypto enabled"				}, -	{ "ace2",	"Advanced Cryptography Engine v2"		}, -	{ "ace2_en",	"ACE v2 enabled"				}, -	{ "phe",	"PadLock Hash Engine"				}, -	{ "phe_en",	"PHE enabled"					}, -	{ "pmm",	"PadLock Montgomery Multiplier"			}, -	{ "pmm_en",	"PMM enabled"					}, -	{ "lahf_lm",	"LAHF/SAHF in long mode"			}, -	{ "cmp_legacy",	"HyperThreading not valid"			}, -	{ "lm",		"LAHF/SAHF in long mode"			}, -	{ "ds_cpl",	"CPL Qualified Debug Store"			}, -	{ "vmx",	"Virtualization support (Intel)"		}, -	{ "svm",	"Virtualization support (AMD)"			}, -	{ "est",	"Enhanced SpeedStep"				}, -	{ "tm2",	"Thermal Monitor 2"				}, -	{ "ssse3",	"Supplemental Streaming SIMD Extension 3"	}, -	{ "cx16",	"CMPXCHG16B instruction"			}, -	{ "xptr",	"Send Task Priority Messages"			}, -	{ "pebs",	"Precise Event Based Sampling"			}, -	{ "bts",	"Branch Trace Store"				}, -	{ "ida",	"Intel Dynamic Acceleration"			}, -	{ "arch_perfmon","Intel Architectural PerfMon"			}, -	{ "pni",	"Streaming SIMD Extension 3 (Prescott New Instruction)"	}, -	{ "rep_good",	"rep microcode works well on this CPU"		}, -	{ "ts",		"Thermal Sensor"				}, -	{ "sse3",	"Streaming SIMD Extension 3"			}, -	{ "sse4",	"Streaming SIMD Extension 4"			}, -	{ "tni",	"Tejas New Instruction"				}, -	{ "nni",	"Nehalem New Instruction"			}, -	{ "tpr",	"Task Priority Register"			}, -	{ "vid",	"Voltage Identifier"				}, -	{ "fid", 	"Frequency Identifier"				}, -	{ "dtes64", 	"64-bit Debug Store"				}, -	{ "monitor", 	"Monitor/Mwait support"				}, -	{ "sse4_1",     "Streaming SIMD Extension 4.1"                  }, -	{ "sse4_2",     "Streaming SIMD Extension 4.2"                  }, -	{ "nopl",       "NOPL instructions"                             }, -	{ "cxmmx",      "Cyrix MMX extensions"                          }, -	{ "xtopology",  "CPU topology enum extensions"                  }, -	{ "nonstop_tsc", "TSC does not stop in C states"                }, -	{ "eagerfpu",   "Non lazy FPU restor"                           }, -	{ "pclmulqdq",  "Perform a Carry-Less Multiplication of Quadword instruction" }, -	{ "smx",        "Safer mode: TXT (TPM support)"                 }, -	{ "pdcm",       "Performance capabilities"                      }, -	{ "pcid",       "Process Context Identifiers"                   }, -	{ "x2apic",     "x2APIC"                                        }, -	{ "popcnt",     "Set bit count instructions"                    }, -	{ "aes",        "Advanced Encryption Standard"                  }, -	{ "aes-ni",     "Advanced Encryption Standard (New Instructions)" }, -	{ "xsave",      "Save Processor Extended States"                }, -	{ "avx",        "Advanced Vector Instructions"                  }, -	{ NULL,		NULL						}, -}; - -static struct { -    char *name, *meaning; -} bug_meaning[] = { -	{ "f00f",        "Intel F00F bug"    }, -	{ "fdiv",        "FPU FDIV"          }, -	{ "coma",        "Cyrix 6x86 coma"   }, -	{ "tlb_mmatch",  "AMD Erratum 383"   }, -	{ "apic_c1e",    "AMD Erratum 400"   }, -	{ "11ap",        "Bad local APIC aka 11AP"  }, -	{ "fxsave_leak", "FXSAVE leaks FOP/FIP/FOP" }, -	{ "clflush_monitor",  "AAI65, CLFLUSH required before MONITOR" }, -	{ "sysret_ss_attrs",  "SYSRET doesn't fix up SS attrs" }, -	{ "espfix",      "IRET to 16-bit SS corrupts ESP/RSP high bits" }, -	{ "null_seg",    "Nulling a selector preserves the base" },         /* see: detect_null_seg_behavior() */ -	{ "swapgs_fence","SWAPGS without input dep on GS" }, -	{ "monitor",     "IPI required to wake up remote CPU" }, -	{ "amd_e400",    "AMD Erratum 400" }, -	{ NULL,		NULL						}, -}; - -/* from arch/x86/kernel/cpu/powerflags.h */ -static struct { -    char *name, *meaning; -} pm_meaning[] = { -	{ "ts",            "temperature sensor"     }, -	{ "fid",           "frequency id control"   }, -	{ "vid",           "voltage id control"     }, -	{ "ttp",           "thermal trip"           }, -	{ "tm",            "hardware thermal control"   }, -	{ "stc",           "software thermal control"   }, -	{ "100mhzsteps",   "100 MHz multiplier control" }, -	{ "hwpstate",      "hardware P-state control"   }, -/*	{ "",              "tsc invariant mapped to constant_tsc" }, */ -	{ "cpb",           "core performance boost"     }, -	{ "eff_freq_ro",   "Readonly aperf/mperf"       }, -	{ "proc_feedback", "processor feedback interface" }, -	{ "acc_power",     "accumulated power mechanism"  }, -	{ NULL,		NULL						}, -}; - -GHashTable *cpu_flags = NULL; - -static void -populate_cpu_flags_list_internal() -{ -    int i; - -    DEBUG("using internal CPU flags database"); +        /* topo & freq */ +        processor->cpufreq = cpufreq_new(processor->id); +        processor->cputopo = cputopo_new(processor->id); -    for (i = 0; flag_meaning[i].name != NULL; i++) { -        g_hash_table_insert(cpu_flags, flag_meaning[i].name, -                            flag_meaning[i].meaning); +        if (processor->cpufreq->cpukhz_max) +            processor->cpu_mhz = processor->cpufreq->cpukhz_max / 1000;      } -    for (i = 0; bug_meaning[i].name != NULL; i++) { -        g_hash_table_insert(cpu_flags, bug_meaning[i].name, -                            bug_meaning[i].meaning); -    } -    for (i = 0; pm_meaning[i].name != NULL; i++) { -        g_hash_table_insert(cpu_flags, pm_meaning[i].name, -                            pm_meaning[i].meaning); -    } -} - -void cpu_flags_init(void) -{ -    gint i; -    gchar *path; - -    cpu_flags = g_hash_table_new(g_str_hash, g_str_equal); - -    path = g_build_filename(g_get_home_dir(), ".hardinfo", "cpuflags.conf", NULL); -    if (!g_file_test(path, G_FILE_TEST_EXISTS)) { -        populate_cpu_flags_list_internal(); -    } else { -        GKeyFile *flags_file; -        DEBUG("using %s as CPU flags database", path); - -        flags_file = g_key_file_new(); -        if (g_key_file_load_from_file(flags_file, path, 0, NULL)) { -            gchar **flag_keys; - -            flag_keys = g_key_file_get_keys(flags_file, "flags", -                                            NULL, NULL); -            if (!flag_keys) { -                DEBUG("error while using %s as CPU flags database, falling back to internal", -                      path); -                populate_cpu_flags_list_internal(); -            } else { -                for (i = 0; flag_keys[i]; i++) { -                    gchar *meaning; - -                    meaning = g_key_file_get_string(flags_file, "flags", -                                                    flag_keys[i], NULL); - -                    g_hash_table_insert(cpu_flags, g_strdup(flag_keys[i]), meaning); - -                    /* can't free meaning */ -                } - -                g_strfreev(flag_keys); -            } -        } - -        g_key_file_free(flags_file); -    } - -    g_free(path); +    return procs;  } -gchar *processor_get_capabilities_from_flags(gchar * strflags) +gchar *processor_get_capabilities_from_flags(gchar *strflags, gchar *lookup_prefix)  { -    /* FIXME: -     * - Separate between processor capabilities, additional instructions and whatnot. -     */      gchar **flags, **old; +    gchar tmp_flag[64] = ""; +    const gchar *meaning;      gchar *tmp = NULL;      gint j = 0; -    if (!cpu_flags) { -        cpu_flags_init(); -    } -      flags = g_strsplit(strflags, " ", 0);      old = flags;      while (flags[j]) { -	gchar *meaning = g_hash_table_lookup(cpu_flags, flags[j]); +        sprintf(tmp_flag, "%s%s", lookup_prefix, flags[j]); +        meaning = x86_flag_meaning(tmp_flag); -	if (meaning) { -  	  tmp = h_strdup_cprintf("%s=%s\n", tmp, flags[j], meaning); +        if (meaning) { +            tmp = h_strdup_cprintf("%s=%s\n", tmp, flags[j], meaning);          } else { -  	  tmp = h_strdup_cprintf("%s=\n", tmp, flags[j]); +            tmp = h_strdup_cprintf("%s=\n", tmp, flags[j]);          } -	j++; +        j++;      }      if (tmp == NULL || g_strcmp0(tmp, "") == 0)          tmp = g_strdup_printf("%s=%s\n", "empty", _("Empty List")); @@ -632,96 +376,120 @@ gchar *processor_get_capabilities_from_flags(gchar * strflags)  gchar *processor_get_detailed_info(Processor * processor)  { -    gchar *tmp_flags, *tmp_bugs, *tmp_pm, *ret, *cache_info; +    gchar *tmp_flags, *tmp_bugs, *tmp_pm, *tmp_cpufreq, *tmp_topology, *ret, *cache_info; -    tmp_flags = processor_get_capabilities_from_flags(processor->flags); -    tmp_bugs = processor_get_capabilities_from_flags(processor->bugs); -    tmp_pm = processor_get_capabilities_from_flags(processor->pm); +    tmp_flags = processor_get_capabilities_from_flags(processor->flags, ""); +    tmp_bugs = processor_get_capabilities_from_flags(processor->bugs, "bug:"); +    tmp_pm = processor_get_capabilities_from_flags(processor->pm, "pm:");      cache_info = __cache_get_info_as_string(processor); -    ret = g_strdup_printf(_("[Processor]\n" -			  "Name=%s\n" -			  "Family, model, stepping=%d, %d, %d (%s)\n" -			  "Vendor=%s\n" -			  "[Configuration]\n" -			  "Cache Size=%dkb\n" -			  "Frequency=%.2fMHz\n" -			  "BogoMIPS=%.2f\n" -			  "Byte Order=%s\n" -			  "[Frequency Scaling]\n" -			  "Minimum=%d kHz\n" -			  "Maximum=%d kHz\n" -			  "Current=%d kHz\n" -			  "[Features]\n" -			  "Has FPU=%s\n" -			  "[Cache]\n" -			  "%s\n" -			  "[Power Management]\n" -			  "%s" -			  "[Bugs]\n" -			  "%s" -			  "[Capabilities]\n" -			  "%s"), -			  processor->model_name, -			  processor->family, -			  processor->model, -			  processor->stepping, -			  processor->strmodel, -			  vendor_get_name(processor->vendor_id), -			  processor->cache_size, -			  processor->cpu_mhz, processor->bogomips, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -			  "Little Endian", -#else -			  "Big Endian", -#endif -			  processor->cpukhz_min, -			  processor->cpukhz_max, -			  processor->cpukhz_cur, -			  processor->has_fpu  ? processor->has_fpu  : "no", -			  cache_info, -			  tmp_pm, tmp_bugs, tmp_flags); +    tmp_topology = cputopo_section_str(processor->cputopo); +    tmp_cpufreq = cpufreq_section_str(processor->cpufreq); + +    ret = g_strdup_printf("[%s]\n" +                       "%s=%s\n" +                       "%s=%d, %d, %d (%s)\n" /* family, model, stepping (decoded name) */ +                       "%s=%s\n"      /* vendor */ +                       "%s=%s\n"      /* microcode */ +                       "[%s]\n"       /* configuration */ +                       "%s=%d %s\n"   /* cache size (from cpuinfo) */ +                       "%s=%.2f %s\n" /* frequency */ +                       "%s=%.2f\n"    /* bogomips */ +                       "%s=%s\n"      /* byte order */ +                       "%s"     /* topology */ +                       "%s"     /* frequency scaling */ +                       "[%s]\n" /* cache */ +                       "%s\n" +                       "[%s]\n" /* pm */ +                       "%s" +                       "[%s]\n" /* bugs */ +                       "%s" +                       "[%s]\n" /* flags */ +                       "%s", +                   _("Processor"), +                   _("Model Name"), processor->model_name, +                   _("Family, model, stepping"), +                   processor->family, +                   processor->model, +                   processor->stepping, +                   processor->strmodel, +                   _("Vendor"), vendor_get_name(processor->vendor_id), +                   _("Microcode Version"), processor->microcode, +                   _("Configuration"), +                   _("Cache Size"), processor->cache_size, _("kb"), +                   _("Frequency"), processor->cpu_mhz, _("MHz"), +                   _("BogoMips"), processor->bogomips, +                   _("Byte Order"), byte_order_str(), +                   tmp_topology, +                   tmp_cpufreq, +                   _("Cache"), cache_info, +                   _("Power Management"), tmp_pm, +                   _("Bug Workarounds"), tmp_bugs, +                   _("Capabilities"), tmp_flags );      g_free(tmp_flags);      g_free(tmp_bugs);      g_free(tmp_pm);      g_free(cache_info); +    g_free(tmp_cpufreq); +    g_free(tmp_topology); +    return ret; +} + +gchar *processor_name(GSList * processors) { +    return processor_name_default(processors); +} +gchar *processor_describe(GSList * processors) { +    return processor_describe_default(processors); +} + +gchar *processor_meta(GSList * processors) { +    gchar *meta_cpu_name = processor_name(processors); +    gchar *meta_cpu_desc = processor_describe(processors); +    gchar *ret = NULL; +    UNKIFNULL(meta_cpu_desc); +    ret = g_strdup_printf("[%s]\n" +                        "%s=%s\n" +                        "%s=%s\n", +                        _("Package Information"), +                        _("Name"), meta_cpu_name, +                        _("Description"), meta_cpu_desc); +    g_free(meta_cpu_desc);      return ret;  }  gchar *processor_get_info(GSList * processors)  {      Processor *processor; +    gchar *ret, *tmp, *hashkey; +    gchar *meta; /* becomes owned by more_info? no need to free? */ +    GSList *l; -    if (g_slist_length(processors) > 1) { -	gchar *ret, *tmp, *hashkey; -	GSList *l; - -	tmp = g_strdup(""); +    tmp = g_strdup_printf("$CPU_META$%s=\n", _("Package Information") ); -	for (l = processors; l; l = l->next) { -	    processor = (Processor *) l->data; +    meta = processor_meta(processors); +    moreinfo_add_with_prefix("DEV", "CPU_META", meta); -	    tmp = g_strdup_printf(_("%s$CPU%d$%s=%.2fMHz\n"), -				  tmp, processor->id, -				  processor->model_name, -				  processor->cpu_mhz); - -	    hashkey = g_strdup_printf("CPU%d", processor->id); -	    moreinfo_add_with_prefix("DEV", hashkey, -				processor_get_detailed_info(processor)); -           g_free(hashkey); -	} +    for (l = processors; l; l = l->next) { +        processor = (Processor *) l->data; -	ret = g_strdup_printf("[$ShellParam$]\n" -			      "ViewType=1\n" -			      "[Processors]\n" -			      "%s", tmp); -	g_free(tmp); +        tmp = g_strdup_printf("%s$CPU%d$%s=%.2f %s\n", +                  tmp, processor->id, +                  processor->model_name, +                  processor->cpu_mhz, _("MHz")); -	return ret; +        hashkey = g_strdup_printf("CPU%d", processor->id); +        moreinfo_add_with_prefix("DEV", hashkey, +                processor_get_detailed_info(processor)); +        g_free(hashkey);      } -    processor = (Processor *) processors->data; -    return processor_get_detailed_info(processor); +    ret = g_strdup_printf("[$ShellParam$]\n" +                  "ViewType=1\n" +                  "[Processors]\n" +                  "%s", tmp); +    g_free(tmp); + +    return ret;  } + diff --git a/modules/devices/x86/x86_data.c b/modules/devices/x86/x86_data.c new file mode 100644 index 00000000..ebd434bb --- /dev/null +++ b/modules/devices/x86/x86_data.c @@ -0,0 +1,344 @@ +/* + * rpiz - https://github.com/bp0/rpiz + * Copyright (C) 2017  Burt P. <pburt0@gmail.com> + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "x86_data.h" + +#ifndef C_ +#define C_(Ctx, String) String +#endif +#ifndef NC_ +#define NC_(Ctx, String) String +#endif + +/* sources: + *   https://unix.stackexchange.com/a/43540 + *   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/arch/x86/include/asm/cpufeatures.h?id=refs/tags/v4.9 + *   hardinfo: modules/devices/x86/processor.c + */ +static struct { +    char *name, *meaning; +} tab_flag_meaning[] = { +/* Intel-defined CPU features, CPUID level 0x00000001 (edx) + * See also Wikipedia and table 2-27 in Intel Advanced Vector Extensions Programming Reference */ +    { "fpu",     NC_("x86-flag", /*/flag:fpu*/  "Onboard FPU (floating point support)") }, +    { "vme",     NC_("x86-flag", /*/flag:vme*/  "Virtual 8086 mode enhancements") }, +    { "de",      NC_("x86-flag", /*/flag:de*/  "Debugging Extensions (CR4.DE)") }, +    { "pse",     NC_("x86-flag", /*/flag:pse*/  "Page Size Extensions (4MB memory pages)") }, +    { "tsc",     NC_("x86-flag", /*/flag:tsc*/  "Time Stamp Counter (RDTSC)") }, +    { "msr",     NC_("x86-flag", /*/flag:msr*/  "Model-Specific Registers (RDMSR, WRMSR)") }, +    { "pae",     NC_("x86-flag", /*/flag:pae*/  "Physical Address Extensions (support for more than 4GB of RAM)") }, +    { "mce",     NC_("x86-flag", /*/flag:mce*/  "Machine Check Exception") }, +    { "cx8",     NC_("x86-flag", /*/flag:cx8*/  "CMPXCHG8 instruction (64-bit compare-and-swap)") }, +    { "apic",    NC_("x86-flag", /*/flag:apic*/  "Onboard APIC") }, +    { "sep",     NC_("x86-flag", /*/flag:sep*/  "SYSENTER/SYSEXIT") }, +    { "mtrr",    NC_("x86-flag", /*/flag:mtrr*/  "Memory Type Range Registers") }, +    { "pge",     NC_("x86-flag", /*/flag:pge*/  "Page Global Enable (global bit in PDEs and PTEs)") }, +    { "mca",     NC_("x86-flag", /*/flag:mca*/  "Machine Check Architecture") }, +    { "cmov",    NC_("x86-flag", /*/flag:cmov*/  "CMOV instructions (conditional move) (also FCMOV)") }, +    { "pat",     NC_("x86-flag", /*/flag:pat*/  "Page Attribute Table") }, +    { "pse36",   NC_("x86-flag", /*/flag:pse36*/  "36-bit PSEs (huge pages)") }, +    { "pn",      NC_("x86-flag", /*/flag:pn*/  "Processor serial number") }, +    { "clflush", NC_("x86-flag", /*/flag:clflush*/  "Cache Line Flush instruction") }, +    { "dts",     NC_("x86-flag", /*/flag:dts*/  "Debug Store (buffer for debugging and profiling instructions), or alternately: digital thermal sensor") }, +    { "acpi",    NC_("x86-flag", /*/flag:acpi*/  "ACPI via MSR (temperature monitoring and clock speed modulation)") }, +    { "mmx",     NC_("x86-flag", /*/flag:mmx*/  "Multimedia Extensions") }, +    { "fxsr",    NC_("x86-flag", /*/flag:fxsr*/  "FXSAVE/FXRSTOR, CR4.OSFXSR") }, +    { "sse",     NC_("x86-flag", /*/flag:sse*/  "Intel SSE vector instructions") }, +    { "sse2",    NC_("x86-flag", /*/flag:sse2*/  "SSE2") }, +    { "ss",      NC_("x86-flag", /*/flag:ss*/  "CPU self snoop") }, +    { "ht",      NC_("x86-flag", /*/flag:ht*/  "Hyper-Threading") }, +    { "tm",      NC_("x86-flag", /*/flag:tm*/  "Automatic clock control (Thermal Monitor)") }, +    { "ia64",    NC_("x86-flag", /*/flag:ia64*/  "Intel Itanium Architecture 64-bit (not to be confused with Intel's 64-bit x86 architecture with flag x86-64 or \"AMD64\" bit indicated by flag lm)") }, +    { "pbe",     NC_("x86-flag", /*/flag:pbe*/  "Pending Break Enable (PBE# pin) wakeup support") }, +/* AMD-defined CPU features, CPUID level 0x80000001 + * See also Wikipedia and table 2-23 in Intel Advanced Vector Extensions Programming Reference */ +    { "syscall",  NC_("x86-flag", /*/flag:syscall*/  "SYSCALL (Fast System Call) and SYSRET (Return From Fast System Call)") }, +    { "mp",       NC_("x86-flag", /*/flag:mp*/  "Multiprocessing Capable.") }, +    { "nx",       NC_("x86-flag", /*/flag:nx*/  "Execute Disable") }, +    { "mmxext",   NC_("x86-flag", /*/flag:mmxext*/  "AMD MMX extensions") }, +    { "fxsr_opt", NC_("x86-flag", /*/flag:fxsr_opt*/  "FXSAVE/FXRSTOR optimizations") }, +    { "pdpe1gb",  NC_("x86-flag", /*/flag:pdpe1gb*/  "One GB pages (allows hugepagesz=1G)") }, +    { "rdtscp",   NC_("x86-flag", /*/flag:rdtscp*/  "Read Time-Stamp Counter and Processor ID") }, +    { "lm",       NC_("x86-flag", /*/flag:lm*/  "Long Mode (x86-64: amd64, also known as Intel 64, i.e. 64-bit capable)") }, +    { "3dnow",    NC_("x86-flag", /*/flag:3dnow*/  "3DNow! (AMD vector instructions, competing with Intel's SSE1)") }, +    { "3dnowext", NC_("x86-flag", /*/flag:3dnowext*/  "AMD 3DNow! extensions") }, +/* Transmeta-defined CPU features, CPUID level 0x80860001 */ +    { "recovery", NC_("x86-flag", /*/flag:recovery*/  "CPU in recovery mode") }, +    { "longrun",  NC_("x86-flag", /*/flag:longrun*/  "Longrun power control") }, +    { "lrti",     NC_("x86-flag", /*/flag:lrti*/  "LongRun table interface") }, +/* Other features, Linux-defined mapping */ +    { "cxmmx",        NC_("x86-flag", /*/flag:cxmmx*/  "Cyrix MMX extensions") }, +    { "k6_mtrr",      NC_("x86-flag", /*/flag:k6_mtrr*/  "AMD K6 nonstandard MTRRs") }, +    { "cyrix_arr",    NC_("x86-flag", /*/flag:cyrix_arr*/  "Cyrix ARRs (= MTRRs)") }, +    { "centaur_mcr",  NC_("x86-flag", /*/flag:centaur_mcr*/  "Centaur MCRs (= MTRRs)") }, +    { "constant_tsc", NC_("x86-flag", /*/flag:constant_tsc*/  "TSC ticks at a constant rate") }, +    { "up",           NC_("x86-flag", /*/flag:up*/  "SMP kernel running on UP") }, +    { "art",          NC_("x86-flag", /*/flag:art*/  "Always-Running Timer") }, +    { "arch_perfmon", NC_("x86-flag", /*/flag:arch_perfmon*/  "Intel Architectural PerfMon") }, +    { "pebs",         NC_("x86-flag", /*/flag:pebs*/  "Precise-Event Based Sampling") }, +    { "bts",          NC_("x86-flag", /*/flag:bts*/  "Branch Trace Store") }, +    { "rep_good",     NC_("x86-flag", /*/flag:rep_good*/  "rep microcode works well") }, +    { "acc_power",    NC_("x86-flag", /*/flag:acc_power*/  "AMD accumulated power mechanism") }, +    { "nopl",         NC_("x86-flag", /*/flag:nopl*/  "The NOPL (0F 1F) instructions") }, +    { "xtopology",    NC_("x86-flag", /*/flag:xtopology*/  "cpu topology enum extensions") }, +    { "tsc_reliable", NC_("x86-flag", /*/flag:tsc_reliable*/  "TSC is known to be reliable") }, +    { "nonstop_tsc",  NC_("x86-flag", /*/flag:nonstop_tsc*/  "TSC does not stop in C states") }, +    { "extd_apicid",  NC_("x86-flag", /*/flag:extd_apicid*/  "has extended APICID (8 bits)") }, +    { "amd_dcm",      NC_("x86-flag", /*/flag:amd_dcm*/  "multi-node processor") }, +    { "aperfmperf",   NC_("x86-flag", /*/flag:aperfmperf*/  "APERFMPERF") }, +    { "eagerfpu",     NC_("x86-flag", /*/flag:eagerfpu*/  "Non lazy FPU restore") }, +    { "nonstop_tsc_s3", NC_("x86-flag", /*/flag:nonstop_tsc_s3*/  "TSC doesn't stop in S3 state") }, +    { "mce_recovery",   NC_("x86-flag", /*/flag:mce_recovery*/  "CPU has recoverable machine checks") }, +/* Intel-defined CPU features, CPUID level 0x00000001 (ecx) + * See also Wikipedia and table 2-26 in Intel Advanced Vector Extensions Programming Reference */ +    { "pni",       NC_("x86-flag", /*/flag:pni*/  "SSE-3 (\"Prescott New Instructions\")") }, +    { "pclmulqdq", NC_("x86-flag", /*/flag:pclmulqdq*/  "Perform a Carry-Less Multiplication of Quadword instruction - accelerator for GCM)") }, +    { "dtes64",    NC_("x86-flag", /*/flag:dtes64*/  "64-bit Debug Store") }, +    { "monitor",   NC_("x86-flag", /*/flag:monitor*/  "Monitor/Mwait support (Intel SSE3 supplements)") }, +    { "ds_cpl",    NC_("x86-flag", /*/flag:ds_cpl*/  "CPL Qual. Debug Store") }, +    { "vmx",       NC_("x86-flag", /*/flag:vmx*/  "Hardware virtualization, Intel VMX") }, +    { "smx",       NC_("x86-flag", /*/flag:smx*/  "Safer mode TXT (TPM support)") }, +    { "est",       NC_("x86-flag", /*/flag:est*/  "Enhanced SpeedStep") }, +    { "tm2",       NC_("x86-flag", /*/flag:tm2*/  "Thermal Monitor 2") }, +    { "ssse3",     NC_("x86-flag", /*/flag:ssse3*/  "Supplemental SSE-3") }, +    { "cid",       NC_("x86-flag", /*/flag:cid*/  "Context ID") }, +    { "sdbg",      NC_("x86-flag", /*/flag:sdbg*/  "silicon debug") }, +    { "fma",       NC_("x86-flag", /*/flag:fma*/  "Fused multiply-add") }, +    { "cx16",      NC_("x86-flag", /*/flag:cx16*/  "CMPXCHG16B") }, +    { "xtpr",      NC_("x86-flag", /*/flag:xtpr*/  "Send Task Priority Messages") }, +    { "pdcm",      NC_("x86-flag", /*/flag:pdcm*/  "Performance Capabilities") }, +    { "pcid",      NC_("x86-flag", /*/flag:pcid*/  "Process Context Identifiers") }, +    { "dca",       NC_("x86-flag", /*/flag:dca*/  "Direct Cache Access") }, +    { "sse4_1",    NC_("x86-flag", /*/flag:sse4_1*/  "SSE-4.1") }, +    { "sse4_2",    NC_("x86-flag", /*/flag:sse4_2*/  "SSE-4.2") }, +    { "x2apic",    NC_("x86-flag", /*/flag:x2apic*/  "x2APIC") }, +    { "movbe",     NC_("x86-flag", /*/flag:movbe*/  "Move Data After Swapping Bytes instruction") }, +    { "popcnt",    NC_("x86-flag", /*/flag:popcnt*/  "Return the Count of Number of Bits Set to 1 instruction (Hamming weight, i.e. bit count)") }, +    { "tsc_deadline_timer", NC_("x86-flag", /*/flag:tsc_deadline_timer*/  "Tsc deadline timer") }, +    { "aes/aes-ni",  NC_("x86-flag", /*/flag:aes/aes-ni*/  "Advanced Encryption Standard (New Instructions)") }, +    { "xsave",       NC_("x86-flag", /*/flag:xsave*/  "Save Processor Extended States: also provides XGETBY,XRSTOR,XSETBY") }, +    { "avx",         NC_("x86-flag", /*/flag:avx*/  "Advanced Vector Extensions") }, +    { "f16c",        NC_("x86-flag", /*/flag:f16c*/  "16-bit fp conversions (CVT16)") }, +    { "rdrand",      NC_("x86-flag", /*/flag:rdrand*/  "Read Random Number from hardware random number generator instruction") }, +    { "hypervisor",  NC_("x86-flag", /*/flag:hypervisor*/  "Running on a hypervisor") }, +/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001 */ +    { "rng",     NC_("x86-flag", /*/flag:rng*/  "Random Number Generator present (xstore)") }, +    { "rng_en",  NC_("x86-flag", /*/flag:rng_en*/  "Random Number Generator enabled") }, +    { "ace",     NC_("x86-flag", /*/flag:ace*/  "on-CPU crypto (xcrypt)") }, +    { "ace_en",  NC_("x86-flag", /*/flag:ace_en*/  "on-CPU crypto enabled") }, +    { "ace2",    NC_("x86-flag", /*/flag:ace2*/  "Advanced Cryptography Engine v2") }, +    { "ace2_en", NC_("x86-flag", /*/flag:ace2_en*/  "ACE v2 enabled") }, +    { "phe",     NC_("x86-flag", /*/flag:phe*/  "PadLock Hash Engine") }, +    { "phe_en",  NC_("x86-flag", /*/flag:phe_en*/  "PHE enabled") }, +    { "pmm",     NC_("x86-flag", /*/flag:pmm*/  "PadLock Montgomery Multiplier") }, +    { "pmm_en",  NC_("x86-flag", /*/flag:pmm_en*/  "PMM enabled") }, +/* More extended AMD flags: CPUID level 0x80000001, ecx */ +    { "lahf_lm",       NC_("x86-flag", /*/flag:lahf_lm*/  "Load AH from Flags (LAHF) and Store AH into Flags (SAHF) in long mode") }, +    { "cmp_legacy",    NC_("x86-flag", /*/flag:cmp_legacy*/  "If yes HyperThreading not valid") }, +    { "svm",           NC_("x86-flag", /*/flag:svm*/  "\"Secure virtual machine\": AMD-V") }, +    { "extapic",       NC_("x86-flag", /*/flag:extapic*/  "Extended APIC space") }, +    { "cr8_legacy",    NC_("x86-flag", /*/flag:cr8_legacy*/  "CR8 in 32-bit mode") }, +    { "abm",           NC_("x86-flag", /*/flag:abm*/  "Advanced Bit Manipulation") }, +    { "sse4a",         NC_("x86-flag", /*/flag:sse4a*/  "SSE-4A") }, +    { "misalignsse",   NC_("x86-flag", /*/flag:misalignsse*/  "indicates if a general-protection exception (#GP) is generated when some legacy SSE instructions operate on unaligned data. Also depends on CR0 and Alignment Checking bit") }, +    { "3dnowprefetch", NC_("x86-flag", /*/flag:3dnowprefetch*/  "3DNow prefetch instructions") }, +    { "osvw",          NC_("x86-flag", /*/flag:osvw*/  "indicates OS Visible Workaround, which allows the OS to work around processor errata.") }, +    { "ibs",           NC_("x86-flag", /*/flag:ibs*/  "Instruction Based Sampling") }, +    { "xop",           NC_("x86-flag", /*/flag:xop*/  "extended AVX instructions") }, +    { "skinit",        NC_("x86-flag", /*/flag:skinit*/  "SKINIT/STGI instructions") }, +    { "wdt",           NC_("x86-flag", /*/flag:wdt*/  "Watchdog timer") }, +    { "lwp",           NC_("x86-flag", /*/flag:lwp*/  "Light Weight Profiling") }, +    { "fma4",          NC_("x86-flag", /*/flag:fma4*/  "4 operands MAC instructions") }, +    { "tce",           NC_("x86-flag", /*/flag:tce*/  "translation cache extension") }, +    { "nodeid_msr",    NC_("x86-flag", /*/flag:nodeid_msr*/  "NodeId MSR") }, +    { "tbm",           NC_("x86-flag", /*/flag:tbm*/  "Trailing Bit Manipulation") }, +    { "topoext",       NC_("x86-flag", /*/flag:topoext*/  "Topology Extensions CPUID leafs") }, +    { "perfctr_core",  NC_("x86-flag", /*/flag:perfctr_core*/  "Core Performance Counter Extensions") }, +    { "perfctr_nb",    NC_("x86-flag", /*/flag:perfctr_nb*/  "NB Performance Counter Extensions") }, +    { "bpext",         NC_("x86-flag", /*/flag:bpext*/  "data breakpoint extension") }, +    { "ptsc",          NC_("x86-flag", /*/flag:ptsc*/  "performance time-stamp counter") }, +    { "perfctr_l2",    NC_("x86-flag", /*/flag:perfctr_l2*/  "L2 Performance Counter Extensions") }, +    { "mwaitx",        NC_("x86-flag", /*/flag:mwaitx*/  "MWAIT extension (MONITORX/MWAITX)") }, +/* Auxiliary flags: Linux defined - For features scattered in various CPUID levels */ +    { "cpb",           NC_("x86-flag", /*/flag:cpb*/  "AMD Core Performance Boost") }, +    { "epb",           NC_("x86-flag", /*/flag:epb*/  "IA32_ENERGY_PERF_BIAS support") }, +    { "hw_pstate",     NC_("x86-flag", /*/flag:hw_pstate*/  "AMD HW-PState") }, +    { "proc_feedback", NC_("x86-flag", /*/flag:proc_feedback*/  "AMD ProcFeedbackInterface") }, +    { "intel_pt",      NC_("x86-flag", /*/flag:intel_pt*/  "Intel Processor Tracing") }, +/* Virtualization flags: Linux defined */ +    { "tpr_shadow",   NC_("x86-flag", /*/flag:tpr_shadow*/  "Intel TPR Shadow") }, +    { "vnmi",         NC_("x86-flag", /*/flag:vnmi*/  "Intel Virtual NMI") }, +    { "flexpriority", NC_("x86-flag", /*/flag:flexpriority*/  "Intel FlexPriority") }, +    { "ept",          NC_("x86-flag", /*/flag:ept*/  "Intel Extended Page Table") }, +    { "vpid",         NC_("x86-flag", /*/flag:vpid*/  "Intel Virtual Processor ID") }, +    { "vmmcall",      NC_("x86-flag", /*/flag:vmmcall*/  "prefer VMMCALL to VMCALL") }, +/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx) */ +    { "fsgsbase",   NC_("x86-flag", /*/flag:fsgsbase*/  "{RD/WR}{FS/GS}BASE instructions") }, +    { "tsc_adjust", NC_("x86-flag", /*/flag:tsc_adjust*/  "TSC adjustment MSR") }, +    { "bmi1",       NC_("x86-flag", /*/flag:bmi1*/  "1st group bit manipulation extensions") }, +    { "hle",        NC_("x86-flag", /*/flag:hle*/  "Hardware Lock Elision") }, +    { "avx2",       NC_("x86-flag", /*/flag:avx2*/  "AVX2 instructions") }, +    { "smep",       NC_("x86-flag", /*/flag:smep*/  "Supervisor Mode Execution Protection") }, +    { "bmi2",       NC_("x86-flag", /*/flag:bmi2*/  "2nd group bit manipulation extensions") }, +    { "erms",       NC_("x86-flag", /*/flag:erms*/  "Enhanced REP MOVSB/STOSB") }, +    { "invpcid",    NC_("x86-flag", /*/flag:invpcid*/  "Invalidate Processor Context ID") }, +    { "rtm",        NC_("x86-flag", /*/flag:rtm*/  "Restricted Transactional Memory") }, +    { "cqm",        NC_("x86-flag", /*/flag:cqm*/  "Cache QoS Monitoring") }, +    { "mpx",        NC_("x86-flag", /*/flag:mpx*/  "Memory Protection Extension") }, +    { "avx512f",    NC_("x86-flag", /*/flag:avx512f*/  "AVX-512 foundation") }, +    { "avx512dq",   NC_("x86-flag", /*/flag:avx512dq*/  "AVX-512 Double/Quad instructions") }, +    { "rdseed",     NC_("x86-flag", /*/flag:rdseed*/  "The RDSEED instruction") }, +    { "adx",        NC_("x86-flag", /*/flag:adx*/  "The ADCX and ADOX instructions") }, +    { "smap",       NC_("x86-flag", /*/flag:smap*/  "Supervisor Mode Access Prevention") }, +    { "clflushopt", NC_("x86-flag", /*/flag:clflushopt*/  "CLFLUSHOPT instruction") }, +    { "clwb",       NC_("x86-flag", /*/flag:clwb*/  "CLWB instruction") }, +    { "avx512pf",   NC_("x86-flag", /*/flag:avx512pf*/  "AVX-512 Prefetch") }, +    { "avx512er",   NC_("x86-flag", /*/flag:avx512er*/  "AVX-512 Exponential and Reciprocal") }, +    { "avx512cd",   NC_("x86-flag", /*/flag:avx512cd*/  "AVX-512 Conflict Detection") }, +    { "sha_ni",     NC_("x86-flag", /*/flag:sha_ni*/  "SHA1/SHA256 Instruction Extensions") }, +    { "avx512bw",   NC_("x86-flag", /*/flag:avx512bw*/  "AVX-512 Byte/Word instructions") }, +    { "avx512vl",   NC_("x86-flag", /*/flag:avx512vl*/  "AVX-512 128/256 Vector Length extensions") }, +/* Extended state features, CPUID level 0x0000000d:1 (eax) */ +    { "xsaveopt",   NC_("x86-flag", /*/flag:xsaveopt*/  "Optimized XSAVE") }, +    { "xsavec",     NC_("x86-flag", /*/flag:xsavec*/  "XSAVEC") }, +    { "xgetbv1",    NC_("x86-flag", /*/flag:xgetbv1*/  "XGETBV with ECX = 1") }, +    { "xsaves",     NC_("x86-flag", /*/flag:xsaves*/  "XSAVES/XRSTORS") }, +/* Intel-defined CPU QoS sub-leaf, CPUID level 0x0000000F:0 (edx) */ +    { "cqm_llc",    NC_("x86-flag", /*/flag:cqm_llc*/  "LLC QoS") }, +/* Intel-defined CPU QoS sub-leaf, CPUID level 0x0000000F:1 (edx) */ +    { "cqm_occup_llc",  NC_("x86-flag", /*/flag:cqm_occup_llc*/  "LLC occupancy monitoring") }, +    { "cqm_mbm_total",  NC_("x86-flag", /*/flag:cqm_mbm_total*/  "LLC total MBM monitoring") }, +    { "cqm_mbm_local",  NC_("x86-flag", /*/flag:cqm_mbm_local*/  "LLC local MBM monitoring") }, +/* AMD-defined CPU features, CPUID level 0x80000008 (ebx) */ +    { "clzero",         NC_("x86-flag", /*/flag:clzero*/  "CLZERO instruction") }, +    { "irperf",         NC_("x86-flag", /*/flag:irperf*/  "instructions retired performance counter") }, +/* Thermal and Power Management leaf, CPUID level 0x00000006 (eax) */ +    { "dtherm",         NC_("x86-flag", /*/flag:dtherm*/  "digital thermal sensor") }, /* formerly dts */ +    { "ida",            NC_("x86-flag", /*/flag:ida*/  "Intel Dynamic Acceleration") }, +    { "arat",           NC_("x86-flag", /*/flag:arat*/  "Always Running APIC Timer") }, +    { "pln",            NC_("x86-flag", /*/flag:pln*/  "Intel Power Limit Notification") }, +    { "pts",            NC_("x86-flag", /*/flag:pts*/  "Intel Package Thermal Status") }, +    { "hwp",            NC_("x86-flag", /*/flag:hwp*/  "Intel Hardware P-states") }, +    { "hwp_notify",     NC_("x86-flag", /*/flag:hwp_notify*/  "HWP notification") }, +    { "hwp_act_window", NC_("x86-flag", /*/flag:hwp_act_window*/  "HWP Activity Window") }, +    { "hwp_epp",        NC_("x86-flag", /*/flag:hwp_epp*/  "HWP Energy Performance Preference") }, +    { "hwp_pkg_req",    NC_("x86-flag", /*/flag:hwp_pkg_req*/  "HWP package-level request") }, +/* AMD SVM Feature Identification, CPUID level 0x8000000a (edx) */ +    { "npt",            NC_("x86-flag", /*/flag:npt*/  "AMD Nested Page Table support") }, +    { "lbrv",           NC_("x86-flag", /*/flag:lbrv*/  "AMD LBR Virtualization support") }, +    { "svm_lock",       NC_("x86-flag", /*/flag:svm_lock*/  "AMD SVM locking MSR") }, +    { "nrip_save",      NC_("x86-flag", /*/flag:nrip_save*/  "AMD SVM next_rip save") }, +    { "tsc_scale",      NC_("x86-flag", /*/flag:tsc_scale*/  "AMD TSC scaling support") }, +    { "vmcb_clean",     NC_("x86-flag", /*/flag:vmcb_clean*/  "AMD VMCB clean bits support") }, +    { "flushbyasid",    NC_("x86-flag", /*/flag:flushbyasid*/  "AMD flush-by-ASID support") }, +    { "decodeassists",  NC_("x86-flag", /*/flag:decodeassists*/  "AMD Decode Assists support") }, +    { "pausefilter",    NC_("x86-flag", /*/flag:pausefilter*/  "AMD filtered pause intercept") }, +    { "pfthreshold",    NC_("x86-flag", /*/flag:pfthreshold*/  "AMD pause filter threshold") }, +    { "avic",           NC_("x86-flag", /*/flag:avic*/  "Virtual Interrupt Controller") }, +/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx) */ +    { "pku",            NC_("x86-flag", /*/flag:pku*/  "Protection Keys for Userspace") }, +    { "ospke",          NC_("x86-flag", /*/flag:ospke*/  "OS Protection Keys Enable") }, +/* AMD-defined CPU features, CPUID level 0x80000007 (ebx) */ +    { "overflow_recov", NC_("x86-flag", /*/flag:overflow_recov*/  "MCA overflow recovery support") }, +    { "succor",         NC_("x86-flag", /*/flag:succor*/  "uncorrectable error containment and recovery") }, +    { "smca",           NC_("x86-flag", /*/flag:smca*/  "Scalable MCA") }, + +/* bug workarounds */ +    { "bug:f00f",       NC_("x86-flag", /*/bug:f00f*/  "Intel F00F bug")    }, +    { "bug:fdiv",       NC_("x86-flag", /*/bug:fdiv*/  "FPU FDIV")          }, +    { "bug:coma",       NC_("x86-flag", /*/bug:coma*/  "Cyrix 6x86 coma")   }, +    { "bug:tlb_mmatch", NC_("x86-flag", /*/bug:tlb_mmatch*/  "AMD Erratum 383")   }, +    { "bug:apic_c1e",   NC_("x86-flag", /*/bug:apic_c1e*/  "AMD Erratum 400")   }, +    { "bug:11ap",       NC_("x86-flag", /*/bug:11ap*/  "Bad local APIC aka 11AP")  }, +    { "bug:fxsave_leak",      NC_("x86-flag", /*/bug:fxsave_leak*/  "FXSAVE leaks FOP/FIP/FOP") }, +    { "bug:clflush_monitor",  NC_("x86-flag", /*/bug:clflush_monitor*/  "AAI65, CLFLUSH required before MONITOR") }, +    { "bug:sysret_ss_attrs",  NC_("x86-flag", /*/bug:sysret_ss_attrs*/  "SYSRET doesn't fix up SS attrs") }, +    { "bug:espfix",       NC_("x86-flag", /*/bug:espfix*/  "IRET to 16-bit SS corrupts ESP/RSP high bits") }, +    { "bug:null_seg",     NC_("x86-flag", /*/bug:null_seg*/  "Nulling a selector preserves the base") },         /* see: detect_null_seg_behavior() */ +    { "bug:swapgs_fence", NC_("x86-flag", /*/bug:swapgs_fence*/  "SWAPGS without input dep on GS") }, +    { "bug:monitor",      NC_("x86-flag", /*/bug:monitor*/  "IPI required to wake up remote CPU") }, +    { "bug:amd_e400",     NC_("x86-flag", /*/bug:amd_e400*/  "AMD Erratum 400") }, +/* power management + * ... from arch/x86/kernel/cpu/powerflags.h */ +    { "pm:ts",            NC_("x86-flag", /*/flag:pm:ts*/  "temperature sensor")     }, +    { "pm:fid",           NC_("x86-flag", /*/flag:pm:fid*/  "frequency id control")   }, +    { "pm:vid",           NC_("x86-flag", /*/flag:pm:vid*/  "voltage id control")     }, +    { "pm:ttp",           NC_("x86-flag", /*/flag:pm:ttp*/  "thermal trip")           }, +    { "pm:tm",            NC_("x86-flag", /*/flag:pm:tm*/  "hardware thermal control")   }, +    { "pm:stc",           NC_("x86-flag", /*/flag:pm:stc*/  "software thermal control")   }, +    { "pm:100mhzsteps",   NC_("x86-flag", /*/flag:pm:100mhzsteps*/  "100 MHz multiplier control") }, +    { "pm:hwpstate",      NC_("x86-flag", /*/flag:pm:hwpstate*/  "hardware P-state control")   }, +    { "pm:cpb",           NC_("x86-flag", /*/flag:pm:cpb*/  "core performance boost")     }, +    { "pm:eff_freq_ro",   NC_("x86-flag", /*/flag:pm:eff_freq_ro*/  "Readonly aperf/mperf")       }, +    { "pm:proc_feedback", NC_("x86-flag", /*/flag:pm:proc_feedback*/  "processor feedback interface") }, +    { "pm:acc_power",     NC_("x86-flag", /*/flag:pm:acc_power*/  "accumulated power mechanism")  }, +    { NULL, NULL}, +}; + +static char all_flags[4096] = ""; + +#define APPEND_FLAG(f) strcat(all_flags, f); strcat(all_flags, " "); +const char *x86_flag_list() { +    int i = 0, built = 0; +    built = strlen(all_flags); +    if (!built) { +        while(tab_flag_meaning[i].name != NULL) { +            APPEND_FLAG(tab_flag_meaning[i].name); +            i++; +        } +    } +    return all_flags; +} + +const char *x86_flag_meaning(const char *flag) { +    int i = 0; +    if (flag) +    while(tab_flag_meaning[i].name != NULL) { +        if (strcmp(tab_flag_meaning[i].name, flag) == 0) { +            if (tab_flag_meaning[i].meaning != NULL) +                return C_("x86-flag", tab_flag_meaning[i].meaning); +            else return NULL; +        } +        i++; +    } +    return NULL; +} + +static void x86_flag_find_dups(void) { +    int t, i; + +    t = 0; +    while(tab_flag_meaning[t].name != NULL) { +        i = t+1; +        while(tab_flag_meaning[i].name != NULL) { +            if (strcmp(tab_flag_meaning[t].name, tab_flag_meaning[i].name) == 0) { +                printf("x86-flag duplicate definition: %s\n ... %d: %s\n ... %d: %s\n", +                    tab_flag_meaning[i].name, +                    t, tab_flag_meaning[t].meaning, +                    i, tab_flag_meaning[i].meaning); +            } +            i++; +        } +        t++; +    } +} diff --git a/modules/devices/x86/x86_data.h b/modules/devices/x86/x86_data.h new file mode 100644 index 00000000..66a4c80f --- /dev/null +++ b/modules/devices/x86/x86_data.h @@ -0,0 +1,28 @@ +/* + * rpiz - https://github.com/bp0/rpiz + * Copyright (C) 2017  Burt P. <pburt0@gmail.com> + * + * This program 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; either version 2 + * of the License, or (at your option) any later version. + * + * 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; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. + * + */ + +#ifndef _X86DATA_H_ +#define _X86DATA_H_ + +/* cpu flags from /proc/cpuinfo */ +const char *x86_flag_list(void);                 /* list of all known flags */ +const char *x86_flag_meaning(const char *flag);  /* lookup flag meaning */ + +#endif diff --git a/modules/devices/x86_64 b/modules/devices/x86_64 deleted file mode 120000 index de1ff735..00000000 --- a/modules/devices/x86_64 +++ /dev/null @@ -1 +0,0 @@ -./x86
\ No newline at end of file diff --git a/modules/network.c b/modules/network.c index 18f8ba65..f27a159a 100644 --- a/modules/network.c +++ b/modules/network.c @@ -80,51 +80,46 @@ void scan_statistics(gboolean reload)      FILE *netstat;      gchar buffer[256];      gchar *netstat_path; -     +    int line = 0; +      SCAN_START(); -     +      g_free(__statistics);      __statistics = g_strdup(""); -     +      if ((netstat_path = find_program("netstat"))) {        gchar *command_line = g_strdup_printf("%s -s", netstat_path); -       +        if ((netstat = popen(command_line, "r"))) {          while (fgets(buffer, 256, netstat)) {            if (!isspace(buffer[0]) && strchr(buffer, ':')) {              gchar *tmp; -             +              tmp = g_ascii_strup(strend(buffer, ':'), -1); -             +              __statistics = h_strdup_cprintf("[%s]\n",                                              __statistics,                                              tmp); -                          g_free(tmp); -          } else if (isdigit(buffer[4])) { -            gchar *tmp1 = buffer + 4, -                  *tmp2 = tmp1; -             -            while (*tmp2 && !isspace(*tmp2)) tmp2++; -            *tmp2 = 0; -            tmp2++; -             -            *tmp2 = toupper(*tmp2); -             -            __statistics = h_strdup_cprintf("%s=%s\n", + +          } else { +            gchar *tmp = buffer; + +            while (*tmp && isspace(*tmp)) tmp++; + +            __statistics = h_strdup_cprintf("<b> </b>#%d=%s\n",                                              __statistics, -                                            g_strstrip(tmp1), -                                            g_strstrip(tmp2)); +                                            line++, tmp);            }          }          pclose(netstat);        } -       +        g_free(command_line);        g_free(netstat_path);      } -     +      SCAN_END();  } @@ -133,24 +128,24 @@ void scan_dns(gboolean reload)  {      FILE *resolv;      gchar buffer[256]; -     +      SCAN_START(); -     +      g_free(__nameservers);      __nameservers = g_strdup(""); -     +      if ((resolv = fopen("/etc/resolv.conf", "r"))) {        while (fgets(buffer, 256, resolv)) {          if (g_str_has_prefix(buffer, "nameserver")) {            gchar *ip;            struct sockaddr_in sa;            char hbuf[NI_MAXHOST]; -           +            ip = g_strstrip(buffer + sizeof("nameserver")); -           +            sa.sin_family = AF_INET;            sa.sin_addr.s_addr = inet_addr(ip); -           +            if (getnameinfo((struct sockaddr *)&sa, sizeof(sa), hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD)) {                __nameservers = h_strdup_cprintf("%s=\n",                                                 __nameservers, @@ -159,15 +154,15 @@ void scan_dns(gboolean reload)                __nameservers = h_strdup_cprintf("%s=%s\n",                                                 __nameservers,                                                 ip, hbuf); -           -          }           -           + +          } +            shell_status_pulse(); -        }  +        }        }        fclose(resolv);      } -     +      SCAN_END();  } @@ -184,15 +179,15 @@ void scan_route(gboolean reload)      FILE *route;      gchar buffer[256];      gchar *route_path; -     +      SCAN_START();      g_free(__routing_table);      __routing_table = g_strdup(""); -     +      if ((route_path = find_program("route"))) {        gchar *command_line = g_strdup_printf("%s -n", route_path); -       +        if ((route = popen(command_line, "r"))) {          /* eat first two lines */          (void)fgets(buffer, 256, route); @@ -203,7 +198,7 @@ void scan_route(gboolean reload)            buffer[31] = '\0';            buffer[47] = '\0';            buffer[53] = '\0'; -           +            __routing_table = h_strdup_cprintf("%s / %s=%s|%s|%s\n",                                               __routing_table,                                               g_strstrip(buffer), g_strstrip(buffer + 16), @@ -211,14 +206,14 @@ void scan_route(gboolean reload)                                               g_strstrip(buffer + 48),                                               g_strstrip(buffer + 32));          } -         +          pclose(route);        } -       +        g_free(command_line);        g_free(route_path);      } -     +      SCAN_END();  } @@ -227,12 +222,12 @@ void scan_arp(gboolean reload)  {      FILE *arp;      gchar buffer[256]; -     +      SCAN_START();      g_free(__arp_table);      __arp_table = g_strdup(""); -     +      if ((arp = fopen("/proc/net/arp", "r"))) {        /* eat first line */        (void)fgets(buffer, 256, arp); @@ -240,17 +235,17 @@ void scan_arp(gboolean reload)        while (fgets(buffer, 256, arp)) {          buffer[15] = '\0';          buffer[58] = '\0'; -         +          __arp_table = h_strdup_cprintf("%s=%s|%s\n",                                         __arp_table,                                         g_strstrip(buffer),                                         g_strstrip(buffer + 72),                                         g_strstrip(buffer + 41));        } -       +        fclose(arp);      } -     +      SCAN_END();  } @@ -260,15 +255,15 @@ void scan_connections(gboolean reload)      FILE *netstat;      gchar buffer[256];      gchar *netstat_path; -     +      SCAN_START();      g_free(__connections);      __connections = g_strdup(""); -     +      if ((netstat_path = find_program("netstat"))) {        gchar *command_line = g_strdup_printf("%s -an", netstat_path); -       +        if ((netstat = popen("netstat -an", "r"))) {          while (fgets(buffer, 256, netstat)) {            buffer[6] = '\0'; @@ -284,91 +279,99 @@ void scan_connections(gboolean reload)                                               g_strstrip(buffer + 68));	/* state */            }          } -         +          pclose(netstat);        } -       +        g_free(command_line);        g_free(netstat_path);      } -     +      SCAN_END();  }  gchar *callback_arp()  { -    return g_strdup_printf(_("[ARP Table]\n" +    return g_strdup_printf("[%s]\n"                             "%s\n"                             "[$ShellParam$]\n"                             "ReloadInterval=3000\n" -                           "ColumnTitle$TextValue=IP Address\n" -                           "ColumnTitle$Value=Interface\n" -                           "ColumnTitle$Extra1=MAC Address\n" -                           "ShowColumnHeaders=true\n"), -                           __arp_table); +                           "ColumnTitle$TextValue=%s\n" /* IP Address */ +                           "ColumnTitle$Value=%s\n" /* Interface */ +                           "ColumnTitle$Extra1=%s\n" /* MAC Address */ +                           "ShowColumnHeaders=true\n", +                           _("ARP Table"), __arp_table, +                           _("IP Address"), _("Interface"), _("MAC Address") );  }  gchar *callback_shares()  { -    return g_strdup_printf("[SAMBA]\n" -			   "%s\n" -			   "[NFS]\n" -			   "%s", smb_shares_list, nfs_shares_list); +    return g_strdup_printf("[%s]\n" +                "%s\n" +                "[%s]\n" +                "%s", +                _("SAMBA"), smb_shares_list, +                _("NFS"), nfs_shares_list);  }  gchar *callback_dns()  { -    return g_strdup_printf(_("[Name servers]\n" +    return g_strdup_printf("[%s]\n"                             "%s\n"                             "[$ShellParam$]\n" -                           "ColumnTitle$TextValue=IP Address\n" -                           "ColumnTitle$Value=Name\n" -                           "ShowColumnHeaders=true\n"), __nameservers); +                           "ColumnTitle$TextValue=%s\n" /* IP Address */ +                           "ColumnTitle$Value=%s\n" /* Name */ +                           "ShowColumnHeaders=true\n", +                           _("Name Servers"), __nameservers, +                           _("IP Address"), _("Name") );  }  gchar *callback_connections()  { -    return g_strdup_printf(_("[Connections]\n" +    return g_strdup_printf("[%s]\n"                             "%s\n"                             "[$ShellParam$]\n"                             "ReloadInterval=3000\n" -                           "ColumnTitle$TextValue=Local Address\n" -                           "ColumnTitle$Value=Protocol\n" -                           "ColumnTitle$Extra1=Foreign Address\n" -                           "ColumnTitle$Extra2=State\n" -                           "ShowColumnHeaders=true\n"), -                           __connections); +                           "ColumnTitle$TextValue=%s\n" /* Local Address */ +                           "ColumnTitle$Value=%s\n" /* Protocol */ +                           "ColumnTitle$Extra1=%s\n" /* Foreign Address */ +                           "ColumnTitle$Extra2=%s\n" /* State */ +                           "ShowColumnHeaders=true\n", +                           _("Connections"), __connections, +                           _("Local Address"), _("Protocol"), _("Foreign Address"), _("State") );  }  gchar *callback_network()  { -    return g_strdup_printf(_("%s\n" -                           "[$ShellParam$]\n" -			   "ReloadInterval=3000\n" -			   "ViewType=1\n" -			   "ColumnTitle$TextValue=Interface\n" -			   "ColumnTitle$Value=IP Address\n" -			   "ColumnTitle$Extra1=Sent\n" -			   "ColumnTitle$Extra2=Received\n" -			   "ShowColumnHeaders=true\n" -			   "%s"), -			   network_interfaces, -			   network_icons); +    return g_strdup_printf("%s\n" +               "[$ShellParam$]\n" +               "ReloadInterval=3000\n" +               "ViewType=1\n" +               "ColumnTitle$TextValue=%s\n" /* Interface */ +               "ColumnTitle$Value=%s\n" /* IP Address */ +               "ColumnTitle$Extra1=%s\n" /* Sent */ +               "ColumnTitle$Extra2=%s\n" /* Received */ +               "ShowColumnHeaders=true\n" +               "%s", +               network_interfaces, +               _("Interface"), _("IP Address"), _("Sent"), _("Received"), +               network_icons);  }  gchar *callback_route()  { -    return g_strdup_printf(_("[IP routing table]\n" +    return g_strdup_printf("[%s]\n"                             "%s\n"                             "[$ShellParam$]\n"                             "ViewType=0\n"                             "ReloadInterval=3000\n" -                           "ColumnTitle$TextValue=Destination / Gateway\n" -                           "ColumnTitle$Value=Interface\n" -                           "ColumnTitle$Extra1=Flags\n" -                           "ColumnTitle$Extra2=Mask\n" -                           "ShowColumnHeaders=true\n"), -                           __routing_table); +                           "ColumnTitle$TextValue=%s\n" /* Destination / Gateway */ +                           "ColumnTitle$Value=%s\n" /* Interface */ +                           "ColumnTitle$Extra1=%s\n" /* Flags */ +                           "ColumnTitle$Extra2=%s\n" /* Mask */ +                           "ShowColumnHeaders=true\n", +                           _("IP routing table"), __routing_table, +                           _("Destination/Gateway"), _("Interface"), _("Flags"), _("Mask") );  }  gchar *callback_statistics() @@ -411,12 +414,12 @@ void hi_module_init(void)  void hi_module_deinit(void)  {      moreinfo_del_with_prefix("NET"); -     +      g_free(smb_shares_list);      g_free(nfs_shares_list);      g_free(network_interfaces);      g_free(network_icons); -     +      g_free(__statistics);      g_free(__nameservers);      g_free(__arp_table); diff --git a/modules/network/net.c b/modules/network/net.c index ebb0612a..99a5e616 100644 --- a/modules/network/net.c +++ b/modules/network/net.c @@ -40,7 +40,7 @@  #include <linux/wireless.h>  #else  #include <net/if.h> -#endif	/* HAS_LINUX_WE */ +#endif  /* HAS_LINUX_WE */  #include "hardinfo.h"  #include "network.h" @@ -57,18 +57,26 @@ struct _NetInfo {      char broadcast[16];  #ifdef HAS_LINUX_WE -    char wi_essid[IW_ESSID_MAX_SIZE + 1];    +    char wi_essid[IW_ESSID_MAX_SIZE + 1];      int  wi_rate;      int  wi_mode, wi_status;      gboolean wi_has_txpower;      struct iw_param wi_txpower; -    int	 wi_quality_level, wi_signal_level, wi_noise_level; +    int  wi_quality_level, wi_signal_level, wi_noise_level;      gboolean is_wireless;  #endif  };  #ifdef HAS_LINUX_WE -const gchar *wi_operation_modes[] = { "Auto", "Ad-Hoc", "Managed", "Master", "Repeater", "Secondary", "Unknown" }; +const gchar *wi_operation_modes[] = { +    NC_("wi-op-mode", "Auto"), +    NC_("wi-op-mode", "Ad-Hoc"), +    NC_("wi-op-mode", "Managed"), +    NC_("wi-op-mode", "Master"), +    NC_("wi-op-mode", "Repeater"), +    NC_("wi-op-mode", "Secondary"), +    NC_("wi-op-mode", "(Unknown)") +};  void get_wireless_info(int fd, NetInfo *netinfo)  { @@ -78,16 +86,16 @@ void get_wireless_info(int fd, NetInfo *netinfo)    int r, trash;    netinfo->is_wireless = FALSE; -   +    if ((wrls = fopen("/proc/net/wireless", "r"))) {        while (fgets(wbuf, 256, wrls)) {            if (strchr(wbuf, ':') && strstr(wbuf, netinfo->name)) {                gchar *buf1 = wbuf; -               +                netinfo->is_wireless = TRUE; -               +                buf1 = strchr(buf1, ':') + 1; -               +                if (strchr(buf1, '.')) {                    sscanf(buf1, "%d %d. %d. %d %d %d %d %d %d %d",                           &(netinfo->wi_status), @@ -104,7 +112,7 @@ void get_wireless_info(int fd, NetInfo *netinfo)                           &trash, &trash, &trash, &trash, &trash,                           &trash);                } -               +                break;            }        } @@ -113,14 +121,14 @@ void get_wireless_info(int fd, NetInfo *netinfo)    if (!netinfo->is_wireless)      return; -   +    strncpy(wi_req.ifr_name, netinfo->name, 16); -   +    /* obtain essid */    wi_req.u.essid.pointer = netinfo->wi_essid;    wi_req.u.essid.length  = IW_ESSID_MAX_SIZE + 1;    wi_req.u.essid.flags   = 0; -   +    if (ioctl(fd, SIOCGIWESSID, &wi_req) < 0) {      strcpy(netinfo->wi_essid, "");    } else { @@ -133,7 +141,7 @@ void get_wireless_info(int fd, NetInfo *netinfo)    } else {      netinfo->wi_rate = wi_req.u.bitrate.value;    } -   +    /* obtain operation mode */    if (ioctl(fd, SIOCGIWMODE, &wi_req) < 0) {      netinfo->wi_mode = 0; @@ -144,19 +152,19 @@ void get_wireless_info(int fd, NetInfo *netinfo)        netinfo->wi_mode = 6;      }    } -   +  #if WIRELESS_EXT >= 10    /* obtain txpower */    if (ioctl(fd, SIOCGIWTXPOW, &wi_req) < 0) {      netinfo->wi_has_txpower = FALSE;    } else {      netinfo->wi_has_txpower = TRUE; -           +      memcpy(&netinfo->wi_txpower, &wi_req.u.txpower, sizeof(struct iw_param));    }  #else    netinfo->wi_has_txpower = FALSE; -#endif	/* WIRELESS_EXT >= 10 */ +#endif  /* WIRELESS_EXT >= 10 */  }  #endif /* HAS_LINUX_WE */ @@ -174,47 +182,47 @@ void get_net_info(char *if_name, NetInfo * netinfo)      /* MTU */      strcpy(ifr.ifr_name, if_name);      if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) { -	netinfo->mtu = 0; +    netinfo->mtu = 0;      } else { -	netinfo->mtu = ifr.ifr_mtu; +    netinfo->mtu = ifr.ifr_mtu;      }      /* HW Address */      strcpy(ifr.ifr_name, if_name);      if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { -	memset(netinfo->mac, 0, 8); +    memset(netinfo->mac, 0, 8);      } else { -	memcpy(netinfo->mac, ifr.ifr_ifru.ifru_hwaddr.sa_data, 8); +    memcpy(netinfo->mac, ifr.ifr_ifru.ifru_hwaddr.sa_data, 8);      }      /* IP Address */      strcpy(ifr.ifr_name, if_name);      if (ioctl(fd, SIOCGIFADDR, &ifr) < 0) { -	netinfo->ip[0] = 0; +    netinfo->ip[0] = 0;      } else { -	snprintf(netinfo->ip, sizeof(netinfo->ip), "%s", -		inet_ntoa(((struct sockaddr_in *) &ifr.ifr_addr)-> -			  sin_addr)); +    snprintf(netinfo->ip, sizeof(netinfo->ip), "%s", +        inet_ntoa(((struct sockaddr_in *) &ifr.ifr_addr)-> +              sin_addr));      }      /* Mask Address */      strcpy(ifr.ifr_name, if_name);      if (ioctl(fd, SIOCGIFNETMASK, &ifr) < 0) { -	netinfo->mask[0] = 0; +    netinfo->mask[0] = 0;      } else { -	snprintf(netinfo->mask, sizeof(netinfo->mask), "%s", -		inet_ntoa(((struct sockaddr_in *) &ifr.ifr_addr)-> -			  sin_addr)); +    snprintf(netinfo->mask, sizeof(netinfo->mask), "%s", +        inet_ntoa(((struct sockaddr_in *) &ifr.ifr_addr)-> +              sin_addr));      }      /* Broadcast Address */      strcpy(ifr.ifr_name, if_name);      if (ioctl(fd, SIOCGIFBRDADDR, &ifr) < 0) { -	netinfo->broadcast[0] = 0; +    netinfo->broadcast[0] = 0;      } else { -	snprintf(netinfo->broadcast, sizeof(netinfo->broadcast), "%s", -		inet_ntoa(((struct sockaddr_in *) &ifr.ifr_addr)-> -			  sin_addr)); +    snprintf(netinfo->broadcast, sizeof(netinfo->broadcast), "%s", +        inet_ntoa(((struct sockaddr_in *) &ifr.ifr_addr)-> +              sin_addr));      }  #ifdef HAS_LINUX_WE @@ -230,34 +238,41 @@ static struct {      char *label;      char *icon;  } netdev2type[] = { -    { "eth", "Ethernet", "network-interface" }, -    { "lo", "Loopback", "network" }, -    { "ppp", "Point-to-Point", "modem" }, -    { "ath", "Wireless", "wireless" }, -    { "wlan", "Wireless", "wireless" }, -    { "ra", "Wireless", "wireless" }, -    { "wl", "Wireless", "wireless" }, -    { "wmaster", "Wireless", "wireless" }, -    { "tun", "Virtual Point-to-Point (TUN)", "network" }, -    { "tap", "Ethernet (TAP)", "network" }, -    { "plip", "Parallel Line Internet Protocol", "network" }, -    { "irlan", "Infrared", "network" }, -    { "slip", "Serial Line Internet Protocol", "network" }, -    { "isdn", "Integrated Services Digital Network", "modem" }, -    { "sit", "IPv6-over-IPv4 Tunnel", "network" }, -    { "vmnet8", "VMWare Virtual Network Interface (NAT)", "computer" }, -    { "vmnet", "VMWare Virtual Network Interface", "computer" }, -    { "pan", "Personal Area Network (PAN)", "bluetooth" }, -    { "bnep", "Bluetooth", "bluetooth" }, -    { "br", "Bridge Interface", "network" }, -    { "ham", "Hamachi Virtual Personal Network", "network"}, -    { "net", "Ethernet", "network-interface" }, -    { "ifb", "Intermediate Functional Block", "network" }, -    { "gre", "GRE Network Tunnel", "network" }, -    { "msh", "Mesh Network", "wireless" }, -    { "wmaster", "Wireless Master Interface", "wireless" }, -    { "vboxnet", "VirtualBox Virtual Network Interface", "network" }, -    { NULL, "Unknown", "network" }, +    /* Classic */ +    { "eth", NC_("net-if-type", "Ethernet"), "network-interface" }, +    { "lo", NC_("net-if-type", "Loopback"), "network" }, +    { "ppp", NC_("net-if-type", "Point-to-Point"), "modem" }, +    { "ath", NC_("net-if-type", "Wireless"), "wireless" }, +    { "wlan", NC_("net-if-type", "Wireless"), "wireless" }, +    { "ra", NC_("net-if-type", "Wireless"), "wireless" }, +    { "wmaster", NC_("net-if-type", "Wireless"), "wireless" }, +    { "tun", NC_("net-if-type", "Virtual Point-to-Point (TUN)"), "network" }, +    { "tap", NC_("net-if-type", "Ethernet (TAP)"), "network" }, +    { "plip", NC_("net-if-type", "Parallel Line Internet Protocol"), "network" }, +    { "irlan", NC_("net-if-type", "Infrared"), "network" }, +    { "slip", NC_("net-if-type", "Serial Line Internet Protocol"), "network" }, +    { "isdn", NC_("net-if-type", "Integrated Services Digital Network"), "modem" }, +    { "sit", NC_("net-if-type", "IPv6-over-IPv4 Tunnel"), "network" }, +    { "vmnet8", NC_("net-if-type", "VMWare Virtual Network Interface (NAT)"), "computer" }, +    { "vmnet", NC_("net-if-type", "VMWare Virtual Network Interface"), "computer" }, +    { "pan", NC_("net-if-type", "Personal Area Network (PAN)"), "bluetooth" }, +    { "bnep", NC_("net-if-type", "Bluetooth"), "bluetooth" }, +    { "br", NC_("net-if-type", "Bridge Interface"), "network" }, +    { "ham", NC_("net-if-type", "Hamachi Virtual Personal Network"), "network"}, +    { "net", NC_("net-if-type", "Ethernet"), "network-interface" }, +    { "ifb", NC_("net-if-type", "Intermediate Functional Block"), "network" }, +    { "gre", NC_("net-if-type", "GRE Network Tunnel"), "network" }, +    { "msh", NC_("net-if-type", "Mesh Network"), "wireless" }, +    { "wmaster", NC_("net-if-type", "Wireless Master Interface"), "wireless" }, +    { "vboxnet", NC_("net-if-type", "VirtualBox Virtual Network Interface"), "network" }, + +    /* Predictable network interface device names (systemd) */ +    { "en", NC_("net-if-type", "Ethernet"), "network-interface" }, +    { "sl", NC_("net-if-type", "Serial Line Internet Protocol"), "network" }, +    { "wl", NC_("net-if-type", "Wireless"), "wireless" }, +    { "ww", NC_("net-if-type", "Wireless (WAN)"), "wireless" }, + +    { NULL, NC_("net-if-type", "(Unknown)"), "network" },  };  static void net_get_iface_type(gchar * name, gchar ** type, gchar ** icon, NetInfo *ni) @@ -266,19 +281,19 @@ static void net_get_iface_type(gchar * name, gchar ** type, gchar ** icon, NetIn  #ifdef HAS_LINUX_WE      if (ni->is_wireless) { -        *type = "Wireless"; +        *type = "Wireless"; /* translated when used */          *icon = "wireless"; -         +          return;      }  #endif      for (i = 0; netdev2type[i].type; i++) { -	if (g_str_has_prefix(name, netdev2type[i].type)) -	    break; +    if (g_str_has_prefix(name, netdev2type[i].type)) +        break;      } -    *type = netdev2type[i].label; +    *type = netdev2type[i].label; /* translated when used */      *icon = netdev2type[i].icon;  } @@ -288,6 +303,30 @@ remove_net_devices(gpointer key, gpointer value, gpointer data)      return g_str_has_prefix(key, "NET");  } +#ifdef HAS_LINUX_WE +const char *wifi_bars(int signal, int noise) +{ +    float quality; + +    if (signal <= -100) +        quality = 0.0; +    else if (signal >= -50) +        quality = 1.0; +    else +        quality = (2.0 * (signal + 100.0)) / 100.0; + +    if (quality < 0.20) +        return "▰▱▱▱▱"; +    if (quality < 0.40) +        return "▰▰▱▱▱"; +    if (quality < 0.60) +        return "▰▰▰▱▱"; +    if (quality < 0.80) +        return "▰▰▰▰▱"; +    return "▰▰▰▰▰"; +} +#endif +  static void scan_net_interfaces_24(void)  {      FILE *proc_net; @@ -303,20 +342,20 @@ static void scan_net_interfaces_24(void)      gdouble trans_packets;      if (!g_file_test("/proc/net/dev", G_FILE_TEST_EXISTS)) { -	if (network_interfaces) { -	    g_free(network_interfaces); -	    network_interfaces = g_strdup("[Network Interfaces]\n" -					  "None found=\n"); -	} +    if (network_interfaces) { +        g_free(network_interfaces); +        network_interfaces = g_strdup_printf("[%s]]\n%s=\n", +            _("Network Interfaces"), _("None Found") ); +    } -	return; +    return;      }      g_free(network_interfaces);      g_free(network_icons); -    network_interfaces = g_strdup("[Network Interfaces]\n"); +    network_interfaces = g_strdup_printf("[%s]\n", _("Network Interfaces"));      network_icons = g_strdup("");      proc_net = fopen("/proc/net/dev", "r"); @@ -324,118 +363,126 @@ static void scan_net_interfaces_24(void)          return;      while (fgets(buffer, 256, proc_net)) { -	if (strchr(buffer, ':')) { -	    gint trash; -	    gchar ifacename[16]; -	    gchar *buf = buffer; -	    gchar *iface_type, *iface_icon; -	    gint i; - -	    buf = g_strstrip(buf); - -	    memset(ifacename, 0, 16); - -	    for (i = 0; buffer[i] != ':' && i < 16; i++) { -		ifacename[i] = buffer[i]; -	    } - -	    buf = strchr(buf, ':') + 1; - -	    /* iface: bytes packets errs drop fifo frame compressed multicast */ -	    sscanf(buf, "%lf %lf %lf %d %d %d %d %d %lf %lf %lf", -		   &recv_bytes, &recv_packets, -		   &recv_errors, &trash, &trash, &trash, &trash, -		   &trash, &trans_bytes, &trans_packets, &trans_errors); - -	    gdouble recv_mb = recv_bytes / 1048576.0; -	    gdouble trans_mb = trans_bytes / 1048576.0; - -	    get_net_info(ifacename, &ni); - -	    devid = g_strdup_printf("NET%s", ifacename); - -	    network_interfaces = -		h_strdup_cprintf -		("$%s$%s=%s|%.2lfMiB|%.2lfMiB\n", -		 network_interfaces, devid, ifacename, ni.ip[0] ? ni.ip : "", -		 trans_mb, recv_mb); -	    net_get_iface_type(ifacename, &iface_type, &iface_icon, &ni); - -	    network_icons = h_strdup_cprintf("Icon$%s$%s=%s.png\n", -					     network_icons, devid, -					     ifacename, iface_icon); - -	    detailed = g_strdup_printf("[Network Adapter Properties]\n" -				       "Interface Type=%s\n" -				       "Hardware Address (MAC)=%02x:%02x:%02x:%02x:%02x:%02x\n" -				       "MTU=%d\n" -				       "[Transfer Details]\n" -				       "Bytes Received=%.0lf (%.2fMiB)\n" -				       "Bytes Sent=%.0lf (%.2fMiB)\n", -				       iface_type, -				       ni.mac[0], ni.mac[1], -				       ni.mac[2], ni.mac[3], -				       ni.mac[4], ni.mac[5], -				       ni.mtu, -				       recv_bytes, recv_mb, -				       trans_bytes, trans_mb); -             +    if (strchr(buffer, ':')) { +        gint trash; +        gchar ifacename[16]; +        gchar *buf = buffer; +        gchar *iface_type, *iface_icon; +        gint i; + +        buf = g_strstrip(buf); + +        memset(ifacename, 0, 16); + +        for (i = 0; buffer[i] != ':' && i < 16; i++) { +        ifacename[i] = buffer[i]; +        } + +        buf = strchr(buf, ':') + 1; + +        /* iface: bytes packets errs drop fifo frame compressed multicast */ +        sscanf(buf, "%lf %lf %lf %d %d %d %d %d %lf %lf %lf", +           &recv_bytes, &recv_packets, +           &recv_errors, &trash, &trash, &trash, &trash, +           &trash, &trans_bytes, &trans_packets, &trans_errors); + +        gdouble recv_mb = recv_bytes / 1048576.0; +        gdouble trans_mb = trans_bytes / 1048576.0; + +        get_net_info(ifacename, &ni); + +        devid = g_strdup_printf("NET%s", ifacename); + +        network_interfaces = +        h_strdup_cprintf +        ("$%s$%s=%s|%.2lf%s|%.2lf%s\n", +         network_interfaces, devid, ifacename, ni.ip[0] ? ni.ip : "", +         trans_mb, _("MiB"), recv_mb, _("MiB")); +        net_get_iface_type(ifacename, &iface_type, &iface_icon, &ni); + +        network_icons = h_strdup_cprintf("Icon$%s$%s=%s.png\n", +                         network_icons, devid, +                         ifacename, iface_icon); + +        detailed = g_strdup_printf("[%s]\n" +                       "%s=%s\n" /* Interface Type */ +                       "%s=%02x:%02x:%02x:%02x:%02x:%02x\n" /* MAC */ +                       "%s=%d\n" /* MTU */ +                       "[%s]\n" /*Transfer Details*/ +                       "%s=%.0lf (%.2f%s)\n" /* Bytes Received */ +                       "%s=%.0lf (%.2f%s)\n" /* Bytes Sent */, +                       _("Network Adapter Properties"), +                       _("Interface Type"), C_("net-if-type", iface_type), +                       _("Hardware Address (MAC)"), +                       ni.mac[0], ni.mac[1], +                       ni.mac[2], ni.mac[3], +                       ni.mac[4], ni.mac[5], +                       _("MTU"), ni.mtu, +                       _("Transfer Details"), +                       _("Bytes Received"), recv_bytes, recv_mb, _("MiB"), +                       _("Bytes Sent"), trans_bytes, trans_mb, _("MiB")); +  #ifdef HAS_LINUX_WE -            if (ni.is_wireless) { -              gchar *txpower; -               -              if (ni.wi_has_txpower) { +        if (ni.is_wireless) { +            gchar *txpower; + +            if (ni.wi_has_txpower) {                  gint mw, dbm; -               +                  if (ni.wi_txpower.flags & IW_TXPOW_MWATT) { -                  mw = ni.wi_txpower.value; -                  dbm = (int) ceil(10.0 * log10((double) ni.wi_txpower.value)); +                    mw = ni.wi_txpower.value; +                    dbm = (int) ceil(10.0 * log10((double) ni.wi_txpower.value));                  } else { -                  dbm = ni.wi_txpower.value; -                  mw = (int) floor(pow(10.0, ((double) dbm / 10.0))); +                    dbm = ni.wi_txpower.value; +                    mw = (int) floor(pow(10.0, ((double) dbm / 10.0)));                  } -                 -                txpower = g_strdup_printf("%ddBm (%dmW)", dbm, mw); -              } else { -                txpower = g_strdup("Unknown"); -              } -             -              detailed = h_strdup_cprintf("\n[Wireless Properties]\n" -                                          "Network Name (SSID)=%s\n" -                                          "Bit Rate=%dMb/s\n" -                                          "Transmission Power=%s\n" -                                          "Mode=%s\n" -                                          "Status=%d\n" -                                          "Link Quality=%d\n" -                                          "Signal / Noise=%d dBm / %d dBm\n", -                                          detailed, -                                          ni.wi_essid, -                                          ni.wi_rate / 1000000, -                                          txpower, -                                          wi_operation_modes[ni.wi_mode], -                                          ni.wi_status, -                                          ni.wi_quality_level, -                                          ni.wi_signal_level, -                                          ni.wi_noise_level); - -              g_free(txpower); + +                txpower = g_strdup_printf("%d%s (%d%s)", dbm, _("dBm"), mw, _("mW")); +            } else { +                txpower = g_strdup(_("(Unknown)"));              } + +            detailed = h_strdup_cprintf("\n[%s]\n" +                "%s=%s\n" /* Network Name (SSID) */ +                "%s=%d%s\n" /* Bit Rate */ +                "%s=%s\n" /* Transmission Power */ +                "%s=%s\n" /* Mode */ +                "%s=%d\n" /* Status */ +                "%s=%d\n" /* Link Quality */ +                "%s=%d %s / %d %s (%s)\n", +                detailed, +                _("Wireless Properties"), +                _("Network Name (SSID)"), ni.wi_essid, +                _("Bit Rate"), ni.wi_rate / 1000000, _("Mb/s"), +                _("Transmission Power"), txpower, +                _("Mode"), C_("wi-op-mode", wi_operation_modes[ni.wi_mode]), +                _("Status"), ni.wi_status, +                _("Link Quality"), ni.wi_quality_level, +                _("Signal / Noise"), +                    ni.wi_signal_level, _("dBm"), +                    ni.wi_noise_level, _("dBm"), +                wifi_bars(ni.wi_signal_level, ni.wi_noise_level)); + +            g_free(txpower); +        }  #endif -	    if (ni.ip[0] || ni.mask[0] || ni.broadcast[0]) { -		detailed = -		    h_strdup_cprintf("\n[Internet Protocol (IPv4)]\n" -				     "IP Address=%s\n" "Mask=%s\n" -				     "Broadcast Address=%s\n", detailed, -				     ni.ip[0] ? ni.ip : "Not set", -				     ni.mask[0] ? ni.mask : "Not set", -				     ni.broadcast[0] ? ni. -				     broadcast : "Not set"); -	    } - -	    moreinfo_add_with_prefix("NET", devid, detailed); -	    g_free(devid); -	} +        if (ni.ip[0] || ni.mask[0] || ni.broadcast[0]) { +        detailed = +            h_strdup_cprintf("\n[%s]\n" +                     "%s=%s\n" +                     "%s=%s\n" +                     "%s=%s\n", detailed, +                     _("Internet Protocol (IPv4)"), +                     _("IP Address"), ni.ip[0] ? ni.ip : _("(Not set)"), +                     _("Mask"), ni.mask[0] ? ni.mask : _("(Not set)"), +                     _("Broadcast Address"), +                        ni.broadcast[0] ? ni.broadcast : _("(Not set)") ); +        } + +        moreinfo_add_with_prefix("NET", devid, detailed); +        g_free(devid); +    }      }      fclose(proc_net);  } | 
