Flesh out the provider interface and allow offline updates

This commit is contained in:
Richard Hughes 2015-02-26 22:28:09 +00:00
parent 8dbfb1c478
commit 8bbfdf49a8
12 changed files with 672 additions and 68 deletions

View File

@ -1,3 +1,4 @@
policy/org.freedesktop.fwupd.policy.in
src/fu-debug.c
src/fu-main.c
src/fu-util.c

View File

@ -57,8 +57,12 @@ libexec_PROGRAMS = \
fwupd_SOURCES = \
fu-cleanup.h \
fu-common.h \
fu-debug.c \
fu-debug.h \
fu-device.c \
fu-device.h \
fu-provider.c \
fu-provider.h \
fu-provider-uefi.c \
fu-provider-uefi.h \
fu-resources.c \

View File

@ -26,4 +26,7 @@
#define FWUPD_DBUS_SERVICE "org.freedesktop.fwupd"
#define FWUPD_DBUS_INTERFACE "org.freedesktop.fwupd"
#define FU_ERROR 1
#define FU_ERROR_INTERNAL 0
#endif /* __FU_COMMON_H */

210
src/fu-debug.c Normal file
View File

@ -0,0 +1,210 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2010-2015 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 <glib/gi18n.h>
#include <unistd.h>
#include <stdio.h>
#include <fu-debug.h>
static gboolean _verbose = FALSE;
static gboolean _console = FALSE;
/**
* fu_debug_is_verbose:
**/
gboolean
fu_debug_is_verbose (void)
{
/* local first */
if (_verbose)
return TRUE;
/* fall back to env variable */
if (g_getenv ("VERBOSE") != NULL)
return TRUE;
return FALSE;
}
/**
* fu_debug_ignore_cb:
**/
static void
fu_debug_ignore_cb (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
/* syslog */
switch (log_level) {
case G_LOG_LEVEL_INFO:
g_print ("%s\n", message);
case G_LOG_LEVEL_CRITICAL:
case G_LOG_LEVEL_ERROR:
case G_LOG_LEVEL_WARNING:
g_print ("%s\n", message);
break;
default:
break;
}
}
/**
* fu_debug_handler_cb:
**/
static void
fu_debug_handler_cb (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
gchar str_time[255];
time_t the_time;
/* syslog */
switch (log_level) {
case G_LOG_LEVEL_INFO:
g_print ("%s\n", message);
case G_LOG_LEVEL_CRITICAL:
case G_LOG_LEVEL_ERROR:
case G_LOG_LEVEL_WARNING:
g_print ("%s\n", message);
break;
default:
break;
}
/* time header */
time (&the_time);
strftime (str_time, 254, "%H:%M:%S", localtime (&the_time));
/* no color please, we're British */
if (!_console) {
if (log_level == G_LOG_LEVEL_DEBUG) {
g_print ("%s\t%s\n",
str_time, message);
} else {
g_print ("***\n%s\t%s\n***\n",
str_time, message);
}
return;
}
/* critical is also in red */
if (log_level == G_LOG_LEVEL_CRITICAL ||
log_level == G_LOG_LEVEL_ERROR) {
g_print ("%c[%dm%s\t", 0x1B, 32, str_time);
g_print ("%c[%dm%s\n%c[%dm", 0x1B, 31, message, 0x1B, 0);
} else {
/* debug in blue */
g_print ("%c[%dm%s\t", 0x1B, 32, str_time);
g_print ("%c[%dm%s\n%c[%dm", 0x1B, 34, message, 0x1B, 0);
}
}
/**
* fu_debug_pre_parse_hook:
*/
static gboolean
fu_debug_pre_parse_hook (GOptionContext *context,
GOptionGroup *group,
gpointer data,
GError **error)
{
const GOptionEntry main_entries[] = {
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &_verbose,
/* TRANSLATORS: turn on all debugging */
N_("Show debugging information for all files"), NULL },
{ NULL}
};
/* add main entry */
g_option_context_add_main_entries (context, main_entries, NULL);
return TRUE;
}
/**
* fu_debug_destroy:
*/
void
fu_debug_destroy (void)
{
}
/**
* fu_debug_setup:
*/
void
fu_debug_setup (gboolean enabled)
{
if (enabled) {
g_log_set_fatal_mask (NULL, G_LOG_LEVEL_ERROR |
G_LOG_LEVEL_CRITICAL);
g_log_set_handler (G_LOG_DOMAIN,
G_LOG_LEVEL_ERROR |
G_LOG_LEVEL_CRITICAL |
G_LOG_LEVEL_DEBUG |
G_LOG_LEVEL_WARNING,
fu_debug_handler_cb, NULL);
} else {
/* hide all debugging */
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
fu_debug_ignore_cb, NULL);
}
/* are we on an actual TTY? */
_console = (isatty (fileno (stdout)) == 1);
}
/**
* fu_debug_post_parse_hook:
*/
static gboolean
fu_debug_post_parse_hook (GOptionContext *context,
GOptionGroup *group,
gpointer data,
GError **error)
{
/* verbose? */
fu_debug_setup (_verbose);
g_debug ("Verbose debugging %s (on console %i)",
_verbose ? "enabled" : "disabled", _console);
return TRUE;
}
/**
* fu_debug_get_option_group:
*/
GOptionGroup *
fu_debug_get_option_group (void)
{
GOptionGroup *group;
group = g_option_group_new ("debug",
_("Debugging Options"),
_("Show debugging options"),
NULL, NULL);
g_option_group_set_parse_hooks (group,
fu_debug_pre_parse_hook,
fu_debug_post_parse_hook);
return group;
}

32
src/fu-debug.h Normal file
View File

@ -0,0 +1,32 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2010-2011 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.
*/
#ifndef __CD_DEBUG_H__
#define __CD_DEBUG_H__
#include <glib.h>
gboolean fu_debug_is_verbose (void);
GOptionGroup *fu_debug_get_option_group (void);
void fu_debug_setup (gboolean enabled);
void fu_debug_destroy (void);
#endif /* __CD_DEBUG_H__ */

View File

@ -29,19 +29,17 @@
#include "fu-cleanup.h"
#include "fu-common.h"
#include "fu-debug.h"
#include "fu-device.h"
#include "fu-provider-uefi.h"
#include "fu-resources.h"
#define FU_ERROR 1
#define FU_ERROR_INTERNAL 0
typedef struct {
GDBusConnection *connection;
GDBusNodeInfo *introspection_daemon;
GMainLoop *loop;
GPtrArray *devices;
FuProviderUefi *provider_uefi;
GPtrArray *providers;
} FuMainPrivate;
/**
@ -62,6 +60,23 @@ fu_main_get_device_list_as_strv (FuMainPrivate *priv)
return val;
}
/**
* fu_main_get_device_by_id:
**/
static FuDevice *
fu_main_get_device_by_id (FuMainPrivate *priv, const gchar *id)
{
FuDevice *device_tmp;
guint i;
for (i = 0; i < priv->devices->len; i++) {
device_tmp = g_ptr_array_index (priv->devices, i);
if (g_strcmp0 (fu_device_get_id (device_tmp), id) == 0)
return device_tmp;
}
return NULL;
}
/**
* fu_main_daemon_method_call:
**/
@ -74,6 +89,8 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
FuMainPrivate *priv = (FuMainPrivate *) user_data;
GVariant *val;
g_debug ("Called %s()", method_name);
/* return 'as' */
if (g_strcmp0 (method_name, "GetDevices") == 0) {
_cleanup_strv_free_ gchar **devices = NULL;
@ -83,6 +100,55 @@ fu_main_daemon_method_call (GDBusConnection *connection, const gchar *sender,
return;
}
/* return '' */
if (g_strcmp0 (method_name, "UpdateOffline") == 0) {
GDBusMessage *message;
GUnixFDList *fd_list;
FuDevice *device;
const gchar *id = NULL;
gint32 fd_handle = 0;
gint fd;
_cleanup_error_free_ GError *error = NULL;
/* check the id exists */
g_variant_get (parameters, "(&sh)", &id, &fd_handle);
device = fu_main_get_device_by_id (priv, id);
if (device == NULL) {
g_dbus_method_invocation_return_error (invocation,
FU_ERROR,
FU_ERROR_INTERNAL,
"no such ID %s",
id);
return;
}
/* get the fd */
message = g_dbus_method_invocation_get_message (invocation);
fd_list = g_dbus_message_get_unix_fd_list (message);
if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1) {
g_dbus_method_invocation_return_error (invocation,
FU_ERROR,
FU_ERROR_INTERNAL,
"invalid handle");
return;
}
fd = g_unix_fd_list_get (fd_list, fd_handle, &error);
if (fd < 0) {
g_dbus_method_invocation_return_gerror (invocation,
error);
return;
}
/* TODO: run the correct provider that can handle this */
// if (!fu_provider_update_offline (provider, device, fd, &error)) {
// g_dbus_method_invocation_return_gerror (invocation,
// error);
// return;
// }
g_dbus_method_invocation_return_value (invocation, NULL);
return;
}
/* we suck */
g_dbus_method_invocation_return_error (invocation,
FU_ERROR,
@ -148,8 +214,16 @@ fu_main_on_name_acquired_cb (GDBusConnection *connection,
gpointer user_data)
{
FuMainPrivate *priv = (FuMainPrivate *) user_data;
fu_provider_uefi_coldplug (priv->provider_uefi);
FuProvider *provider;
guint i;
g_debug ("FuMain: acquired name: %s", name);
for (i = 0; i < priv->providers->len; i++) {
_cleanup_error_free_ GError *error = NULL;
provider = g_ptr_array_index (priv->providers, i);
if (!fu_provider_coldplug (FU_PROVIDER (provider), &error))
g_warning ("Failed to coldplug: %s", error->message);
}
}
/**
@ -202,7 +276,7 @@ fu_main_load_introspection (const gchar *filename, GError **error)
* cd_main_provider_device_added_cb:
**/
static void
cd_main_provider_device_added_cb (FuProviderUefi *provider_uefi,
cd_main_provider_device_added_cb (FuProvider *provider,
FuDevice *device,
gpointer user_data)
{
@ -214,7 +288,7 @@ cd_main_provider_device_added_cb (FuProviderUefi *provider_uefi,
* cd_main_provider_device_removed_cb:
**/
static void
cd_main_provider_device_removed_cb (FuProviderUefi *provider_uefi,
cd_main_provider_device_removed_cb (FuProvider *provider,
FuDevice *device,
gpointer user_data)
{
@ -222,6 +296,21 @@ cd_main_provider_device_removed_cb (FuProviderUefi *provider_uefi,
g_ptr_array_remove (priv->devices, g_object_ref (device));
}
/**
* fu_main_add_provider:
**/
static void
fu_main_add_provider (FuMainPrivate *priv, FuProvider *provider)
{
g_signal_connect (provider, "device-added",
G_CALLBACK (cd_main_provider_device_added_cb),
priv);
g_signal_connect (provider, "device-removed",
G_CALLBACK (cd_main_provider_device_removed_cb),
priv);
g_ptr_array_add (priv->providers, provider);
}
/**
* main:
**/
@ -256,6 +345,7 @@ main (int argc, char *argv[])
g_set_application_name (_("Firmware Update"));
context = g_option_context_new (NULL);
g_option_context_add_main_entries (context, options, NULL);
g_option_context_add_group (context, fu_debug_get_option_group ());
g_option_context_set_summary (context, _("Firmware Update D-Bus Service"));
ret = g_option_context_parse (context, &argc, &argv, &error);
if (!ret) {
@ -268,13 +358,10 @@ main (int argc, char *argv[])
priv = g_new0 (FuMainPrivate, 1);
priv->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
priv->loop = g_main_loop_new (NULL, FALSE);
priv->provider_uefi = fu_provider_uefi_new ();
g_signal_connect (priv->provider_uefi, "device-added",
G_CALLBACK (cd_main_provider_device_added_cb),
priv);
g_signal_connect (priv->provider_uefi, "device-removed",
G_CALLBACK (cd_main_provider_device_removed_cb),
priv);
/* add providers */
priv->providers = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
fu_main_add_provider (priv, fu_provider_uefi_new ());
/* load introspection from file */
priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml",
@ -319,6 +406,7 @@ out:
g_object_unref (priv->connection);
if (priv->introspection_daemon != NULL)
g_dbus_node_info_unref (priv->introspection_daemon);
g_ptr_array_unref (priv->providers);
g_ptr_array_unref (priv->devices);
g_free (priv);
}

View File

@ -40,15 +40,7 @@ struct _FuProviderUefiPrivate
GPtrArray *array_devices;
};
enum {
SIGNAL_SENSOR_ADDED,
SIGNAL_SENSOR_REMOVED,
SIGNAL_LAST
};
static guint signals[SIGNAL_LAST] = { 0 };
G_DEFINE_TYPE (FuProviderUefi, fu_provider_uefi, G_TYPE_OBJECT)
G_DEFINE_TYPE (FuProviderUefi, fu_provider_uefi, FU_TYPE_PROVIDER)
/**
* fu_provider_uefi_get_by_id:
@ -72,19 +64,34 @@ fu_provider_uefi_get_by_id (FuProviderUefi *provider_uefi,
return device;
}
/**
* fu_provider_uefi_update_offline:
**/
static gboolean
fu_provider_uefi_update_offline (FuProvider *provider,
FuDevice *device,
gint fd,
GError **error)
{
//FIXME
return TRUE;
}
/**
* fu_provider_uefi_coldplug:
**/
void
fu_provider_uefi_coldplug (FuProviderUefi *provider_uefi)
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, "819b858e-c52c-402f-80e1-5b311b6c1959");
g_signal_emit (provider_uefi, signals[SIGNAL_SENSOR_ADDED], 0, dev);
fu_provider_emit_added (provider, dev);
return TRUE;
}
/**
@ -93,20 +100,12 @@ fu_provider_uefi_coldplug (FuProviderUefi *provider_uefi)
static void
fu_provider_uefi_class_init (FuProviderUefiClass *klass)
{
FuProviderClass *provider_class = FU_PROVIDER_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
provider_class->coldplug = fu_provider_uefi_coldplug;
provider_class->update_offline = fu_provider_uefi_update_offline;
object_class->finalize = fu_provider_uefi_finalize;
signals[SIGNAL_SENSOR_ADDED] =
g_signal_new ("device-added",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (FuProviderUefiClass, device_added),
NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, FU_TYPE_DEVICE);
signals[SIGNAL_SENSOR_REMOVED] =
g_signal_new ("device-removed",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (FuProviderUefiClass, device_removed),
NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, FU_TYPE_DEVICE);
g_type_class_add_private (klass, sizeof (FuProviderUefiPrivate));
}
@ -138,11 +137,10 @@ fu_provider_uefi_finalize (GObject *object)
/**
* fu_provider_uefi_new:
**/
FuProviderUefi *
FuProvider *
fu_provider_uefi_new (void)
{
FuProviderUefi *provider_uefi;
provider_uefi = g_object_new (FU_TYPE_PROVIDER_UEFI, NULL);
return FU_PROVIDER_UEFI (provider_uefi);
FuProviderUefi *provider;
provider = g_object_new (FU_TYPE_PROVIDER_UEFI, NULL);
return FU_PROVIDER (provider);
}

View File

@ -25,16 +25,15 @@
#include <glib-object.h>
#include "fu-device.h"
#include "fu-provider-uefi.h"
#include "fu-provider.h"
G_BEGIN_DECLS
#define FU_TYPE_PROVIDER_UEFI (fu_provider_uefi_get_type ())
#define FU_PROVIDER_UEFI(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FU_TYPE_PROVIDER_UEFI, FuProviderUefi))
#define FU_PROVIDER_UEFI_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), FU_TYPE_PROVIDER_UEFI, FuProviderUefiClass))
//#define FU_PROVIDER_UEFI_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), FU_TYPE_PROVIDER_UEFI, FuProviderUefiClass))
#define FU_IS_PROVIDER_UEFI(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FU_TYPE_PROVIDER_UEFI))
#define FU_IS_PROVIDER_UEFI_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), FU_TYPE_PROVIDER_UEFI))
#define FU_PROVIDER_UEFI_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), FU_TYPE_PROVIDER_UEFI, FuProviderUefiClass))
//#define FU_IS_PROVIDER_UEFI_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), FU_TYPE_PROVIDER_UEFI))
typedef struct _FuProviderUefiPrivate FuProviderUefiPrivate;
typedef struct _FuProviderUefi FuProviderUefi;
@ -42,22 +41,17 @@ typedef struct _FuProviderUefiClass FuProviderUefiClass;
struct _FuProviderUefi
{
GObject parent;
FuProvider parent;
FuProviderUefiPrivate *priv;
};
struct _FuProviderUefiClass
{
GObjectClass parent_class;
void (* device_added) (FuProviderUefi *provider_uefi,
FuDevice *device);
void (* device_removed) (FuProviderUefi *provider_uefi,
FuDevice *device);
FuProviderClass parent_class;
};
GType fu_provider_uefi_get_type (void);
FuProviderUefi *fu_provider_uefi_new (void);
void fu_provider_uefi_coldplug (FuProviderUefi *provider_uefi);
FuProvider *fu_provider_uefi_new (void);
G_END_DECLS

135
src/fu-provider.c Normal file
View File

@ -0,0 +1,135 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2015 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 <glib-object.h>
#include <gio/gio.h>
#include "fu-cleanup.h"
#include "fu-common.h"
#include "fu-device.h"
#include "fu-provider-uefi.h"
static void fu_provider_finalize (GObject *object);
#define FU_PROVIDER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), FU_TYPE_PROVIDER, FuProviderPrivate))
enum {
SIGNAL_DEVICE_ADDED,
SIGNAL_DEVICE_REMOVED,
SIGNAL_LAST
};
static guint signals[SIGNAL_LAST] = { 0 };
G_DEFINE_TYPE (FuProvider, fu_provider, G_TYPE_OBJECT)
/**
* fu_provider_coldplug:
**/
gboolean
fu_provider_coldplug (FuProvider *provider, GError **error)
{
FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider);
if (klass->coldplug != NULL)
return klass->coldplug (provider, error);
return TRUE;
}
/**
* fu_provider_update_offline:
**/
gboolean
fu_provider_update_offline (FuProvider *provider,
FuDevice *device,
gint fd,
GError **error)
{
FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider);
if (klass->update_offline == NULL) {
g_set_error_literal (error,
FU_ERROR,
FU_ERROR_INTERNAL,
"No offline update functionality");
return FALSE;
}
return klass->update_offline (provider, device, fd, error);
}
/**
* fu_provider_emit_added:
**/
void
fu_provider_emit_added (FuProvider *provider, FuDevice *device)
{
g_debug ("emit added: %s", fu_device_get_id (device));
g_signal_emit (provider, signals[SIGNAL_DEVICE_ADDED], 0, device);
}
/**
* fu_provider_emit_removed:
**/
void
fu_provider_emit_removed (FuProvider *provider, FuDevice *device)
{
g_debug ("emit removed: %s", fu_device_get_id (device));
g_signal_emit (provider, signals[SIGNAL_DEVICE_REMOVED], 0, device);
}
/**
* fu_provider_class_init:
**/
static void
fu_provider_class_init (FuProviderClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = fu_provider_finalize;
signals[SIGNAL_DEVICE_ADDED] =
g_signal_new ("device-added",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (FuProviderClass, device_added),
NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, FU_TYPE_DEVICE);
signals[SIGNAL_DEVICE_REMOVED] =
g_signal_new ("device-removed",
G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (FuProviderClass, device_removed),
NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, FU_TYPE_DEVICE);
}
/**
* fu_provider_init:
**/
static void
fu_provider_init (FuProvider *provider)
{
}
/**
* fu_provider_finalize:
**/
static void
fu_provider_finalize (GObject *object)
{
G_OBJECT_CLASS (fu_provider_parent_class)->finalize (object);
}

81
src/fu-provider.h Normal file
View File

@ -0,0 +1,81 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2015 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.
*/
#ifndef __FU_PROVIDER_H
#define __FU_PROVIDER_H
#include <glib-object.h>
#include "fu-device.h"
#include "fu-provider.h"
G_BEGIN_DECLS
#define FU_TYPE_PROVIDER (fu_provider_get_type ())
#define FU_PROVIDER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FU_TYPE_PROVIDER, FuProvider))
#define FU_PROVIDER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), FU_TYPE_PROVIDER, FuProviderClass))
#define FU_IS_PROVIDER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FU_TYPE_PROVIDER))
#define FU_IS_PROVIDER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), FU_TYPE_PROVIDER))
#define FU_PROVIDER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), FU_TYPE_PROVIDER, FuProviderClass))
typedef struct _FuProvider FuProvider;
typedef struct _FuProviderClass FuProviderClass;
struct _FuProvider
{
GObject parent;
};
struct _FuProviderClass
{
GObjectClass parent_class;
/* vfunc */
gboolean (*coldplug) (FuProvider *provider,
GError **error);
gboolean (*update_offline) (FuProvider *provider,
FuDevice *device,
gint fd,
GError **error);
/* signals */
void (* device_added) (FuProvider *provider,
FuDevice *device);
void (* device_removed) (FuProvider *provider,
FuDevice *device);
};
GType fu_provider_get_type (void);
void fu_provider_emit_added (FuProvider *provider,
FuDevice *device);
void fu_provider_emit_removed (FuProvider *provider,
FuDevice *device);
gboolean fu_provider_coldplug (FuProvider *provider,
GError **error);
gboolean fu_provider_update_offline (FuProvider *provider,
FuDevice *device,
gint fd,
GError **error);
G_END_DECLS
#endif /* __FU_PROVIDER_H */

View File

@ -21,11 +21,13 @@
#include "config.h"
#include <glib/gi18n.h>
#include <fcntl.h>
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include <glib/gi18n.h>
#include <locale.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include "fu-cleanup.h"
#include "fu-common.h"
@ -194,7 +196,7 @@ fu_util_get_devices (FuUtilPrivate *priv, gchar **values, GError **error)
_cleanup_object_unref_ GDBusConnection *conn = NULL;
_cleanup_object_unref_ GDBusProxy *proxy = NULL;
_cleanup_variant_unref_ GVariant *val = NULL;
const gchar **guids = NULL;
const gchar **ids = NULL;
guint i;
conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
@ -219,12 +221,12 @@ fu_util_get_devices (FuUtilPrivate *priv, gchar **values, GError **error)
error);
if (val == NULL)
return FALSE;
g_variant_get (val, "(^a&s)", &guids);
g_assert (guids != NULL);
if (guids[0] == NULL)
g_variant_get (val, "(^a&s)", &ids);
g_assert (ids != NULL);
if (ids[0] == NULL)
g_print ("No hardware detected with firmware update capaility\n");
for (i = 0; guids[i] != NULL; i++)
g_print ("%i: %s\n", i, guids[i]);
for (i = 0; ids[i] != NULL; i++)
g_print ("%i: %s\n", i, ids[i]);
return TRUE;
}
@ -234,7 +236,63 @@ fu_util_get_devices (FuUtilPrivate *priv, gchar **values, GError **error)
static gboolean
fu_util_update_offline (FuUtilPrivate *priv, gchar **values, GError **error)
{
//FIXME
GVariant *body;
gint retval;
gint fd;
_cleanup_object_unref_ GDBusConnection *conn = NULL;
_cleanup_object_unref_ GDBusMessage *message = NULL;
_cleanup_object_unref_ GDBusMessage *request = NULL;
_cleanup_object_unref_ GUnixFDList *fd_list = NULL;
if (g_strv_length (values) != 2) {
g_set_error_literal (error,
FU_ERROR,
FU_ERROR_INTERNAL,
"Invalid arguments: expected 'id' 'filename'");
return FALSE;
}
conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
if (conn == NULL)
return FALSE;
/* open file */
fd = open (values[1], O_RDONLY);
if (fd < 0) {
g_set_error (error,
FU_ERROR,
FU_ERROR_INTERNAL,
"failed to open %s",
values[1]);
return FALSE;
}
/* set out of band file descriptor */
fd_list = g_unix_fd_list_new ();
retval = g_unix_fd_list_append (fd_list, fd, NULL);
g_assert (retval != -1);
request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE,
FWUPD_DBUS_PATH,
FWUPD_DBUS_INTERFACE,
"UpdateOffline");
g_dbus_message_set_unix_fd_list (request, fd_list);
/* g_unix_fd_list_append did a dup() already */
close (fd);
/* send message */
body = g_variant_new ("(sh)", values[0], fd);
g_dbus_message_set_body (request, body);
message = g_dbus_connection_send_message_with_reply_sync (conn,
request,
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
-1,
NULL,
NULL,
error);
if (message == NULL)
return FALSE;
return TRUE;
}

View File

@ -31,10 +31,10 @@
</doc:para>
</doc:description>
</doc:doc>
<arg type='as' name='devices' direction='out'>
<arg type='as' name='ids' direction='out'>
<doc:doc>
<doc:summary>
<doc:para>An array of GUIDs.</doc:para>
<doc:para>An array of IDs.</doc:para>
</doc:summary>
</doc:doc>
</arg>
@ -49,10 +49,10 @@
</doc:para>
</doc:description>
</doc:doc>
<arg type='s' name='guid' direction='in'>
<arg type='s' name='id' direction='in'>
<doc:doc>
<doc:summary>
<doc:para>A GUID of the hardware to update.</doc:para>
<doc:para>An ID, typically a GUID of the hardware to update.</doc:para>
</doc:summary>
</doc:doc>
</arg>