Return the device properties when calling GetDevices()

This allows us to discover a version number, and other things.
This commit is contained in:
Richard Hughes 2015-03-02 22:44:48 +00:00
parent 74cc217f9d
commit 1ffde6cd72
8 changed files with 142 additions and 65 deletions

View File

@ -21,6 +21,8 @@ AM_CPPFLAGS = \
bin_PROGRAMS = fwupdmgr
fwupdmgr_SOURCES = \
fu-device.c \
fu-device.h \
fu-util.c
fwupdmgr_LDADD = \

View File

@ -29,4 +29,7 @@
#define FU_ERROR 1
#define FU_ERROR_INTERNAL 0
#define FU_DEVICE_KEY_VERSION "Version"
#define FU_DEVICE_KEY_PROVIDER "Provider"
#endif /* __FU_COMMON_H */

View File

@ -40,6 +40,7 @@ static void fu_device_finalize (GObject *object);
struct _FuDevicePrivate
{
gchar *id;
GHashTable *metadata;
};
enum {
@ -76,6 +77,75 @@ fu_device_set_id (FuDevice *device, const gchar *id)
device->priv->id = g_strdup (id);
}
/**
* fu_device_get_metadata:
**/
const gchar *
fu_device_get_metadata (FuDevice *device, const gchar *key)
{
g_return_val_if_fail (FU_IS_DEVICE (device), NULL);
g_return_val_if_fail (key != NULL, NULL);
return g_hash_table_lookup (device->priv->metadata, key);
}
/**
* fu_device_get_id:
**/
void
fu_device_set_metadata (FuDevice *device, const gchar *key, const gchar *value)
{
g_return_if_fail (FU_IS_DEVICE (device));
g_return_if_fail (key != NULL);
g_return_if_fail (value != NULL);
g_hash_table_insert (device->priv->metadata, g_strdup (key), g_strdup (value));
}
/**
* fu_device_to_variant:
**/
GVariant *
fu_device_to_variant (FuDevice *device)
{
GList *l;
GVariantBuilder builder;
const gchar *key;
const gchar *value;
_cleanup_list_free_ GList *keys = NULL;
/* create an array with all the metadata in */
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
keys = g_hash_table_get_keys (device->priv->metadata);
for (l = keys; l != NULL; l = l->next) {
key = l->data;
value = g_hash_table_lookup (device->priv->metadata, key);
g_variant_builder_add (&builder, "{sv}",
key, g_variant_new_string (value));
}
return g_variant_new ("{sa{sv}}", device->priv->id, &builder);
}
/**
* fu_device_set_metadata_from_iter:
**/
void
fu_device_set_metadata_from_iter (FuDevice *device, GVariantIter *iter)
{
GVariant *variant;
const gchar *key;
const gchar *type;
while (g_variant_iter_next (iter, "{&sv}", &key, &variant)) {
type = g_variant_get_type_string (variant);
if (g_strcmp0 (type, "s") == 0) {
fu_device_set_metadata (device, key,
g_variant_get_string (variant, NULL));
} else {
fu_device_set_metadata (device, key, "???");
}
g_variant_unref (variant);
}
}
/**
* fu_device_get_property:
**/
@ -145,6 +215,8 @@ static void
fu_device_init (FuDevice *device)
{
device->priv = FU_DEVICE_GET_PRIVATE (device);
device->priv->metadata = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
}
/**
@ -157,6 +229,7 @@ fu_device_finalize (GObject *object)
FuDevicePrivate *priv = device->priv;
g_free (priv->id);
g_hash_table_unref (priv->metadata);
G_OBJECT_CLASS (fu_device_parent_class)->finalize (object);
}

View File

@ -53,9 +53,17 @@ GType fu_device_get_type (void);
FuDevice *fu_device_new (void);
/* accessors */
GVariant *fu_device_to_variant (FuDevice *device);
const gchar *fu_device_get_id (FuDevice *device);
void fu_device_set_id (FuDevice *device,
const gchar *id);
const gchar *fu_device_get_metadata (FuDevice *device,
const gchar *key);
void fu_device_set_metadata (FuDevice *device,
const gchar *key,
const gchar *value);
void fu_device_set_metadata_from_iter (FuDevice *device,
GVariantIter *iter);
G_END_DECLS

View File

@ -50,21 +50,23 @@ typedef struct {
} FuDeviceItem;
/**
* fu_main_get_device_list_as_strv:
* fu_device_to_variants:
**/
static gchar **
fu_main_get_device_list_as_strv (FuMainPrivate *priv)
static GVariant *
fu_device_to_variants (FuMainPrivate *priv)
{
gchar **val;
GVariantBuilder builder;
guint i;
FuDevice *dev_tmp;
val = g_new0 (gchar *, priv->devices->len + 1);
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
for (i = 0; i < priv->devices->len; i++) {
dev_tmp = g_ptr_array_index (priv->devices, i);
val[i] = g_strdup (fu_device_get_id (dev_tmp));
GVariant *tmp;
FuDeviceItem *item;
item = g_ptr_array_index (priv->devices, i);
tmp = fu_device_to_variant (item->device);
g_variant_builder_add_value (&builder, tmp);
}
return val;
return g_variant_new ("(a{sa{sv}})", &builder);
}
/**
@ -163,8 +165,9 @@ fu_main_check_authorization_cb (GObject *source, GAsyncResult *res, gpointer use
/* run the correct provider that added this */
if (!fu_provider_update (item->provider,
item->device,
helper->fd,
helper->flags,
helper->fd, &error)) {
&error)) {
g_dbus_method_invocation_return_gerror (helper->invocation,
error);
fu_main_helper_free (helper);
@ -192,8 +195,7 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
if (g_strcmp0 (method_name, "GetDevices") == 0) {
_cleanup_strv_free_ gchar **devices = NULL;
g_debug ("Called %s()", method_name);
devices = fu_main_get_device_list_as_strv (priv);
val = g_variant_new ("(^as)", devices);
val = fu_device_to_variants (priv);
g_dbus_method_invocation_return_value (invocation, val);
return;
}
@ -234,6 +236,7 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
if (g_strcmp0 (prop_key, "offline") == 0 &&
g_variant_get_boolean (prop_value) == TRUE)
flags |= FU_PROVIDER_UPDATE_FLAG_OFFLINE;
g_variant_unref (prop_value);
}
/* get the fd */

View File

@ -31,40 +31,8 @@
static void fu_provider_uefi_finalize (GObject *object);
#define FU_PROVIDER_UEFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FU_TYPE_PROVIDER_UEFI, FuProviderUefiPrivate))
/**
* FuProviderUefiPrivate:
**/
struct _FuProviderUefiPrivate
{
GPtrArray *array_devices;
};
G_DEFINE_TYPE (FuProviderUefi, fu_provider_uefi, FU_TYPE_PROVIDER)
/**
* fu_provider_uefi_get_by_id:
**/
static FuDevice *
fu_provider_uefi_get_by_id (FuProviderUefi *provider_uefi,
const gchar *device_id)
{
FuProviderUefiPrivate *priv = provider_uefi->priv;
FuDevice *device = NULL;
FuDevice *device_tmp;
guint i;
for (i = 0; i < priv->array_devices->len; i++) {
device_tmp = g_ptr_array_index (priv->array_devices, i);
if (g_strcmp0 (fu_device_get_id (device_tmp), device_id) == 0) {
device = g_object_ref (device_tmp);
break;
}
}
return device;
}
/**
* fu_provider_uefi_update:
**/
@ -75,8 +43,6 @@ fu_provider_uefi_update (FuProvider *provider,
FuProviderFlags flags,
GError **error)
{
// FuProviderUefi *provider_uefi = FU_PROVIDER_UEFI (provider);
/* this only makes sense offline */
if ((flags & FU_PROVIDER_UPDATE_FLAG_OFFLINE) == 0) {
g_set_error_literal (error,
@ -97,13 +63,14 @@ fu_provider_uefi_update (FuProvider *provider,
static gboolean
fu_provider_uefi_coldplug (FuProvider *provider, GError **error)
{
// FuProviderUefi *provider_uefi = FU_PROVIDER_UEFI (provider);
_cleanup_object_unref_ FuDevice *dev = NULL;
//FIXME
g_debug ("Adding fake UEFI device");
dev = fu_device_new ();
fu_device_set_id (dev, "UEFI-819b858e-c52c-402f-80e1-5b311b6c1959-dev1");
fu_device_set_metadata (dev, FU_DEVICE_KEY_PROVIDER, "UEFI");
fu_device_set_metadata (dev, FU_DEVICE_KEY_VERSION, "12345");
fu_provider_emit_added (provider, dev);
return TRUE;
}
@ -120,8 +87,6 @@ fu_provider_uefi_class_init (FuProviderUefiClass *klass)
provider_class->coldplug = fu_provider_uefi_coldplug;
provider_class->update = fu_provider_uefi_update;
object_class->finalize = fu_provider_uefi_finalize;
g_type_class_add_private (klass, sizeof (FuProviderUefiPrivate));
}
/**
@ -130,8 +95,6 @@ fu_provider_uefi_class_init (FuProviderUefiClass *klass)
static void
fu_provider_uefi_init (FuProviderUefi *provider_uefi)
{
provider_uefi->priv = FU_PROVIDER_UEFI_GET_PRIVATE (provider_uefi);
provider_uefi->priv->array_devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
}
/**
@ -140,11 +103,6 @@ fu_provider_uefi_init (FuProviderUefi *provider_uefi)
static void
fu_provider_uefi_finalize (GObject *object)
{
FuProviderUefi *provider_uefi = FU_PROVIDER_UEFI (object);
FuProviderUefiPrivate *priv = provider_uefi->priv;
g_ptr_array_unref (priv->array_devices);
G_OBJECT_CLASS (fu_provider_uefi_parent_class)->finalize (object);
}

View File

@ -194,11 +194,14 @@ fu_util_run (FuUtilPrivate *priv, const gchar *command, gchar **values, GError *
static gboolean
fu_util_get_devices (FuUtilPrivate *priv, gchar **values, GError **error)
{
GVariantIter *iter_device;
FuDevice *dev;
gchar *id;
_cleanup_ptrarray_unref_ GPtrArray *devices = NULL;
_cleanup_object_unref_ GDBusConnection *conn = NULL;
_cleanup_object_unref_ GDBusProxy *proxy = NULL;
_cleanup_variant_iter_free_ GVariantIter *iter = NULL;
_cleanup_variant_unref_ GVariant *val = NULL;
const gchar **ids = NULL;
guint i;
conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
if (conn == NULL)
@ -222,12 +225,39 @@ fu_util_get_devices (FuUtilPrivate *priv, gchar **values, GError **error)
error);
if (val == NULL)
return FALSE;
g_variant_get (val, "(^a&s)", &ids);
g_assert (ids != NULL);
if (ids[0] == NULL)
/* parse */
g_variant_get (val, "(a{sa{sv}})", &iter);
devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
while (g_variant_iter_next (iter, "{&sa{sv}}", &id, &iter_device)) {
dev = fu_device_new ();
fu_device_set_id (dev, id);
fu_device_set_metadata_from_iter (dev, iter_device);
g_ptr_array_add (devices, dev);
g_variant_iter_free (iter_device);
}
/* print */
if (devices->len == 0) {
g_print ("No hardware detected with firmware update capaility\n");
for (i = 0; ids[i] != NULL; i++)
g_print ("%i: %s\n", i, ids[i]);
} else {
guint i;
guint j;
const gchar *value;
const gchar *keys[] = {
FU_DEVICE_KEY_PROVIDER,
FU_DEVICE_KEY_VERSION,
NULL };
for (i = 0; i < devices->len; i++) {
dev = g_ptr_array_index (devices, i);
g_print ("Device: %s\n", fu_device_get_id (dev));
for (j = 0; keys[j] != NULL; j++) {
value = fu_device_get_metadata (dev, keys[j]);
if (value != NULL)
g_print (" %s:\t%s\n", keys[j], value);
}
}
}
return TRUE;
}

View File

@ -31,10 +31,10 @@
</doc:para>
</doc:description>
</doc:doc>
<arg type='as' name='ids' direction='out'>
<arg type='a{sa{sv}}' name='devices' direction='out'>
<doc:doc>
<doc:summary>
<doc:para>An array of IDs.</doc:para>
<doc:para>An array of devices, with any properties set on each.</doc:para>
</doc:summary>
</doc:doc>
</arg>