diff --git a/libfwupd/fwupd-client.c b/libfwupd/fwupd-client.c index 15f0ea141..25cff7c26 100644 --- a/libfwupd/fwupd-client.c +++ b/libfwupd/fwupd-client.c @@ -616,6 +616,51 @@ fwupd_client_get_downgrades (FwupdClient *client, const gchar *device_id, return fwupd_client_parse_releases_from_variant (val); } +/** + * fwupd_client_get_upgrades: + * @client: A #FwupdClient + * @device_id: the device ID + * @cancellable: the #GCancellable, or %NULL + * @error: the #GError, or %NULL + * + * Gets all the upgrades for a specific device. + * + * Returns: (element-type FwupdRelease) (transfer container): results + * + * Since: 0.9.8 + **/ +GPtrArray * +fwupd_client_get_upgrades (FwupdClient *client, const gchar *device_id, + GCancellable *cancellable, GError **error) +{ + FwupdClientPrivate *priv = GET_PRIVATE (client); + g_autoptr(GVariant) val = NULL; + + g_return_val_if_fail (FWUPD_IS_CLIENT (client), NULL); + g_return_val_if_fail (device_id != NULL, NULL); + g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + /* connect */ + if (!fwupd_client_connect (client, cancellable, error)) + return NULL; + + /* call into daemon */ + val = g_dbus_proxy_call_sync (priv->proxy, + "GetUpgrades", + g_variant_new ("(s)", device_id), + G_DBUS_CALL_FLAGS_NONE, + -1, + cancellable, + error); + if (val == NULL) { + if (error != NULL) + fwupd_client_fixup_dbus_error (*error); + return NULL; + } + return fwupd_client_parse_releases_from_variant (val); +} + static void fwupd_client_proxy_call_cb (GObject *source, GAsyncResult *res, gpointer user_data) { diff --git a/libfwupd/fwupd-client.h b/libfwupd/fwupd-client.h index 881452ef2..0a54fc418 100644 --- a/libfwupd/fwupd-client.h +++ b/libfwupd/fwupd-client.h @@ -71,6 +71,10 @@ GPtrArray *fwupd_client_get_downgrades (FwupdClient *client, const gchar *device_id, GCancellable *cancellable, GError **error); +GPtrArray *fwupd_client_get_upgrades (FwupdClient *client, + const gchar *device_id, + GCancellable *cancellable, + GError **error); GPtrArray *fwupd_client_get_details_local (FwupdClient *client, const gchar *filename, GCancellable *cancellable, diff --git a/src/fu-engine.c b/src/fu-engine.c index 849fbcd58..55f42a08c 100644 --- a/src/fu-engine.c +++ b/src/fu-engine.c @@ -2235,6 +2235,7 @@ fu_engine_get_releases (FuEngine *self, const gchar *device_id, GError **error) "No releases for device"); return NULL; } + g_ptr_array_sort (releases, fu_engine_sort_releases_cb); return g_steal_pointer (&releases); } @@ -2331,6 +2332,86 @@ fu_engine_get_downgrades (FuEngine *self, const gchar *device_id, GError **error return g_steal_pointer (&releases); } +/** + * fu_engine_get_upgrades: + * @self: A #FuEngine + * @device_id: A device ID + * @error: A #GError, or %NULL + * + * Gets the upgrades available for a specific device. + * + * Returns: (transfer container) (element-type FwupdResult): results + **/ +GPtrArray * +fu_engine_get_upgrades (FuEngine *self, const gchar *device_id, GError **error) +{ + FuDeviceItem *item; + g_autoptr(GPtrArray) releases = NULL; + g_autoptr(GPtrArray) releases_tmp = NULL; + g_autoptr(GString) error_str = g_string_new (NULL); + + g_return_val_if_fail (FU_IS_ENGINE (self), NULL); + g_return_val_if_fail (device_id != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + /* find the device */ + item = fu_engine_get_item_by_id (self, device_id, error); + if (item == NULL) + return NULL; + + /* get all the releases for the device */ + releases_tmp = fu_engine_get_releases_for_device (self, item->device, error); + if (releases_tmp == NULL) + return NULL; + releases = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + for (guint i = 0; i < releases_tmp->len; i++) { + FwupdRelease *rel_tmp = g_ptr_array_index (releases_tmp, i); + gint vercmp; + + /* only include older firmware */ + vercmp = as_utils_vercmp (fwupd_release_get_version (rel_tmp), + fu_device_get_version (item->device)); + if (vercmp == 0) { + g_string_append_printf (error_str, "%s=same, ", + fwupd_release_get_version (rel_tmp)); + g_debug ("ignoring %s as the same as %s", + fwupd_release_get_version (rel_tmp), + fu_device_get_version (item->device)); + continue; + } + if (vercmp < 0) { + g_string_append_printf (error_str, "%s=older, ", + fwupd_release_get_version (rel_tmp)); + g_debug ("ignoring %s as older than %s", + fwupd_release_get_version (rel_tmp), + fu_device_get_version (item->device)); + continue; + } + g_ptr_array_add (releases, g_object_ref (rel_tmp)); + } + if (error_str->len > 2) + g_string_truncate (error_str, error_str->len - 2); + if (releases->len == 0) { + if (error_str->len > 0) { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_NOTHING_TO_DO, + "No upgrades for device, current is %s: %s", + fu_device_get_version (item->device), + error_str->str); + } else { + g_set_error (error, + FWUPD_ERROR, + FWUPD_ERROR_NOTHING_TO_DO, + "No upgrades for device, current is %s", + fu_device_get_version (item->device)); + } + return NULL; + } + g_ptr_array_sort (releases, fu_engine_sort_releases_cb); + return g_steal_pointer (&releases); +} + /** * fu_engine_clear_results: * @self: A #FuEngine diff --git a/src/fu-engine.h b/src/fu-engine.h index 0d73b4373..471ac8e37 100644 --- a/src/fu-engine.h +++ b/src/fu-engine.h @@ -63,6 +63,9 @@ GPtrArray *fu_engine_get_releases (FuEngine *self, GPtrArray *fu_engine_get_downgrades (FuEngine *self, const gchar *device_id, GError **error); +GPtrArray *fu_engine_get_upgrades (FuEngine *self, + const gchar *device_id, + GError **error); FwupdResult *fu_engine_get_results (FuEngine *self, const gchar *device_id, GError **error); diff --git a/src/fu-main.c b/src/fu-main.c index 6bb348369..2437416b0 100644 --- a/src/fu-main.c +++ b/src/fu-main.c @@ -469,6 +469,20 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender, g_dbus_method_invocation_return_value (invocation, val); return; } + if (g_strcmp0 (method_name, "GetUpgrades") == 0) { + const gchar *device_id; + g_autoptr(GPtrArray) releases = NULL; + g_variant_get (parameters, "(&s)", &device_id); + g_debug ("Called %s(%s)", method_name, device_id); + releases = fu_engine_get_upgrades (priv->engine, device_id, &error); + if (releases == NULL) { + g_dbus_method_invocation_return_gerror (invocation, error); + return; + } + val = fu_main_release_array_to_variant (releases); + g_dbus_method_invocation_return_value (invocation, val); + return; + } if (g_strcmp0 (method_name, "GetRemotes") == 0) { g_autoptr(GPtrArray) remotes = NULL; g_debug ("Called %s()", method_name); diff --git a/src/org.freedesktop.fwupd.xml b/src/org.freedesktop.fwupd.xml index 7ec9d86e9..0aebfe786 100644 --- a/src/org.freedesktop.fwupd.xml +++ b/src/org.freedesktop.fwupd.xml @@ -140,6 +140,36 @@ + + + + + + Gets a list of all the upgrades possible for a specific device. + + + + + + + + A device ID. + + + + + + + + + An array of releases (with the release number as the key), + with any properties set on each. + + + + + +