summaryrefslogtreecommitdiff
path: root/modules/devices.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/devices.c')
-rw-r--r--modules/devices.c389
1 files changed, 244 insertions, 145 deletions
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;