From bc93e4ab6ef59c20e2ef6cd3ed46ff195834e809 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Thu, 8 Dec 2016 17:29:51 +0000 Subject: [PATCH] Make all providers and plugins share a GUsbContext This means we don't have more that one thread just watching for the USB hotplug events. To achieve this split up the coldplug into setup and coldplug phases and run the enumerate just once in the daemon. --- libdfu/dfu-context.c | 40 +++++++++++++++++++++----- libdfu/dfu-context.h | 2 ++ src/fu-main.c | 44 ++++++++++++++++++++++++++--- src/fu-plugin.c | 14 +++++++++ src/fu-plugin.h | 5 ++++ src/fu-provider-chug.c | 19 ++++++------- src/fu-provider-dell.c | 33 +++++++++++++--------- src/fu-provider-dfu.c | 27 +++++++++--------- src/fu-provider-ebitdo.c | 24 ++++++++++------ src/fu-provider-usb.c | 24 ++++++++++------ src/fu-provider.c | 36 ++++++++++++++++++++++- src/fu-provider.h | 9 ++++++ src/plugins/fu-plugin-steelseries.c | 2 +- 13 files changed, 213 insertions(+), 66 deletions(-) diff --git a/libdfu/dfu-context.c b/libdfu/dfu-context.c index 569e169ad..00519f0c9 100644 --- a/libdfu/dfu-context.c +++ b/libdfu/dfu-context.c @@ -38,8 +38,6 @@ #include "config.h" -#include - #include "dfu-device-private.h" #include "dfu-error.h" #include "dfu-context.h" @@ -286,17 +284,23 @@ dfu_context_device_removed_cb (GUsbContext *usb_context, g_timeout_add (priv->timeout, dfu_context_device_timeout_cb, item); } +static void +dfu_context_set_usb_context (DfuContext *context, GUsbContext *usb_ctx) +{ + DfuContextPrivate *priv = GET_PRIVATE (context); + priv->usb_ctx = g_object_ref (usb_ctx); + g_signal_connect (priv->usb_ctx, "device-added", + G_CALLBACK (dfu_context_device_added_cb), context); + g_signal_connect (priv->usb_ctx, "device-removed", + G_CALLBACK (dfu_context_device_removed_cb), context); +} + static void dfu_context_init (DfuContext *context) { DfuContextPrivate *priv = GET_PRIVATE (context); priv->timeout = 5000; priv->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) dfu_context_device_free); - priv->usb_ctx = g_usb_context_new (NULL); - g_signal_connect (priv->usb_ctx, "device-added", - G_CALLBACK (dfu_context_device_added_cb), context); - g_signal_connect (priv->usb_ctx, "device-removed", - G_CALLBACK (dfu_context_device_removed_cb), context); } static void @@ -324,7 +328,29 @@ DfuContext * dfu_context_new (void) { DfuContext *context; + g_autoptr(GUsbContext) usb_ctx = g_usb_context_new (NULL); context = g_object_new (DFU_TYPE_CONTEXT, NULL); + dfu_context_set_usb_context (context, usb_ctx); + return context; +} + +/** + * dfu_context_new_with_context: + * @context: a #DfuContext + * + * Creates a new DFU context object. + * + * Return value: a new #DfuContext + * + * Since: 0.7.6 + **/ +DfuContext * +dfu_context_new_with_context (GUsbContext *usb_ctx) +{ + DfuContext *context; + g_return_val_if_fail (G_USB_IS_CONTEXT (usb_ctx), NULL); + context = g_object_new (DFU_TYPE_CONTEXT, NULL); + dfu_context_set_usb_context (context, usb_ctx); return context; } diff --git a/libdfu/dfu-context.h b/libdfu/dfu-context.h index 3b194134d..b0d85616d 100644 --- a/libdfu/dfu-context.h +++ b/libdfu/dfu-context.h @@ -24,6 +24,7 @@ #include #include +#include #include "dfu-device.h" @@ -55,6 +56,7 @@ struct _DfuContextClass }; DfuContext *dfu_context_new (void); +DfuContext *dfu_context_new_with_context (GUsbContext *usb_ctx); gboolean dfu_context_enumerate (DfuContext *context, GError **error); GPtrArray *dfu_context_get_devices (DfuContext *context); diff --git a/src/fu-main.c b/src/fu-main.c index 8f40b81de..109e7fe3f 100644 --- a/src/fu-main.c +++ b/src/fu-main.c @@ -71,6 +71,7 @@ typedef struct { GDBusNodeInfo *introspection_daemon; GDBusProxy *proxy_uid; GDBusProxy *proxy_upower; + GUsbContext *usb_ctx; GKeyFile *config; GMainLoop *loop; GPtrArray *devices; /* of FuDeviceItem */ @@ -260,7 +261,7 @@ fu_main_invocation_return_error (FuMainPrivate *priv, } static gboolean -fu_main_load_plugins (GHashTable *plugins, GError **error) +fu_main_load_plugins (FuMainPrivate *priv, GError **error) { FuPlugin *plugin; GModule *module; @@ -296,13 +297,14 @@ fu_main_load_plugins (GHashTable *plugins, GError **error) g_warning ("plugin %s requires name", filename); continue; } + fu_plugin_set_usb_context (plugin, priv->usb_ctx); /* add */ - g_hash_table_insert (plugins, g_strdup (plugin->name), plugin); + g_hash_table_insert (priv->plugins, g_strdup (plugin->name), plugin); } /* start them all up */ - values = g_hash_table_get_values (plugins); + values = g_hash_table_get_values (priv->plugins); for (GList *l = values; l != NULL; l = l->next) { plugin = FU_PLUGIN (l->data); if (!fu_plugin_run_startup (plugin, error)) @@ -2138,6 +2140,24 @@ fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender, return NULL; } +static void +fu_main_providers_setup (FuMainPrivate *priv) +{ + g_autoptr(AsProfileTask) ptask = NULL; + + ptask = as_profile_start_literal (priv->profile, "FuMain:setup"); + for (guint i = 0; i < priv->providers->len; i++) { + g_autoptr(GError) error = NULL; + g_autoptr(AsProfileTask) ptask2 = NULL; + FuProvider *provider = g_ptr_array_index (priv->providers, i); + ptask2 = as_profile_start (priv->profile, + "FuMain:setup{%s}", + fu_provider_get_name (provider)); + if (!fu_provider_setup (FU_PROVIDER (provider), &error)) + g_warning ("Failed to setup: %s", error->message); + } +} + static void fu_main_providers_coldplug (FuMainPrivate *priv) { @@ -2181,6 +2201,8 @@ fu_main_on_bus_acquired_cb (GDBusConnection *connection, g_assert (registration_id > 0); /* add devices */ + fu_main_providers_setup (priv); + g_usb_context_enumerate (priv->usb_ctx); fu_main_providers_coldplug (priv); /* connect to D-Bus directly */ @@ -2471,7 +2493,7 @@ main (int argc, char *argv[]) /* load plugin */ priv->plugins = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) fu_plugin_free); - if (!fu_main_load_plugins (priv->plugins, &error)) { + if (!fu_main_load_plugins (priv, &error)) { g_print ("failed to load plugins: %s\n", error->message); retval = EXIT_FAILURE; goto out; @@ -2519,6 +2541,18 @@ main (int argc, char *argv[]) /* last as least priority */ fu_main_add_provider (priv, fu_provider_usb_new ()); + /* set shared USB context */ + priv->usb_ctx = g_usb_context_new (&error); + if (priv->usb_ctx == NULL) { + g_warning ("FuMain: failed to get USB context: %s", + error->message); + goto out; + } + for (guint i = 0; i < priv->providers->len; i++) { + FuProvider *provider = g_ptr_array_index (priv->providers, i); + fu_provider_set_usb_context (provider, priv->usb_ctx); + } + /* load introspection from file */ priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml", &error); @@ -2570,6 +2604,8 @@ out: g_object_unref (priv->proxy_uid); if (priv->proxy_upower != NULL) g_object_unref (priv->proxy_upower); + if (priv->usb_ctx != NULL) + g_object_unref (priv->usb_ctx); if (priv->config != NULL) g_key_file_unref (priv->config); if (priv->connection != NULL) diff --git a/src/fu-plugin.c b/src/fu-plugin.c index 4d96fb3fb..c67a6d37a 100644 --- a/src/fu-plugin.c +++ b/src/fu-plugin.c @@ -56,6 +56,18 @@ fu_plugin_new (GModule *module) return plugin; } +GUsbContext * +fu_plugin_get_usb_context (FuPlugin *plugin) +{ + return g_object_ref (plugin->usb_ctx); +} + +void +fu_plugin_set_usb_context (FuPlugin *plugin, GUsbContext *usb_ctx) +{ + g_set_object (&plugin->usb_ctx, usb_ctx); +} + void fu_plugin_free (FuPlugin *plugin) { @@ -69,6 +81,8 @@ fu_plugin_free (FuPlugin *plugin) } /* deallocate */ + if (plugin->usb_ctx != NULL) + g_object_unref (plugin->usb_ctx); g_module_close (plugin->module); g_free (plugin->name); g_free (plugin->priv); diff --git a/src/fu-plugin.h b/src/fu-plugin.h index 39de0b35a..c6bb93f9e 100644 --- a/src/fu-plugin.h +++ b/src/fu-plugin.h @@ -24,6 +24,7 @@ #include #include +#include #include "fu-device.h" @@ -34,6 +35,7 @@ typedef struct FuPlugin FuPlugin; struct FuPlugin { GModule *module; + GUsbContext *usb_ctx; gboolean enabled; gchar *name; FuPluginPrivate *priv; @@ -80,6 +82,9 @@ gboolean fu_plugin_run_device_update (FuPlugin *plugin, FuDevice *device, GBytes *data, GError **error); +GUsbContext *fu_plugin_get_usb_context (FuPlugin *plugin); +void fu_plugin_set_usb_context (FuPlugin *plugin, + GUsbContext *usb_ctx); G_END_DECLS diff --git a/src/fu-provider-chug.c b/src/fu-provider-chug.c index 17f5bb407..0b0311b05 100644 --- a/src/fu-provider-chug.c +++ b/src/fu-provider-chug.c @@ -541,11 +541,17 @@ fu_provider_chug_device_removed_cb (GUsbContext *ctx, } static gboolean -fu_provider_chug_coldplug (FuProvider *provider, GError **error) +fu_provider_chug_setup (FuProvider *provider, GError **error) { FuProviderChug *provider_chug = FU_PROVIDER_CHUG (provider); FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug); - g_usb_context_enumerate (priv->usb_ctx); + priv->usb_ctx = fu_provider_get_usb_context (provider); + g_signal_connect (priv->usb_ctx, "device-added", + G_CALLBACK (fu_provider_chug_device_added_cb), + provider_chug); + g_signal_connect (priv->usb_ctx, "device-removed", + G_CALLBACK (fu_provider_chug_device_removed_cb), + provider_chug); return TRUE; } @@ -556,7 +562,7 @@ fu_provider_chug_class_init (FuProviderChugClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); provider_class->get_name = fu_provider_chug_get_name; - provider_class->coldplug = fu_provider_chug_coldplug; + provider_class->setup = fu_provider_chug_setup; provider_class->update_online = fu_provider_chug_update; provider_class->verify = fu_provider_chug_verify; object_class->finalize = fu_provider_chug_finalize; @@ -568,14 +574,7 @@ fu_provider_chug_init (FuProviderChug *provider_chug) FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug); priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) fu_provider_chug_device_free); - priv->usb_ctx = g_usb_context_new (NULL); priv->device_queue = ch_device_queue_new (); - g_signal_connect (priv->usb_ctx, "device-added", - G_CALLBACK (fu_provider_chug_device_added_cb), - provider_chug); - g_signal_connect (priv->usb_ctx, "device-removed", - G_CALLBACK (fu_provider_chug_device_removed_cb), - provider_chug); } static void diff --git a/src/fu-provider-dell.c b/src/fu-provider-dell.c index 40dff441f..8f57cbd0f 100644 --- a/src/fu-provider-dell.c +++ b/src/fu-provider-dell.c @@ -877,7 +877,7 @@ fu_provider_dell_detect_tpm (FuProvider *provider, GError **error) } static gboolean -fu_provider_dell_coldplug (FuProvider *provider, GError **error) +fu_provider_dell_setup (FuProvider *provider, GError **error) { FuProviderDell *provider_dell = FU_PROVIDER_DELL (provider); FuProviderDellPrivate *priv = GET_PRIVATE (provider_dell); @@ -885,6 +885,15 @@ fu_provider_dell_coldplug (FuProvider *provider, GError **error) gint uefi_supported = 0; struct smbios_struct *de_table; + /* get USB */ + priv->usb_ctx = fu_provider_get_usb_context (provider); + g_signal_connect (priv->usb_ctx, "device-added", + G_CALLBACK (fu_provider_dell_device_added_cb), + provider_dell); + g_signal_connect (priv->usb_ctx, "device-removed", + G_CALLBACK (fu_provider_dell_device_removed_cb), + provider_dell); + if (priv->fake_smbios) { g_debug ("Dell: called with fake SMBIOS implementation. " "We're ignoring test for SBMIOS table and ESRT. " @@ -924,14 +933,15 @@ fu_provider_dell_coldplug (FuProvider *provider, GError **error) return FALSE; } + return TRUE; +} - /* enumerate looking for a connected dock */ - g_usb_context_enumerate (priv->usb_ctx); - +static gboolean +fu_provider_dell_coldplug (FuProvider *provider, GError **error) +{ /* look for switchable TPM */ if (!fu_provider_dell_detect_tpm (provider, error)) g_debug ("Dell: No switchable TPM detected"); - return TRUE; } @@ -1009,7 +1019,7 @@ fu_provider_dell_update_offline (FuProvider *provider, #endif /* test the flash counter - * - devices with 0 left at coldplug aren't allowed offline updates + * - devices with 0 left at setup aren't allowed offline updates * - devices greater than 0 should show a warning when near 0 */ flashes_left = fu_device_get_flashes_left (device); @@ -1210,6 +1220,7 @@ fu_provider_dell_class_init (FuProviderDellClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); provider_class->get_name = fu_provider_dell_get_name; + provider_class->setup = fu_provider_dell_setup; provider_class->coldplug = fu_provider_dell_coldplug; provider_class->unlock = fu_provider_dell_unlock; provider_class->update_offline = fu_provider_dell_update_offline; @@ -1225,13 +1236,6 @@ fu_provider_dell_init (FuProviderDell *provider_dell) priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) fu_provider_dell_device_free); - priv->usb_ctx = g_usb_context_new (NULL); - g_signal_connect (priv->usb_ctx, "device-added", - G_CALLBACK (fu_provider_dell_device_added_cb), - provider_dell); - g_signal_connect (priv->usb_ctx, "device-removed", - G_CALLBACK (fu_provider_dell_device_removed_cb), - provider_dell); priv->fake_smbios = FALSE; if (g_getenv ("FWUPD_DELL_FAKE_SMBIOS") != NULL) priv->fake_smbios = TRUE; @@ -1244,7 +1248,8 @@ fu_provider_dell_finalize (GObject *object) FuProviderDellPrivate *priv = GET_PRIVATE (provider_dell); g_hash_table_unref (priv->devices); - g_object_unref (priv->usb_ctx); + if (priv->usb_ctx != NULL) + g_object_unref (priv->usb_ctx); G_OBJECT_CLASS (fu_provider_dell_parent_class)->finalize (object); } diff --git a/src/fu-provider-dfu.c b/src/fu-provider-dfu.c index 9e5388a09..4789030f9 100644 --- a/src/fu-provider-dfu.c +++ b/src/fu-provider-dfu.c @@ -205,11 +205,22 @@ fu_provider_dfu_device_removed_cb (DfuContext *ctx, } static gboolean -fu_provider_dfu_coldplug (FuProvider *provider, GError **error) +fu_provider_dfu_setup (FuProvider *provider, GError **error) { + g_autoptr(GUsbContext) usb_ctx = NULL; FuProviderDfu *provider_dfu = FU_PROVIDER_DFU (provider); FuProviderDfuPrivate *priv = GET_PRIVATE (provider_dfu); - dfu_context_enumerate (priv->context, NULL); + usb_ctx = fu_provider_get_usb_context (provider); + priv->context = dfu_context_new_with_context (usb_ctx); + g_signal_connect (priv->context, "device-added", + G_CALLBACK (fu_provider_dfu_device_added_cb), + provider_dfu); + g_signal_connect (priv->context, "device-removed", + G_CALLBACK (fu_provider_dfu_device_removed_cb), + provider_dfu); + g_signal_connect (priv->context, "device-changed", + G_CALLBACK (fu_provider_dfu_device_changed_cb), + provider_dfu); return TRUE; } @@ -391,7 +402,7 @@ fu_provider_dfu_class_init (FuProviderDfuClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); provider_class->get_name = fu_provider_dfu_get_name; - provider_class->coldplug = fu_provider_dfu_coldplug; + provider_class->setup = fu_provider_dfu_setup; provider_class->update_online = fu_provider_dfu_update; provider_class->verify = fu_provider_dfu_verify; object_class->finalize = fu_provider_dfu_finalize; @@ -403,16 +414,6 @@ fu_provider_dfu_init (FuProviderDfu *provider_dfu) FuProviderDfuPrivate *priv = GET_PRIVATE (provider_dfu); priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); - priv->context = dfu_context_new (); - g_signal_connect (priv->context, "device-added", - G_CALLBACK (fu_provider_dfu_device_added_cb), - provider_dfu); - g_signal_connect (priv->context, "device-removed", - G_CALLBACK (fu_provider_dfu_device_removed_cb), - provider_dfu); - g_signal_connect (priv->context, "device-changed", - G_CALLBACK (fu_provider_dfu_device_changed_cb), - provider_dfu); } static void diff --git a/src/fu-provider-ebitdo.c b/src/fu-provider-ebitdo.c index 491525452..47fe68c4d 100644 --- a/src/fu-provider-ebitdo.c +++ b/src/fu-provider-ebitdo.c @@ -219,12 +219,26 @@ fu_provider_ebitdo_device_removed_cb (GUsbContext *ctx, g_hash_table_remove (priv->devices, platform_id); } +static gboolean +fu_provider_ebitdo_setup (FuProvider *provider, GError **error) +{ + FuProviderEbitdo *provider_ebitdo = FU_PROVIDER_EBITDO (provider); + FuProviderEbitdoPrivate *priv = GET_PRIVATE (provider_ebitdo); + priv->usb_ctx = fu_provider_get_usb_context (provider); + g_signal_connect (priv->usb_ctx, "device-added", + G_CALLBACK (fu_provider_ebitdo_device_added_cb), + provider_ebitdo); + g_signal_connect (priv->usb_ctx, "device-removed", + G_CALLBACK (fu_provider_ebitdo_device_removed_cb), + provider_ebitdo); + return TRUE; +} + static gboolean fu_provider_ebitdo_coldplug (FuProvider *provider, GError **error) { FuProviderEbitdo *provider_ebitdo = FU_PROVIDER_EBITDO (provider); FuProviderEbitdoPrivate *priv = GET_PRIVATE (provider_ebitdo); - g_usb_context_enumerate (priv->usb_ctx); priv->done_enumerate = TRUE; return TRUE; } @@ -236,6 +250,7 @@ fu_provider_ebitdo_class_init (FuProviderEbitdoClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); provider_class->get_name = fu_provider_ebitdo_get_name; + provider_class->setup = fu_provider_ebitdo_setup; provider_class->coldplug = fu_provider_ebitdo_coldplug; provider_class->update_online = fu_provider_ebitdo_update; object_class->finalize = fu_provider_ebitdo_finalize; @@ -249,13 +264,6 @@ fu_provider_ebitdo_init (FuProviderEbitdo *provider_ebitdo) g_free, (GDestroyNotify) g_object_unref); priv->devices_runtime = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); - priv->usb_ctx = g_usb_context_new (NULL); - g_signal_connect (priv->usb_ctx, "device-added", - G_CALLBACK (fu_provider_ebitdo_device_added_cb), - provider_ebitdo); - g_signal_connect (priv->usb_ctx, "device-removed", - G_CALLBACK (fu_provider_ebitdo_device_removed_cb), - provider_ebitdo); } static void diff --git a/src/fu-provider-usb.c b/src/fu-provider-usb.c index c70e17b61..cf4015843 100644 --- a/src/fu-provider-usb.c +++ b/src/fu-provider-usb.c @@ -200,12 +200,26 @@ fu_provider_usb_device_removed_cb (GUsbContext *ctx, g_hash_table_remove (priv->devices, platform_id); } +static gboolean +fu_provider_usb_setup (FuProvider *provider, GError **error) +{ + FuProviderUsb *provider_usb = FU_PROVIDER_USB (provider); + FuProviderUsbPrivate *priv = GET_PRIVATE (provider_usb); + priv->usb_ctx = fu_provider_get_usb_context (provider); + g_signal_connect (priv->usb_ctx, "device-added", + G_CALLBACK (fu_provider_usb_device_added_cb), + provider_usb); + g_signal_connect (priv->usb_ctx, "device-removed", + G_CALLBACK (fu_provider_usb_device_removed_cb), + provider_usb); + return TRUE; +} + static gboolean fu_provider_usb_coldplug (FuProvider *provider, GError **error) { FuProviderUsb *provider_usb = FU_PROVIDER_USB (provider); FuProviderUsbPrivate *priv = GET_PRIVATE (provider_usb); - g_usb_context_enumerate (priv->usb_ctx); priv->done_enumerate = TRUE; return TRUE; } @@ -217,6 +231,7 @@ fu_provider_usb_class_init (FuProviderUsbClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); provider_class->get_name = fu_provider_usb_get_name; + provider_class->setup = fu_provider_usb_setup; provider_class->coldplug = fu_provider_usb_coldplug; object_class->finalize = fu_provider_usb_finalize; } @@ -227,13 +242,6 @@ fu_provider_usb_init (FuProviderUsb *provider_usb) FuProviderUsbPrivate *priv = GET_PRIVATE (provider_usb); priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); - priv->usb_ctx = g_usb_context_new (NULL); - g_signal_connect (priv->usb_ctx, "device-added", - G_CALLBACK (fu_provider_usb_device_added_cb), - provider_usb); - g_signal_connect (priv->usb_ctx, "device-removed", - G_CALLBACK (fu_provider_usb_device_removed_cb), - provider_usb); } static void diff --git a/src/fu-provider.c b/src/fu-provider.c index ef43ca72d..074f2d95e 100644 --- a/src/fu-provider.c +++ b/src/fu-provider.c @@ -34,6 +34,10 @@ #include "fu-plugin.h" #include "fu-provider-uefi.h" +typedef struct { + GUsbContext *usb_ctx; +} FuProviderPrivate; + static void fu_provider_finalize (GObject *object); enum { @@ -46,7 +50,8 @@ enum { static guint signals[SIGNAL_LAST] = { 0 }; -G_DEFINE_TYPE (FuProvider, fu_provider, G_TYPE_OBJECT) +G_DEFINE_TYPE_WITH_PRIVATE (FuProvider, fu_provider, G_TYPE_OBJECT) +#define GET_PRIVATE(o) (fu_provider_get_instance_private (o)) static gboolean fu_provider_offline_invalidate (GError **error) @@ -92,6 +97,15 @@ fu_provider_offline_setup (GError **error) return TRUE; } +gboolean +fu_provider_setup (FuProvider *provider, GError **error) +{ + FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider); + if (klass->setup != NULL) + return klass->setup (provider, error); + return TRUE; +} + gboolean fu_provider_coldplug (FuProvider *provider, GError **error) { @@ -425,6 +439,20 @@ fu_provider_get_checksum_type (FuProviderVerifyFlags flags) return G_CHECKSUM_SHA1; } +GUsbContext * +fu_provider_get_usb_context (FuProvider *provider) +{ + FuProviderPrivate *priv = GET_PRIVATE (provider); + return g_object_ref (priv->usb_ctx); +} + +void +fu_provider_set_usb_context (FuProvider *provider, GUsbContext *usb_ctx) +{ + FuProviderPrivate *priv = GET_PRIVATE (provider); + g_set_object (&priv->usb_ctx, usb_ctx); +} + static void fu_provider_class_init (FuProviderClass *klass) { @@ -464,5 +492,11 @@ fu_provider_init (FuProvider *provider) static void fu_provider_finalize (GObject *object) { + FuProvider *provider = FU_PROVIDER (object); + FuProviderPrivate *priv = GET_PRIVATE (provider); + + if (priv->usb_ctx != NULL) + g_object_unref (priv->usb_ctx); + G_OBJECT_CLASS (fu_provider_parent_class)->finalize (object); } diff --git a/src/fu-provider.h b/src/fu-provider.h index 57aa525b2..1e47a2615 100644 --- a/src/fu-provider.h +++ b/src/fu-provider.h @@ -23,6 +23,7 @@ #define __FU_PROVIDER_H #include +#include #include "fu-device.h" #include "fu-plugin.h" @@ -45,6 +46,8 @@ struct _FuProviderClass /* vfunc */ const gchar *(*get_name) (FuProvider *provider); + gboolean (*setup) (FuProvider *provider, + GError **error); gboolean (*coldplug) (FuProvider *provider, GError **error); gboolean (*verify) (FuProvider *provider, @@ -93,6 +96,8 @@ void fu_provider_set_status (FuProvider *provider, void fu_provider_set_percentage (FuProvider *provider, guint percentage); const gchar *fu_provider_get_name (FuProvider *provider); +gboolean fu_provider_setup (FuProvider *provider, + GError **error); gboolean fu_provider_coldplug (FuProvider *provider, GError **error); gboolean fu_provider_update (FuProvider *provider, @@ -117,6 +122,10 @@ gboolean fu_provider_get_results (FuProvider *provider, GError **error); GChecksumType fu_provider_get_checksum_type (FuProviderVerifyFlags flags); +GUsbContext *fu_provider_get_usb_context (FuProvider *provider); +void fu_provider_set_usb_context (FuProvider *provider, + GUsbContext *usb_ctx); + G_END_DECLS #endif /* __FU_PROVIDER_H */ diff --git a/src/plugins/fu-plugin-steelseries.c b/src/plugins/fu-plugin-steelseries.c index cbb8b86d9..cc5b8e168 100644 --- a/src/plugins/fu-plugin-steelseries.c +++ b/src/plugins/fu-plugin-steelseries.c @@ -49,7 +49,7 @@ fu_plugin_device_probe (FuPlugin *plugin, FuDevice *device, GError **error) /* get version */ platform_id = fu_device_get_id (device); - usb_ctx = g_usb_context_new (NULL); + usb_ctx = fu_plugin_get_usb_context (plugin); usb_device = g_usb_context_find_by_platform_id (usb_ctx, platform_id, error);