[gnome-software/wip/hughsie/fwupd: 14/21] Support getting firmware updates from fwupd



commit fb84f2818500d976902d246a24d1915125abe88c
Author: Richard Hughes <richard hughsie com>
Date:   Thu Mar 5 14:57:47 2015 +0000

    Support getting firmware updates from fwupd

 src/gs-update-list.c          |    9 +-
 src/plugins/Makefile.am       |    6 +
 src/plugins/gs-plugin-fwupd.c |  249 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 262 insertions(+), 2 deletions(-)
---
diff --git a/src/gs-update-list.c b/src/gs-update-list.c
index 733ba78..ba05632 100644
--- a/src/gs-update-list.c
+++ b/src/gs-update-list.c
@@ -65,6 +65,8 @@ is_addon_id_kind (GsApp *app)
                return FALSE;
        if (id_kind == AS_ID_KIND_WEB_APP)
                return FALSE;
+       if (id_kind == AS_ID_KIND_FIRMWARE)
+               return FALSE;
        return TRUE;
 }
 
@@ -117,12 +119,15 @@ get_app_sort_key (GsApp *app)
 
        /* sort desktop files, then addons */
        switch (gs_app_get_id_kind (app)) {
-       case AS_ID_KIND_DESKTOP:
+       case AS_ID_KIND_FIRMWARE:
                g_string_append (key, "1:");
                break;
-       default:
+       case AS_ID_KIND_DESKTOP:
                g_string_append (key, "2:");
                break;
+       default:
+               g_string_append (key, "3:");
+               break;
        }
 
        /* sort by install date */
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index de60263..7608898 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -38,6 +38,7 @@ plugin_LTLIBRARIES =                                  \
        libgs_plugin_epiphany.la                        \
        libgs_plugin_icons.la                           \
        libgs_plugin_systemd-updates.la                 \
+       libgs_plugin_fwupd.la                           \
        libgs_plugin_packagekit-refine.la               \
        libgs_plugin_packagekit-refresh.la              \
        libgs_plugin_packagekit-offline.la              \
@@ -148,6 +149,11 @@ libgs_plugin_systemd_updates_la_LIBADD = $(GS_PLUGIN_LIBS) $(PACKAGEKIT_LIBS)
 libgs_plugin_systemd_updates_la_LDFLAGS = -module -avoid-version
 libgs_plugin_systemd_updates_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
 
+libgs_plugin_fwupd_la_SOURCES = gs-plugin-fwupd.c
+libgs_plugin_fwupd_la_LIBADD = $(GS_PLUGIN_LIBS) $(PACKAGEKIT_LIBS)
+libgs_plugin_fwupd_la_LDFLAGS = -module -avoid-version
+libgs_plugin_fwupd_la_CFLAGS = $(GS_PLUGIN_CFLAGS) $(WARN_CFLAGS)
+
 libgs_plugin_packagekit_history_la_SOURCES = gs-plugin-packagekit-history.c
 libgs_plugin_packagekit_history_la_LIBADD = $(GS_PLUGIN_LIBS)
 libgs_plugin_packagekit_history_la_LDFLAGS = -module -avoid-version
diff --git a/src/plugins/gs-plugin-fwupd.c b/src/plugins/gs-plugin-fwupd.c
new file mode 100644
index 0000000..00a6cd7
--- /dev/null
+++ b/src/plugins/gs-plugin-fwupd.c
@@ -0,0 +1,249 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2013 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+#include <gio/gio.h>
+
+#include "gs-cleanup.h"
+
+#include <appstream-glib.h>
+#include <gs-plugin.h>
+
+#define FWUPD_DBUS_PATH                        "/"
+#define FWUPD_DBUS_SERVICE             "org.freedesktop.fwupd"
+#define FWUPD_DBUS_INTERFACE           "org.freedesktop.fwupd"
+
+struct GsPluginPrivate {
+       gsize                    done_init;
+       GDBusProxy              *proxy;
+       AsStore                 *store;
+};
+
+/**
+ * gs_plugin_get_name:
+ */
+const gchar *
+gs_plugin_get_name (void)
+{
+       return "fwupd";
+}
+
+/**
+ * gs_plugin_initialize:
+ */
+void
+gs_plugin_initialize (GsPlugin *plugin)
+{
+       plugin->priv = GS_PLUGIN_GET_PRIVATE (GsPluginPrivate);
+       plugin->priv->store = as_store_new ();
+}
+
+/**
+ * gs_plugin_destroy:
+ */
+void
+gs_plugin_destroy (GsPlugin *plugin)
+{
+       g_object_unref (plugin->priv->store);
+       if (plugin->priv->proxy != NULL)
+               g_object_unref (plugin->priv->proxy);
+}
+
+/**
+ * gs_plugin_startup:
+ */
+static gboolean
+gs_plugin_startup (GsPlugin *plugin, GCancellable *cancellable, GError **error)
+{
+       _cleanup_object_unref_ GDBusConnection *conn = NULL;
+       conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
+       if (conn == NULL)
+               return FALSE;
+       plugin->priv->proxy = g_dbus_proxy_new_sync (conn,
+                                                    G_DBUS_PROXY_FLAGS_NONE,
+                                                    NULL,
+                                                    FWUPD_DBUS_SERVICE,
+                                                    FWUPD_DBUS_PATH,
+                                                    FWUPD_DBUS_INTERFACE,
+                                                    NULL,
+                                                    error);
+       if (plugin->priv->proxy == NULL)
+               return FALSE;
+
+       /* this is hugely wasteful */
+       if (!as_store_load (plugin->priv->store,
+                           AS_STORE_LOAD_FLAG_APP_INFO_SYSTEM,
+                           cancellable, error))
+               return FALSE;
+
+       return TRUE;
+}
+
+/**
+ * gs_plugin_fwupd_add_device:
+ */
+static gboolean
+gs_plugin_fwupd_add_device (GsPlugin *plugin,
+                           const gchar *guid,
+                           const gchar *version,
+                           GList **list,
+                           GError **error)
+{
+       AsApp *item;
+       AsRelease *rel;
+       GPtrArray *releases;
+       const gchar *tmp;
+       guint i;
+       _cleanup_free_ gchar *update_version = NULL;
+       _cleanup_object_unref_ GsApp *app = NULL;
+       _cleanup_string_free_ GString *update_desc = NULL;
+
+       /* find the device */
+       item = as_store_get_app_by_id (plugin->priv->store, guid);
+       if (item == NULL) {
+               g_set_error (error,
+                            GS_PLUGIN_ERROR,
+                            GS_PLUGIN_ERROR_FAILED,
+                            "device id %s not found in metadata",
+                            guid);
+               return FALSE;
+       }
+
+       /* are any releases newer than what we have here */
+       g_debug ("device id %s found in metadata", guid);
+       update_desc = g_string_new ("");
+       releases = as_app_get_releases (item);
+       for (i = 0; i < releases->len; i++) {
+               _cleanup_free_ gchar *md = NULL;
+
+               /* check if actually newer */
+               rel = g_ptr_array_index (releases, i);
+               if (as_utils_vercmp (as_release_get_version (rel), version) <= 0)
+                       continue;
+
+               /* get the update text, if it exists */
+               if (update_version == NULL)
+                       update_version = g_strdup (as_release_get_version (rel));
+               tmp = as_release_get_description (rel, NULL);
+               if (tmp == NULL)
+                       continue;
+               md = as_markup_convert (tmp, -1,
+                                       AS_MARKUP_CONVERT_FORMAT_MARKDOWN,
+                                       NULL);
+               if (md != NULL)
+                       g_string_append_printf (update_desc, "%s\n", md);
+       }
+
+       /* no updates for this hardware */
+       if (update_version == NULL) {
+               g_set_error_literal (error,
+                                    GS_PLUGIN_ERROR,
+                                    GS_PLUGIN_ERROR_FAILED,
+                                    "no updates available");
+               return FALSE;
+       }
+
+       /* remove trailing newline */
+       if (update_desc->len > 0)
+               g_string_truncate (update_desc, update_desc->len - 1);
+
+       /* actually addd the application */
+       app = gs_app_new (guid);
+       gs_app_set_management_plugin (app, "fwupd");
+       gs_app_set_state (app, AS_APP_STATE_UPDATABLE);
+       gs_app_set_update_details (app, update_desc->str);
+       gs_app_set_update_version (app, update_version);
+//     gs_app_add_source_id (app, package_ids[i]);
+       gs_app_add_source (app, as_app_get_name (item, NULL));
+       gs_app_set_kind (app, GS_APP_KIND_SYSTEM);
+       gs_plugin_add_app (list, app);
+       return TRUE;
+}
+
+/**
+ * gs_plugin_add_updates:
+ */
+gboolean
+gs_plugin_add_updates (GsPlugin *plugin,
+                      GList **list,
+                      GCancellable *cancellable,
+                      GError **error)
+{
+       const gchar *id;
+       gboolean ret;
+       GVariantIter *iter_device;
+       _cleanup_variant_iter_free_ GVariantIter *iter = NULL;
+       _cleanup_variant_unref_ GVariant *val = NULL;
+
+       /* watch the file in case it comes or goes */
+       if (g_once_init_enter (&plugin->priv->done_init)) {
+               ret = gs_plugin_startup (plugin, cancellable, error);
+               g_once_init_leave (&plugin->priv->done_init, TRUE);
+               if (!ret)
+                       return FALSE;
+       }
+
+       val = g_dbus_proxy_call_sync (plugin->priv->proxy,
+                                     "GetDevices",
+                                     NULL,
+                                     G_DBUS_CALL_FLAGS_NONE,
+                                     -1,
+                                     NULL,
+                                     error);
+       if (val == NULL)
+               return FALSE;
+
+       /* parse */
+       g_variant_get (val, "(a{sa{sv}})", &iter);
+       while (g_variant_iter_next (iter, "{&sa{sv}}", &id, &iter_device)) {
+               GVariant *variant;
+               const gchar *key;
+               _cleanup_free_ gchar *guid = NULL;
+               _cleanup_free_ gchar *version = NULL;
+
+               while (g_variant_iter_next (iter_device, "{&sv}", &key, &variant)) {
+                       g_debug ("%s has key %s", id, key);
+                       if (g_strcmp0 (key, "Guid") == 0) {
+                               guid = g_variant_dup_string (variant, NULL);
+                       } else if (g_strcmp0 (key, "Version") == 0) {
+                               version = g_variant_dup_string (variant, NULL);
+                       }
+                       g_variant_unref (variant);
+               }
+
+               /* we got all we needed */
+               if (guid != NULL && version != NULL) {
+                       _cleanup_error_free_ GError *error_local = NULL;
+                       if (!gs_plugin_fwupd_add_device (plugin,
+                                                        guid,
+                                                        version,
+                                                        list,
+                                                        &error_local)) {
+                               g_debug ("cannot add device %s: %s",
+                                        id, error_local->message);
+                       }
+               }
+
+               g_variant_iter_free (iter_device);
+       }
+
+       return TRUE;
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]