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.
+
+
+
+
+
+