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.
This commit is contained in:
Richard Hughes 2016-12-08 17:29:51 +00:00
parent e34654e17f
commit bc93e4ab6e
13 changed files with 213 additions and 66 deletions

View File

@ -38,8 +38,6 @@
#include "config.h" #include "config.h"
#include <gusb.h>
#include "dfu-device-private.h" #include "dfu-device-private.h"
#include "dfu-error.h" #include "dfu-error.h"
#include "dfu-context.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); 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 static void
dfu_context_init (DfuContext *context) dfu_context_init (DfuContext *context)
{ {
DfuContextPrivate *priv = GET_PRIVATE (context); DfuContextPrivate *priv = GET_PRIVATE (context);
priv->timeout = 5000; priv->timeout = 5000;
priv->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) dfu_context_device_free); 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 static void
@ -324,7 +328,29 @@ DfuContext *
dfu_context_new (void) dfu_context_new (void)
{ {
DfuContext *context; DfuContext *context;
g_autoptr(GUsbContext) usb_ctx = g_usb_context_new (NULL);
context = g_object_new (DFU_TYPE_CONTEXT, 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; return context;
} }

View File

@ -24,6 +24,7 @@
#include <glib-object.h> #include <glib-object.h>
#include <gio/gio.h> #include <gio/gio.h>
#include <gusb.h>
#include "dfu-device.h" #include "dfu-device.h"
@ -55,6 +56,7 @@ struct _DfuContextClass
}; };
DfuContext *dfu_context_new (void); DfuContext *dfu_context_new (void);
DfuContext *dfu_context_new_with_context (GUsbContext *usb_ctx);
gboolean dfu_context_enumerate (DfuContext *context, gboolean dfu_context_enumerate (DfuContext *context,
GError **error); GError **error);
GPtrArray *dfu_context_get_devices (DfuContext *context); GPtrArray *dfu_context_get_devices (DfuContext *context);

View File

@ -71,6 +71,7 @@ typedef struct {
GDBusNodeInfo *introspection_daemon; GDBusNodeInfo *introspection_daemon;
GDBusProxy *proxy_uid; GDBusProxy *proxy_uid;
GDBusProxy *proxy_upower; GDBusProxy *proxy_upower;
GUsbContext *usb_ctx;
GKeyFile *config; GKeyFile *config;
GMainLoop *loop; GMainLoop *loop;
GPtrArray *devices; /* of FuDeviceItem */ GPtrArray *devices; /* of FuDeviceItem */
@ -260,7 +261,7 @@ fu_main_invocation_return_error (FuMainPrivate *priv,
} }
static gboolean static gboolean
fu_main_load_plugins (GHashTable *plugins, GError **error) fu_main_load_plugins (FuMainPrivate *priv, GError **error)
{ {
FuPlugin *plugin; FuPlugin *plugin;
GModule *module; GModule *module;
@ -296,13 +297,14 @@ fu_main_load_plugins (GHashTable *plugins, GError **error)
g_warning ("plugin %s requires name", filename); g_warning ("plugin %s requires name", filename);
continue; continue;
} }
fu_plugin_set_usb_context (plugin, priv->usb_ctx);
/* add */ /* 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 */ /* 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) { for (GList *l = values; l != NULL; l = l->next) {
plugin = FU_PLUGIN (l->data); plugin = FU_PLUGIN (l->data);
if (!fu_plugin_run_startup (plugin, error)) if (!fu_plugin_run_startup (plugin, error))
@ -2138,6 +2140,24 @@ fu_main_daemon_get_property (GDBusConnection *connection_, const gchar *sender,
return NULL; 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 static void
fu_main_providers_coldplug (FuMainPrivate *priv) fu_main_providers_coldplug (FuMainPrivate *priv)
{ {
@ -2181,6 +2201,8 @@ fu_main_on_bus_acquired_cb (GDBusConnection *connection,
g_assert (registration_id > 0); g_assert (registration_id > 0);
/* add devices */ /* add devices */
fu_main_providers_setup (priv);
g_usb_context_enumerate (priv->usb_ctx);
fu_main_providers_coldplug (priv); fu_main_providers_coldplug (priv);
/* connect to D-Bus directly */ /* connect to D-Bus directly */
@ -2471,7 +2493,7 @@ main (int argc, char *argv[])
/* load plugin */ /* load plugin */
priv->plugins = g_hash_table_new_full (g_str_hash, g_str_equal, priv->plugins = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) fu_plugin_free); 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); g_print ("failed to load plugins: %s\n", error->message);
retval = EXIT_FAILURE; retval = EXIT_FAILURE;
goto out; goto out;
@ -2519,6 +2541,18 @@ main (int argc, char *argv[])
/* last as least priority */ /* last as least priority */
fu_main_add_provider (priv, fu_provider_usb_new ()); 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 */ /* load introspection from file */
priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml", priv->introspection_daemon = fu_main_load_introspection (FWUPD_DBUS_INTERFACE ".xml",
&error); &error);
@ -2570,6 +2604,8 @@ out:
g_object_unref (priv->proxy_uid); g_object_unref (priv->proxy_uid);
if (priv->proxy_upower != NULL) if (priv->proxy_upower != NULL)
g_object_unref (priv->proxy_upower); g_object_unref (priv->proxy_upower);
if (priv->usb_ctx != NULL)
g_object_unref (priv->usb_ctx);
if (priv->config != NULL) if (priv->config != NULL)
g_key_file_unref (priv->config); g_key_file_unref (priv->config);
if (priv->connection != NULL) if (priv->connection != NULL)

View File

@ -56,6 +56,18 @@ fu_plugin_new (GModule *module)
return plugin; 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 void
fu_plugin_free (FuPlugin *plugin) fu_plugin_free (FuPlugin *plugin)
{ {
@ -69,6 +81,8 @@ fu_plugin_free (FuPlugin *plugin)
} }
/* deallocate */ /* deallocate */
if (plugin->usb_ctx != NULL)
g_object_unref (plugin->usb_ctx);
g_module_close (plugin->module); g_module_close (plugin->module);
g_free (plugin->name); g_free (plugin->name);
g_free (plugin->priv); g_free (plugin->priv);

View File

@ -24,6 +24,7 @@
#include <glib-object.h> #include <glib-object.h>
#include <gmodule.h> #include <gmodule.h>
#include <gusb.h>
#include "fu-device.h" #include "fu-device.h"
@ -34,6 +35,7 @@ typedef struct FuPlugin FuPlugin;
struct FuPlugin { struct FuPlugin {
GModule *module; GModule *module;
GUsbContext *usb_ctx;
gboolean enabled; gboolean enabled;
gchar *name; gchar *name;
FuPluginPrivate *priv; FuPluginPrivate *priv;
@ -80,6 +82,9 @@ gboolean fu_plugin_run_device_update (FuPlugin *plugin,
FuDevice *device, FuDevice *device,
GBytes *data, GBytes *data,
GError **error); GError **error);
GUsbContext *fu_plugin_get_usb_context (FuPlugin *plugin);
void fu_plugin_set_usb_context (FuPlugin *plugin,
GUsbContext *usb_ctx);
G_END_DECLS G_END_DECLS

View File

@ -541,11 +541,17 @@ fu_provider_chug_device_removed_cb (GUsbContext *ctx,
} }
static gboolean 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); FuProviderChug *provider_chug = FU_PROVIDER_CHUG (provider);
FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug); 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; return TRUE;
} }
@ -556,7 +562,7 @@ fu_provider_chug_class_init (FuProviderChugClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
provider_class->get_name = fu_provider_chug_get_name; 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->update_online = fu_provider_chug_update;
provider_class->verify = fu_provider_chug_verify; provider_class->verify = fu_provider_chug_verify;
object_class->finalize = fu_provider_chug_finalize; object_class->finalize = fu_provider_chug_finalize;
@ -568,14 +574,7 @@ fu_provider_chug_init (FuProviderChug *provider_chug)
FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug); FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug);
priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) fu_provider_chug_device_free); g_free, (GDestroyNotify) fu_provider_chug_device_free);
priv->usb_ctx = g_usb_context_new (NULL);
priv->device_queue = ch_device_queue_new (); 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 static void

View File

@ -877,7 +877,7 @@ fu_provider_dell_detect_tpm (FuProvider *provider, GError **error)
} }
static gboolean 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); FuProviderDell *provider_dell = FU_PROVIDER_DELL (provider);
FuProviderDellPrivate *priv = GET_PRIVATE (provider_dell); FuProviderDellPrivate *priv = GET_PRIVATE (provider_dell);
@ -885,6 +885,15 @@ fu_provider_dell_coldplug (FuProvider *provider, GError **error)
gint uefi_supported = 0; gint uefi_supported = 0;
struct smbios_struct *de_table; 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) { if (priv->fake_smbios) {
g_debug ("Dell: called with fake SMBIOS implementation. " g_debug ("Dell: called with fake SMBIOS implementation. "
"We're ignoring test for SBMIOS table and ESRT. " "We're ignoring test for SBMIOS table and ESRT. "
@ -924,14 +933,15 @@ fu_provider_dell_coldplug (FuProvider *provider, GError **error)
return FALSE; return FALSE;
} }
return TRUE;
}
/* enumerate looking for a connected dock */ static gboolean
g_usb_context_enumerate (priv->usb_ctx); fu_provider_dell_coldplug (FuProvider *provider, GError **error)
{
/* look for switchable TPM */ /* look for switchable TPM */
if (!fu_provider_dell_detect_tpm (provider, error)) if (!fu_provider_dell_detect_tpm (provider, error))
g_debug ("Dell: No switchable TPM detected"); g_debug ("Dell: No switchable TPM detected");
return TRUE; return TRUE;
} }
@ -1009,7 +1019,7 @@ fu_provider_dell_update_offline (FuProvider *provider,
#endif #endif
/* test the flash counter /* 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 * - devices greater than 0 should show a warning when near 0
*/ */
flashes_left = fu_device_get_flashes_left (device); 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); GObjectClass *object_class = G_OBJECT_CLASS (klass);
provider_class->get_name = fu_provider_dell_get_name; 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->coldplug = fu_provider_dell_coldplug;
provider_class->unlock = fu_provider_dell_unlock; provider_class->unlock = fu_provider_dell_unlock;
provider_class->update_offline = fu_provider_dell_update_offline; 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, priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) fu_provider_dell_device_free); 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; priv->fake_smbios = FALSE;
if (g_getenv ("FWUPD_DELL_FAKE_SMBIOS") != NULL) if (g_getenv ("FWUPD_DELL_FAKE_SMBIOS") != NULL)
priv->fake_smbios = TRUE; priv->fake_smbios = TRUE;
@ -1244,7 +1248,8 @@ fu_provider_dell_finalize (GObject *object)
FuProviderDellPrivate *priv = GET_PRIVATE (provider_dell); FuProviderDellPrivate *priv = GET_PRIVATE (provider_dell);
g_hash_table_unref (priv->devices); 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); G_OBJECT_CLASS (fu_provider_dell_parent_class)->finalize (object);
} }

View File

@ -205,11 +205,22 @@ fu_provider_dfu_device_removed_cb (DfuContext *ctx,
} }
static gboolean 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); FuProviderDfu *provider_dfu = FU_PROVIDER_DFU (provider);
FuProviderDfuPrivate *priv = GET_PRIVATE (provider_dfu); 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; return TRUE;
} }
@ -391,7 +402,7 @@ fu_provider_dfu_class_init (FuProviderDfuClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
provider_class->get_name = fu_provider_dfu_get_name; 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->update_online = fu_provider_dfu_update;
provider_class->verify = fu_provider_dfu_verify; provider_class->verify = fu_provider_dfu_verify;
object_class->finalize = fu_provider_dfu_finalize; object_class->finalize = fu_provider_dfu_finalize;
@ -403,16 +414,6 @@ fu_provider_dfu_init (FuProviderDfu *provider_dfu)
FuProviderDfuPrivate *priv = GET_PRIVATE (provider_dfu); FuProviderDfuPrivate *priv = GET_PRIVATE (provider_dfu);
priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) g_object_unref); 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 static void

View File

@ -219,12 +219,26 @@ fu_provider_ebitdo_device_removed_cb (GUsbContext *ctx,
g_hash_table_remove (priv->devices, platform_id); 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 static gboolean
fu_provider_ebitdo_coldplug (FuProvider *provider, GError **error) fu_provider_ebitdo_coldplug (FuProvider *provider, GError **error)
{ {
FuProviderEbitdo *provider_ebitdo = FU_PROVIDER_EBITDO (provider); FuProviderEbitdo *provider_ebitdo = FU_PROVIDER_EBITDO (provider);
FuProviderEbitdoPrivate *priv = GET_PRIVATE (provider_ebitdo); FuProviderEbitdoPrivate *priv = GET_PRIVATE (provider_ebitdo);
g_usb_context_enumerate (priv->usb_ctx);
priv->done_enumerate = TRUE; priv->done_enumerate = TRUE;
return TRUE; return TRUE;
} }
@ -236,6 +250,7 @@ fu_provider_ebitdo_class_init (FuProviderEbitdoClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
provider_class->get_name = fu_provider_ebitdo_get_name; 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->coldplug = fu_provider_ebitdo_coldplug;
provider_class->update_online = fu_provider_ebitdo_update; provider_class->update_online = fu_provider_ebitdo_update;
object_class->finalize = fu_provider_ebitdo_finalize; object_class->finalize = fu_provider_ebitdo_finalize;
@ -249,13 +264,6 @@ fu_provider_ebitdo_init (FuProviderEbitdo *provider_ebitdo)
g_free, (GDestroyNotify) g_object_unref); g_free, (GDestroyNotify) g_object_unref);
priv->devices_runtime = g_hash_table_new_full (g_str_hash, g_str_equal, priv->devices_runtime = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) g_object_unref); 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 static void

View File

@ -200,12 +200,26 @@ fu_provider_usb_device_removed_cb (GUsbContext *ctx,
g_hash_table_remove (priv->devices, platform_id); 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 static gboolean
fu_provider_usb_coldplug (FuProvider *provider, GError **error) fu_provider_usb_coldplug (FuProvider *provider, GError **error)
{ {
FuProviderUsb *provider_usb = FU_PROVIDER_USB (provider); FuProviderUsb *provider_usb = FU_PROVIDER_USB (provider);
FuProviderUsbPrivate *priv = GET_PRIVATE (provider_usb); FuProviderUsbPrivate *priv = GET_PRIVATE (provider_usb);
g_usb_context_enumerate (priv->usb_ctx);
priv->done_enumerate = TRUE; priv->done_enumerate = TRUE;
return TRUE; return TRUE;
} }
@ -217,6 +231,7 @@ fu_provider_usb_class_init (FuProviderUsbClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
provider_class->get_name = fu_provider_usb_get_name; provider_class->get_name = fu_provider_usb_get_name;
provider_class->setup = fu_provider_usb_setup;
provider_class->coldplug = fu_provider_usb_coldplug; provider_class->coldplug = fu_provider_usb_coldplug;
object_class->finalize = fu_provider_usb_finalize; object_class->finalize = fu_provider_usb_finalize;
} }
@ -227,13 +242,6 @@ fu_provider_usb_init (FuProviderUsb *provider_usb)
FuProviderUsbPrivate *priv = GET_PRIVATE (provider_usb); FuProviderUsbPrivate *priv = GET_PRIVATE (provider_usb);
priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) g_object_unref); 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 static void

View File

@ -34,6 +34,10 @@
#include "fu-plugin.h" #include "fu-plugin.h"
#include "fu-provider-uefi.h" #include "fu-provider-uefi.h"
typedef struct {
GUsbContext *usb_ctx;
} FuProviderPrivate;
static void fu_provider_finalize (GObject *object); static void fu_provider_finalize (GObject *object);
enum { enum {
@ -46,7 +50,8 @@ enum {
static guint signals[SIGNAL_LAST] = { 0 }; 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 static gboolean
fu_provider_offline_invalidate (GError **error) fu_provider_offline_invalidate (GError **error)
@ -92,6 +97,15 @@ fu_provider_offline_setup (GError **error)
return TRUE; 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 gboolean
fu_provider_coldplug (FuProvider *provider, GError **error) fu_provider_coldplug (FuProvider *provider, GError **error)
{ {
@ -425,6 +439,20 @@ fu_provider_get_checksum_type (FuProviderVerifyFlags flags)
return G_CHECKSUM_SHA1; 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 static void
fu_provider_class_init (FuProviderClass *klass) fu_provider_class_init (FuProviderClass *klass)
{ {
@ -464,5 +492,11 @@ fu_provider_init (FuProvider *provider)
static void static void
fu_provider_finalize (GObject *object) 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); G_OBJECT_CLASS (fu_provider_parent_class)->finalize (object);
} }

View File

@ -23,6 +23,7 @@
#define __FU_PROVIDER_H #define __FU_PROVIDER_H
#include <glib-object.h> #include <glib-object.h>
#include <gusb.h>
#include "fu-device.h" #include "fu-device.h"
#include "fu-plugin.h" #include "fu-plugin.h"
@ -45,6 +46,8 @@ struct _FuProviderClass
/* vfunc */ /* vfunc */
const gchar *(*get_name) (FuProvider *provider); const gchar *(*get_name) (FuProvider *provider);
gboolean (*setup) (FuProvider *provider,
GError **error);
gboolean (*coldplug) (FuProvider *provider, gboolean (*coldplug) (FuProvider *provider,
GError **error); GError **error);
gboolean (*verify) (FuProvider *provider, gboolean (*verify) (FuProvider *provider,
@ -93,6 +96,8 @@ void fu_provider_set_status (FuProvider *provider,
void fu_provider_set_percentage (FuProvider *provider, void fu_provider_set_percentage (FuProvider *provider,
guint percentage); guint percentage);
const gchar *fu_provider_get_name (FuProvider *provider); const gchar *fu_provider_get_name (FuProvider *provider);
gboolean fu_provider_setup (FuProvider *provider,
GError **error);
gboolean fu_provider_coldplug (FuProvider *provider, gboolean fu_provider_coldplug (FuProvider *provider,
GError **error); GError **error);
gboolean fu_provider_update (FuProvider *provider, gboolean fu_provider_update (FuProvider *provider,
@ -117,6 +122,10 @@ gboolean fu_provider_get_results (FuProvider *provider,
GError **error); GError **error);
GChecksumType fu_provider_get_checksum_type (FuProviderVerifyFlags flags); 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 G_END_DECLS
#endif /* __FU_PROVIDER_H */ #endif /* __FU_PROVIDER_H */

View File

@ -49,7 +49,7 @@ fu_plugin_device_probe (FuPlugin *plugin, FuDevice *device, GError **error)
/* get version */ /* get version */
platform_id = fu_device_get_id (device); 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, usb_device = g_usb_context_find_by_platform_id (usb_ctx,
platform_id, platform_id,
error); error);