diff options
Diffstat (limited to 'modules/devices.c')
-rw-r--r-- | modules/devices.c | 613 |
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; +} |