diff options
author | Ondrej Čerman <ondrej.cerman@gmail.com> | 2020-01-04 21:18:52 +0100 |
---|---|---|
committer | Leandro A. F. Pereira <leandro@hardinfo.org> | 2020-01-05 10:00:56 -0800 |
commit | 43498b2a714b7fabd61c9a90ff7fabb910165893 (patch) | |
tree | 7fa192abc0a06c5551fcad65f083098e902b6206 /modules/devices/firmware.c | |
parent | b6f45ad47930a2d40f7d0c85cad97912f78d678f (diff) |
firmware: switched to D-Bus
Diffstat (limited to 'modules/devices/firmware.c')
-rw-r--r-- | modules/devices/firmware.c | 275 |
1 files changed, 136 insertions, 139 deletions
diff --git a/modules/devices/firmware.c b/modules/devices/firmware.c index f3191503..6c283d6e 100644 --- a/modules/devices/firmware.c +++ b/modules/devices/firmware.c @@ -2,6 +2,7 @@ * HardInfo - Displays System Information * Copyright (C) 2003-2019 Leandro A. F. Pereira <leandro@hardinfo.org> * Copyright (C) 2019 Burt P. <pburt0@gmail.com> + * Copyright (C) 2020 Ondrej Čerman * * 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 @@ -17,85 +18,54 @@ * 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 <gio/gio.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; +#define FWUPT_INTERFACE "org.freedesktop.fwupd" -const char *find_flag_definition(const char *flag) { +gboolean fail_no_fwupd = TRUE; + +char *decode_flags(guint64 flags) { /* 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 } + static const struct { guint64 b; char *flag, *def; } flag_defs[] = { + { (1u << 0), "internal", N_("Device cannot be removed easily") }, + { (1u << 1), "updatable", N_("Device is updatable in this or any other mode") }, + { (1u << 2), "only-offline", N_("Update can only be done from offline mode") }, + { (1u << 3), "require-ac", N_("Requires AC power") }, + { (1u << 4), "locked", N_("Is locked and can be unlocked") }, + { (1u << 5), "supported", N_("Is found in current metadata") }, + { (1u << 6), "needs-bootloader", N_("Requires a bootloader mode to be manually enabled by the user") }, + { (1u << 7), "registered", N_("Has been registered with other plugins") }, + { (1u << 8), "needs-reboot", N_("Requires a reboot to apply firmware or to reload hardware") }, + { (1u << 17), "needs-shutdown", N_("Requires system shutdown to apply firmware") }, + { (1u << 9), "reported", N_("Has been reported to a metadata server") }, + { (1u << 10), "notified", N_("User has been notified") }, + { (1u << 11), "use-runtime-version", N_("Always use the runtime version rather than the bootloader") }, + { (1u << 12), "install-parent-first", N_("Install composite firmware on the parent before the child") }, + { (1u << 13), "is-bootloader", N_("Is currently in bootloader mode") }, + { (1u << 14), "wait-for-replug", N_("The hardware is waiting to be replugged") }, + { (1u << 15), "ignore-validation", N_("Ignore validation safety checks when flashing this device") }, + { (1u << 18), "another-write-required", N_("Requires the update to be retried with a new plugin") }, + { (1u << 19), "no-auto-instance-ids", N_("Do not add instance IDs from the device baseclass") }, + { (1u << 20), "needs-activation", N_("Device update needs to be separately activated") }, + { (1u << 21), "ensure-semver", N_("Ensure the version is a valid semantic version, e.g. numbers separated with dots") }, + { (1u << 16), "trusted", N_("Extra metadata can be exposed about this device") }, + { 0, NULL } }; + + gchar *flag_list = g_strdup(""); + int i; for (i = 0; flag_defs[i].flag; i++) { - if (SEQ(flag, flag_defs[i].flag)) - return flag_defs[i].def; + if (flags & flag_defs[i].b) + flag_list = appfnl(flag_list, "[%s] %s", flag_defs[i].flag, flag_defs[i].def); } - return NULL; + return flag_list; } const char *find_translation(const char *str) { @@ -143,99 +113,126 @@ const char *find_icon(const char *lvfs_name) { } 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; + gboolean updatable = FALSE; const Vendor *gv = NULL; int gc = 0; - 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) { - info_group_add_field(this_group, - info_field(_("Vendor"), gv->name, + GDBusConnection *conn; + GDBusProxy *proxy; + GVariant *devices, *value; + GVariantIter *deviter, *dictiter, *iter; + const gchar *key, *tmpstr; + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL); + if (!conn) + return g_strdup(""); + + proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL, + FWUPT_INTERFACE, "/", FWUPT_INTERFACE, + NULL, NULL); + if (!proxy) { + g_object_unref(conn); + return g_strdup(""); + } + + fail_no_fwupd = FALSE; + devices = g_dbus_proxy_call_sync(proxy, "GetDevices", NULL, + G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); + + if (devices) { + g_variant_get(devices, "(aa{sv})", &deviter); + while(g_variant_iter_loop(deviter, "a{sv}", &dictiter)){ + + this_group = info_add_group(info, _("Unknown"), info_field_last()); + this_group->sort = INFO_GROUP_SORT_NAME_DESCENDING; + has_vendor_field = FALSE; + updatable = FALSE; + gv = NULL; + + while (g_variant_iter_loop(dictiter, "{&sv}", &key, &value)) { + if (SEQ(key, "Name")) { + tmpstr = g_variant_get_string(value, NULL); + this_group->name = hardinfo_clean_grpname(tmpstr, 0); + gv = vendor_match(tmpstr, NULL); + } else if (SEQ(key, "Vendor")) { + has_vendor_field = TRUE; + tmpstr = g_variant_get_string(value, NULL); + + const Vendor* v = vendor_match(tmpstr, NULL); + if (v) { + info_group_add_field(this_group, + info_field(_("Vendor"), v->name, .value_has_vendor = TRUE, .free_value_on_flatten = FALSE) ); - } - 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")) { + } else { 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) { - info_group_add_field(this_group, - info_field(_("Vendor"), v->name, - .value_has_vendor = TRUE, - .free_value_on_flatten = FALSE) ); - } 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_field(_("Vendor"), g_strdup(tmpstr), + .free_value_on_flatten = TRUE) ); + } + } else if (SEQ(key, "Icon")) { + g_variant_get(value, "as", &iter); + while (g_variant_iter_loop(iter, "s", &tmpstr)) { info_group_add_field(this_group, - info_field(find_translation(p), g_strdup(col+1), + info_field(_("Icon"), g_strdup(tmpstr), + .free_value_on_flatten = TRUE, + .icon = g_strdup(find_icon(tmpstr)) ) ); + } + } else if (SEQ(key, "Guid")) { + g_variant_get(value, "as", &iter); + while (g_variant_iter_loop(iter, "s", &tmpstr)) { + info_group_add_field(this_group, + info_field(_("Guid"), g_strdup(tmpstr), .tag = g_strdup_printf("guid%d", gc++), .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 : ""); - } + } + g_variant_iter_free(iter); + } else if (SEQ(key, "Created")) { + guint64 created = g_variant_get_uint64(value); + GDateTime *dt = g_date_time_new_from_unix_local(created); + if (dt) { info_group_add_field(this_group, - info_field(find_translation(p), flag_list, + info_field(_("Created"), g_date_time_format(dt, "%x"), + .free_value_on_flatten = TRUE) ); + g_date_time_unref(dt); + } + } else if (SEQ(key, "Flags")) { + guint64 flags = g_variant_get_uint64(value); + updatable = (gboolean)(flags & (1u << 1)); + info_group_add_field(this_group, + info_field(_("Flags"), decode_flags(flags), .free_value_on_flatten = TRUE) ); - } else + } else { + if (g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { info_group_add_field(this_group, - info_field(find_translation(p), g_strdup(col+1), + info_field(find_translation(key), + g_variant_dup_string(value, NULL), .free_value_on_flatten = TRUE) ); + } } } - p = next_nl + 1; - } - if (gv && !has_vendor_field) { - info_group_add_field(this_group, - info_field(_("Vendor"), gv->name, - .value_has_vendor = TRUE, - .free_value_on_flatten = FALSE) ); - } + if (gv && !has_vendor_field) { + info_group_add_field(this_group, + info_field(_("Vendor"), gv->name, + .value_has_vendor = TRUE, + .free_value_on_flatten = FALSE) ); + } - g_free(out); - g_free(err); - } else { - fail_no_fwupdmgr = TRUE; + // hide devices that are not updatable + if (!updatable) { + info_remove_group(info, info->groups->len - 1); + } + } + g_variant_iter_free(deviter); + g_variant_unref(devices); } + g_object_unref(proxy); + g_object_unref(conn); + gchar *ret = NULL; if (info->groups->len) { info_set_view_type(info, SHELL_VIEW_DETAIL); @@ -255,9 +252,9 @@ gchar *firmware_get_info() { } gboolean firmware_hinote(const char **msg) { - if (fail_no_fwupdmgr) { + if (fail_no_fwupd) { *msg = g_strdup( - _("Requires the <i><b>fwupdmgr</b></i> utility.")); + _("Requires the <i><b>fwupd</b></i> daemon.")); return TRUE; } return FALSE; |