aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorBurt P <pburt0@gmail.com>2019-07-21 23:22:51 -0500
committerLeandro A. F. Pereira <leandro@hardinfo.org>2019-08-14 20:04:11 -0700
commit1e777159dcbeac96976b3980a1ab72234f6dede9 (patch)
treebbe07a9235c93eb48ae41fa42ba2e96aea5b1b09 /modules
parent703cd4ff5b504fd97b8f5b0173bcf8f52b08a70a (diff)
Devices/Firmware
As requested in: https://github.com/lpereira/hardinfo/issues/420 firmware: translatable labels, parse flags, link vendors firmware: attempt using struct Info, issues exist firmware: add flag definitions firmware: remove <-... from guid when run with sudo firmware: map lvfs icons to hardinfo pixmaps firmware: cleanup, add hinote when not available. Signed-off-by: Burt P <pburt0@gmail.com>
Diffstat (limited to 'modules')
-rw-r--r--modules/devices.c29
-rw-r--r--modules/devices/firmware.c260
2 files changed, 289 insertions, 0 deletions
diff --git a/modules/devices.c b/modules/devices.c
index f4a716a1..02597e65 100644
--- a/modules/devices.c
+++ b/modules/devices.c
@@ -51,6 +51,7 @@ gchar *callback_input();
gchar *callback_usb();
gchar *callback_dmi();
gchar *callback_dmi_mem();
+gchar *callback_firmware();
gchar *callback_dtree();
gchar *callback_device_resources();
@@ -65,6 +66,7 @@ void scan_input(gboolean reload);
void scan_usb(gboolean reload);
void scan_dmi(gboolean reload);
void scan_dmi_mem(gboolean reload);
+void scan_firmware(gboolean reload);
void scan_dtree(gboolean reload);
void scan_device_resources(gboolean reload);
@@ -81,6 +83,7 @@ enum {
ENTRY_DMI_MEM,
ENTRY_PCI,
ENTRY_USB,
+ ENTRY_FW,
ENTRY_PRINTERS,
ENTRY_BATTERY,
ENTRY_SENSORS,
@@ -94,6 +97,7 @@ static ModuleEntry entries[] = {
[ENTRY_GPU] = {N_("Graphics Processors"), "devices.png", callback_gpu, scan_gpu, 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_FW] = {N_("Firmware"), "processor.png", callback_firmware, scan_firmware, 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},
@@ -125,6 +129,11 @@ gchar *memory_devices_get_info();
gboolean memory_devices_hinote(const char **msg);
gchar *memory_devices_info = NULL;
+/* in firmware.c */
+gchar *firmware_get_info();
+gboolean firmware_hinote(const char **msg);
+gchar *firmware_info = NULL;
+
#include <vendor.h>
extern gchar *gpu_summary;
@@ -542,6 +551,15 @@ void scan_dmi_mem(gboolean reload)
SCAN_END();
}
+void scan_firmware(gboolean reload)
+{
+ SCAN_START();
+ if (firmware_info)
+ g_free(firmware_info);
+ firmware_info = firmware_get_info();
+ SCAN_END();
+}
+
void scan_dtree(gboolean reload)
{
SCAN_START();
@@ -638,6 +656,11 @@ gchar *callback_dmi_mem()
return g_strdup(memory_devices_info);
}
+gchar *callback_firmware()
+{
+ return g_strdup(firmware_info);
+}
+
gchar *callback_dtree()
{
return g_strdup_printf("%s"
@@ -811,5 +834,11 @@ const gchar *hi_note_func(gint entry)
return msg;
}
}
+ else if (entry == ENTRY_FW) {
+ const char *msg;
+ if (firmware_hinote(&msg)) {
+ return msg;
+ }
+ }
return NULL;
}
diff --git a/modules/devices/firmware.c b/modules/devices/firmware.c
new file mode 100644
index 00000000..e5f11391
--- /dev/null
+++ b/modules/devices/firmware.c
@@ -0,0 +1,260 @@
+/*
+ * HardInfo - Displays System Information
+ * Copyright (C) 2003-2019 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2019 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
+ */
+
+/* TODO Consider: https://fwupd.org/lvfs/docs/users -> "Using the D-Bus API" */
+
+/* Example `fwupdmgr get-devices`:
+Unifying Receiver
+ DeviceId: ecd8ed6144290e36b8d2587116f9d3543d3c69b7
+ Guid: 9d131a0c-a606-580f-8eda-80587250b8d6
+ Guid: 279ed287-3607-549e-bacc-f873bb9838c4
+ Guid: 21e75d9a-5ce6-5da2-b7ab-910c7f3f6836
+ Summary: A miniaturised USB wireless receiver
+ Plugin: unifying
+ Flags: updatable|supported|registered
+ Vendor: Logitech
+ VendorId: USB:0x046D
+ Version: RQR12.09_B0030
+ VersionBootloader: BOT01.04_B0016
+ Icon: preferences-desktop-keyboard
+ InstallDuration: 7
+ Created: 2019-07-22
+*/
+/* sudo example:
+Unifying Receiver
+ DeviceId: ecd8ed6144290e36b8d2587116f9d3543d3c69b7
+ Guid: 9d131a0c-a606-580f-8eda-80587250b8d6
+ Guid: 279ed287-3607-549e-bacc-f873bb9838c4 <- HIDRAW\VEN_046D&DEV_C52B
+ Guid: 21e75d9a-5ce6-5da2-b7ab-910c7f3f6836 <- HIDRAW\VEN_046D
+ Summary: A miniaturised USB wireless receiver
+ Plugin: unifying
+ Flags: updatable|supported|registered
+ Vendor: Logitech
+ VendorId: USB:0x046D
+ Version: RQR12.09_B0030
+ VersionBootloader: BOT01.04_B0016
+ Icon: preferences-desktop-keyboard
+ InstallDuration: 7
+ Created: 2019-07-26
+*/
+
+#include "hardinfo.h"
+#include "devices.h"
+#include <inttypes.h>
+#include "util_sysobj.h" /* for SEQ() and appf() */
+
+#define fw_msg(msg, ...) fprintf (stderr, "[%s] " msg "\n", __FUNCTION__, ##__VA_ARGS__) /**/
+
+gboolean fail_no_fwupdmgr = TRUE;
+
+const char *find_flag_definition(const char *flag) {
+ /* https://github.com/hughsie/fwupd/blob/master/libfwupd/fwupd-enums.{h,c} */
+ static const struct { char *flag, *def; } flag_defs[] = {
+ { "internal", N_("Device cannot be removed easily") },
+ { "updatable", N_("Device is updatable in this or any other mode") },
+ { "only-offline", N_("Update can only be done from offline mode") },
+ { "require-ac", N_("Requires AC power") },
+ { "locked", N_("Is locked and can be unlocked") },
+ { "supported", N_("Is found in current metadata") },
+ { "needs-bootloader", N_("Requires a bootloader mode to be manually enabled by the user") },
+ { "registered", N_("Has been registered with other plugins") },
+ { "needs-reboot", N_("Requires a reboot to apply firmware or to reload hardware") },
+ { "needs-shutdown", N_("Requires system shutdown to apply firmware") },
+ { "reported", N_("Has been reported to a metadata server") },
+ { "notified", N_("User has been notified") },
+ { "use-runtime-version", N_("Always use the runtime version rather than the bootloader") },
+ { "install-parent-first", N_("Install composite firmware on the parent before the child") },
+ { "is-bootloader", N_("Is currently in bootloader mode") },
+ { "wait-for-replug", N_("The hardware is waiting to be replugged") },
+ { "ignore-validation", N_("Ignore validation safety checks when flashing this device") },
+ { "another-write-required", N_("Requires the update to be retried with a new plugin") },
+ { "no-auto-instance-ids", N_("Do not add instance IDs from the device baseclass") },
+ { "needs-activation", N_("Device update needs to be separately activated") },
+ { "ensure-semver", N_("Ensure the version is a valid semantic version, e.g. numbers separated with dots") },
+ { "trusted", N_("Extra metadata can be exposed about this device") },
+ { NULL }
+ };
+ int i;
+ for (i = 0; flag_defs[i].flag; i++) {
+ if (SEQ(flag, flag_defs[i].flag))
+ return flag_defs[i].def;
+ }
+ return NULL;
+}
+
+const char *find_translation(const char *str) {
+ /* TODO: https://github.com/hughsie/fwupd/blob/master/src/README.md */
+ static const char *translatable[] = {
+ N_("DeviceId"), N_("Guid"), N_("Summary"), N_("Plugin"), N_("Flags"),
+ N_("Vendor"), N_("VendorId"), N_("Version"), N_("VersionBootloader"),
+ N_("Icon"), N_("InstallDuration"), N_("Created"),
+ NULL
+ };
+ int i;
+ if (!str) return NULL;
+ for (i = 0; translatable[i]; i++) {
+ if (SEQ(str, translatable[i]))
+ return _(translatable[i]);
+ }
+ return str;
+};
+
+/* map lvfs icon names to hardinfo icon names */
+const char *find_icon(const char *lvfs_name) {
+ /* icon names found by looking for fu_device_add_icon ()
+ * in the fwupd source. */
+ static const
+ struct { char *lvfs, *hi; } imap[] = {
+ { "applications-internet", "dns.png" },
+ { "audio-card", "audio.png" },
+ { "computer", "computer.png" },
+ { "drive-harddisk", "hdd.png" },
+ { "input-gaming", "joystick.png" },
+ { "input-tablet", NULL },
+ { "network-modem", "wireless.png" },
+ { "preferences-desktop-keyboard", "keyboard.png" },
+ { "thunderbolt", NULL },
+ { "touchpad-disabled", NULL },
+ /* default */
+ { NULL, "memory.png" } /* a device with firmware maybe */
+ };
+ unsigned int i = 0;
+ for(; imap[i].lvfs; i++) {
+ if (SEQ(imap[i].lvfs, lvfs_name) && imap[i].hi)
+ return imap[i].hi;
+ }
+ return imap[i].hi;
+}
+
+gchar *fwupdmgr_get_devices_info() {
+ gboolean spawned;
+ gchar *out, *err, *p, *next_nl, *col;
+ gint exit_status;
+
+ struct Info *info = info_new();
+
+ struct InfoGroup *this_group = NULL;
+ gboolean has_vendor_field = FALSE;
+ const Vendor *gv = NULL;
+
+ fail_no_fwupdmgr = FALSE;
+ spawned = g_spawn_command_line_sync("fwupdmgr get-devices",
+ &out, &err, &exit_status, NULL);
+ if (spawned) {
+ p = out;
+ while(next_nl = strchr(p, '\n')) {
+ *next_nl = 0;
+ if (!isspace(*p) && *p != 0) {
+ if (gv && !has_vendor_field) {
+ gchar *vstr = vendor_get_link_from_vendor(gv);
+ info_group_add_field(this_group,
+ info_field(_("Vendor"), vstr, .free_value_on_flatten = TRUE) );
+ }
+ g_strstrip(p);
+ this_group = info_add_group(info, g_strdup(p), info_field_last());
+ this_group->sort = INFO_GROUP_SORT_NAME_DESCENDING;
+ gv = vendor_match(p, NULL);
+ has_vendor_field = FALSE;
+ } else {
+ if (col = strchr(p, ':')) {
+ *col = 0;
+ g_strstrip(p); // name
+ g_strstrip(col+1); // value
+ if (SEQ(p, "Icon")) {
+ info_group_add_field(this_group,
+ info_field(find_translation(p), g_strdup(col+1),
+ .free_value_on_flatten = TRUE, .icon = g_strdup(find_icon(col+1)) ) );
+ } else if (SEQ(p, "Vendor")) {
+ has_vendor_field = TRUE;
+ const Vendor* v = vendor_match(col+1, NULL);
+ if (v) {
+ gchar *vstr = vendor_get_link_from_vendor(v);
+ info_group_add_field(this_group,
+ info_field(_("Vendor"), vstr,
+ .free_value_on_flatten = TRUE) );
+ } else {
+ info_group_add_field(this_group,
+ info_field(find_translation(p), g_strdup(col+1),
+ .free_value_on_flatten = TRUE) );
+ }
+ } else if (SEQ(p, "Guid")) {
+ gchar *ar = NULL;
+ if (ar = strstr(col+1, " <-"))
+ *ar = 0;
+ info_group_add_field(this_group,
+ info_field(find_translation(p), g_strdup(col+1),
+ .free_value_on_flatten = TRUE) );
+ } else if (SEQ(p, "Flags")) {
+ gchar **flags = g_strsplit(col+1, "|", 0);
+ gchar *flag_list = g_strdup("");
+ int f = 0;
+ for(; flags[f]; f++) {
+ const char *lf = find_flag_definition(flags[f]);
+ flag_list = appfnl(flag_list, "[%s] %s", flags[f], lf ? lf : "");
+ }
+ info_group_add_field(this_group,
+ info_field(find_translation(p), flag_list,
+ .free_value_on_flatten = TRUE) );
+ } else
+ info_group_add_field(this_group,
+ info_field(find_translation(p), g_strdup(col+1),
+ .free_value_on_flatten = TRUE) );
+ }
+ }
+ p = next_nl + 1;
+ }
+
+ if (gv && !has_vendor_field) {
+ gchar *vstr = vendor_get_link_from_vendor(gv);
+ info_group_add_field(this_group,
+ info_field(_("Vendor"), vstr, .free_value_on_flatten = TRUE) );
+ }
+
+ g_free(out);
+ g_free(err);
+ } else {
+ fail_no_fwupdmgr = TRUE;
+ }
+
+ gchar *ret = NULL;
+ if (info->groups->len) {
+ info_set_view_type(info, SHELL_VIEW_DETAIL);
+ //fw_msg("flatten...");
+ ret = info_flatten(info);
+ //fw_msg("ret: %s", ret);
+ } else {
+ ret = g_strdup_printf("[%s]\n%s=%s\n" "[$ShellParam$]\nViewType=0\n",
+ _("Firmware List"),
+ _("Result"), _("(Not available)") );
+ }
+ return ret;
+}
+
+gchar *firmware_get_info() {
+ return fwupdmgr_get_devices_info();
+}
+
+gboolean firmware_hinote(const char **msg) {
+ if (fail_no_fwupdmgr) {
+ *msg = g_strdup(
+ _("Requires the <i><b>fwupdmgr</b></i> utility."));
+ return TRUE;
+ }
+ return FALSE;
+}