summaryrefslogtreecommitdiff
path: root/modules/devices.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/devices.c')
-rw-r--r--modules/devices.c613
1 files changed, 613 insertions, 0 deletions
diff --git a/modules/devices.c b/modules/devices.c
new file mode 100644
index 00000000..87bb8a80
--- /dev/null
+++ b/modules/devices.c
@@ -0,0 +1,613 @@
+/*
+ * 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
+ */
+
+#ifndef __USE_XOPEN
+#define __USE_XOPEN
+#endif /* __USE_XOPEN */
+
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE
+#endif /* _XOPEN_SOURCE */
+
+#include <gtk/gtk.h>
+#include <config.h>
+#include <string.h>
+
+#include <hardinfo.h>
+#include <shell.h>
+#include <iconcache.h>
+#include <syncmanager.h>
+
+#include <expr.h>
+#include <socket.h>
+
+#include "devices.h"
+
+gchar *callback_processors();
+gchar *callback_memory();
+gchar *callback_battery();
+gchar *callback_pci();
+gchar *callback_sensors();
+gchar *callback_printers();
+gchar *callback_storage();
+gchar *callback_input();
+gchar *callback_usb();
+#if defined(ARCH_x86) || defined(ARCH_x86_64)
+gchar *callback_dmi();
+gchar *callback_spd();
+#endif
+gchar *callback_device_resources();
+
+void scan_processors(gboolean reload);
+void scan_memory(gboolean reload);
+void scan_battery(gboolean reload);
+void scan_pci(gboolean reload);
+void scan_sensors(gboolean reload);
+void scan_printers(gboolean reload);
+void scan_storage(gboolean reload);
+void scan_input(gboolean reload);
+void scan_usb(gboolean reload);
+#if defined(ARCH_x86) || defined(ARCH_x86_64)
+void scan_dmi(gboolean reload);
+void scan_spd(gboolean reload);
+#endif
+void scan_device_resources(gboolean reload);
+
+gboolean root_required_for_resources(void);
+
+gchar *hi_more_info(gchar *entry);
+
+enum {
+ ENTRY_PROCESSOR,
+ ENTRY_MEMORY,
+ ENTRY_PCI,
+ ENTRY_USB,
+ ENTRY_PRINTERS,
+ ENTRY_BATTERY,
+ ENTRY_SENSORS,
+ ENTRY_INPUT,
+ ENTRY_STORAGE,
+ ENTRY_DMI,
+ ENTRY_SPD,
+ ENTRY_RESOURCES
+};
+
+static ModuleEntry entries[] = {
+ [ENTRY_PROCESSOR] = {N_("Processor"), "processor.png", callback_processors, scan_processors, MODULE_FLAG_NONE},
+ [ENTRY_MEMORY] = {N_("Memory"), "memory.png", callback_memory, scan_memory, MODULE_FLAG_NONE},
+ [ENTRY_PCI] = {N_("PCI Devices"), "devices.png", callback_pci, scan_pci, MODULE_FLAG_NONE},
+ [ENTRY_USB] = {N_("USB Devices"), "usb.png", callback_usb, scan_usb, MODULE_FLAG_NONE},
+ [ENTRY_PRINTERS] = {N_("Printers"), "printer.png", callback_printers, scan_printers, MODULE_FLAG_NONE},
+ [ENTRY_BATTERY] = {N_("Battery"), "battery.png", callback_battery, scan_battery, MODULE_FLAG_NONE},
+ [ENTRY_SENSORS] = {N_("Sensors"), "therm.png", callback_sensors, scan_sensors, MODULE_FLAG_NONE},
+ [ENTRY_INPUT] = {N_("Input Devices"), "inputdevices.png", callback_input, scan_input, MODULE_FLAG_NONE},
+ [ENTRY_STORAGE] = {N_("Storage"), "hdd.png", callback_storage, scan_storage, MODULE_FLAG_NONE},
+#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},
+#endif /* x86 or x86_64 */
+ [ENTRY_RESOURCES] = {N_("Resources"), "resources.png", callback_device_resources, scan_device_resources, MODULE_FLAG_NONE},
+ {NULL}
+};
+
+static GSList *processors = NULL;
+gchar *printer_list = NULL;
+gchar *printer_icons = NULL;
+gchar *pci_list = NULL;
+gchar *input_list = NULL;
+gchar *storage_list = NULL;
+gchar *battery_list = NULL;
+gchar *meminfo = NULL;
+gchar *lginterval = NULL;
+
+#include <vendor.h>
+
+gchar *get_processor_name(void)
+{
+ scan_processors(FALSE);
+
+ Processor *p = (Processor *) processors->data;
+
+ if (g_slist_length(processors) > 1) {
+ return idle_free(g_strdup_printf("%dx %s",
+ g_slist_length(processors),
+ p->model_name));
+ } else {
+ return p->model_name;
+ }
+}
+
+gchar *get_storage_devices(void)
+{
+ scan_storage(FALSE);
+
+ return storage_list;
+}
+
+gchar *get_printers(void)
+{
+ scan_printers(FALSE);
+
+ return printer_list;
+}
+
+gchar *get_input_devices(void)
+{
+ scan_input(FALSE);
+
+ return input_list;
+}
+
+gchar *get_processor_count(void)
+{
+ scan_processors(FALSE);
+
+ return g_strdup_printf("%d", g_slist_length(processors));
+}
+
+gchar *get_processor_frequency(void)
+{
+ Processor *p;
+
+ scan_processors(FALSE);
+
+ p = (Processor *)processors->data;
+ if (p->cpu_mhz == 0.0f) {
+ return g_strdup(N_("Unknown"));
+ } else {
+ return g_strdup_printf("%.0f", p->cpu_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;
+}
+
+gchar *get_motherboard(void)
+{
+ char *board_name, *board_vendor;
+#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;
+ }
+ }
+
+ return board_vendor;
+ }
+#endif
+
+ return g_strdup(_("Unknown"));
+}
+
+ShellModuleMethod *hi_exported_methods(void)
+{
+ static ShellModuleMethod m[] = {
+ {"getProcessorCount", get_processor_count},
+ {"getProcessorName", get_processor_name},
+ {"getProcessorFrequency", get_processor_frequency},
+ {"getMemoryTotal", get_memory_total},
+ {"getStorageDevices", get_storage_devices},
+ {"getPrinters", get_printers},
+ {"getInputDevices", get_input_devices},
+ {"getPCIDeviceDescription", get_pci_device_description},
+ {"getMotherboard", get_motherboard},
+ {NULL}
+ };
+
+ return m;
+}
+
+gchar *hi_more_info(gchar * entry)
+{
+ gchar *info = moreinfo_lookup_with_prefix("DEV", entry);
+
+ if (info)
+ return g_strdup(info);
+
+ return g_strdup("?");
+}
+
+gchar *hi_get_field(gchar * field)
+{
+ gchar *info = moreinfo_lookup_with_prefix("DEV", field);
+
+ if (info)
+ return g_strdup(info);
+
+ return g_strdup(field);
+}
+
+#if defined(ARCH_x86) || defined(ARCH_x86_64)
+void scan_dmi(gboolean reload)
+{
+ SCAN_START();
+ __scan_dmi();
+ SCAN_END();
+}
+
+void scan_spd(gboolean reload)
+{
+ SCAN_START();
+ scan_spd_do();
+ SCAN_END();
+}
+#endif
+
+void scan_processors(gboolean reload)
+{
+ SCAN_START();
+ if (!processors)
+ processors = processor_scan();
+ SCAN_END();
+}
+
+void scan_memory(gboolean reload)
+{
+ SCAN_START();
+ scan_memory_do();
+ SCAN_END();
+}
+
+void scan_battery(gboolean reload)
+{
+ SCAN_START();
+ scan_battery_do();
+ SCAN_END();
+}
+
+void scan_pci(gboolean reload)
+{
+ SCAN_START();
+ scan_pci_do();
+ SCAN_END();
+}
+
+void scan_sensors(gboolean reload)
+{
+ SCAN_START();
+ scan_sensors_do();
+ SCAN_END();
+}
+
+void scan_printers(gboolean reload)
+{
+ SCAN_START();
+ scan_printers_do();
+ SCAN_END();
+}
+
+void scan_storage(gboolean reload)
+{
+ SCAN_START();
+ g_free(storage_list);
+ storage_list = g_strdup("");
+
+ __scan_ide_devices();
+ __scan_scsi_devices();
+ SCAN_END();
+}
+
+void scan_input(gboolean reload)
+{
+ SCAN_START();
+ __scan_input_devices();
+ SCAN_END();
+}
+
+void scan_usb(gboolean reload)
+{
+ SCAN_START();
+ __scan_usb();
+ SCAN_END();
+}
+
+gchar *callback_processors()
+{
+ return processor_get_info(processors);
+}
+
+#if defined(ARCH_x86) || defined(ARCH_x86_64)
+gchar *callback_dmi()
+{
+ return g_strdup(dmi_info);
+}
+
+gchar *callback_spd()
+{
+ return g_strdup(spd_info);
+}
+#endif
+
+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);
+}
+
+gchar *callback_battery()
+{
+ return g_strdup_printf("%s\n"
+ "[$ShellParam$]\n"
+ "ReloadInterval=4000\n", battery_list);
+}
+
+gchar *callback_pci()
+{
+ return g_strdup_printf("[PCI Devices]\n"
+ "%s"
+ "[$ShellParam$]\n" "ViewType=1\n", pci_list);
+}
+
+gchar *callback_sensors()
+{
+ return g_strdup_printf("[$ShellParam$]\n"
+ "ReloadInterval=5000\n" "%s", sensors);
+}
+
+gchar *callback_printers()
+{
+ return g_strdup_printf("%s\n"
+ "[$ShellParam$]\n"
+ "ViewType=1\n"
+ "ReloadInterval=5000\n"
+ "%s", printer_list, printer_icons);
+}
+
+gchar *callback_storage()
+{
+ return g_strdup_printf("%s\n"
+ "[$ShellParam$]\n"
+ "ReloadInterval=5000\n"
+ "ViewType=1\n%s", storage_list, storage_icons);
+}
+
+gchar *callback_input()
+{
+ return g_strdup_printf("[Input Devices]\n"
+ "%s"
+ "[$ShellParam$]\n"
+ "ViewType=1\n"
+ "ReloadInterval=5000\n%s", input_list,
+ input_icons);
+}
+
+gchar *callback_usb()
+{
+ return g_strdup_printf("%s"
+ "[$ShellParam$]\n"
+ "ViewType=1\n"
+ "ReloadInterval=5000\n", usb_list);
+}
+
+ModuleEntry *hi_module_get_entries(void)
+{
+ return entries;
+}
+
+gchar *hi_module_get_name(void)
+{
+ return g_strdup(_("Devices"));
+}
+
+guchar hi_module_get_weight(void)
+{
+ return 85;
+}
+
+void hi_module_init(void)
+{
+ if (!g_file_test("/usr/share/misc/pci.ids", G_FILE_TEST_EXISTS)) {
+ static SyncEntry se = {
+ .fancy_name = N_("Update PCI ID listing"),
+ .name = "GetPCIIds",
+ .save_to = "pci.ids",
+ .get_data = NULL
+ };
+
+ sync_manager_add_entry(&se);
+ }
+
+#if defined(ARCH_x86) || defined(ARCH_x86_64)
+ {
+ static SyncEntry se = {
+ .fancy_name = N_("Update CPU feature database"),
+ .name = "RecvCPUFlags",
+ .save_to = "cpuflags.conf",
+ .get_data = NULL
+ };
+
+ sync_manager_add_entry(&se);
+ }
+#endif /* defined(ARCH_x86) */
+
+ init_memory_labels();
+ init_cups();
+ sensors_init();
+}
+
+void hi_module_deinit(void)
+{
+ moreinfo_del_with_prefix("DEV");
+ sensors_shutdown();
+ g_hash_table_destroy(memlabels);
+ g_module_close(cups);
+}
+
+ModuleAbout *hi_module_get_about(void)
+{
+ static ModuleAbout ma[] = {
+ {
+ .author = "Leandro A. F. Pereira",
+ .description = N_("Gathers information about hardware devices"),
+ .version = VERSION,
+ .license = "GNU GPL version 2"}
+ };
+
+ return ma;
+}
+
+gchar **hi_module_get_dependencies(void)
+{
+ static gchar *deps[] = { "computer.so", NULL };
+
+ return deps;
+}
+
+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 NULL;
+}