blob: c8768f2bae0681a24272048dce3486b37f541a7e [file] [log] [blame]
Richard Hughes02c90d82018-08-09 12:13:03 +01001/*
Richard Hughes2de8f132018-01-17 09:12:02 +00002 * Copyright (C) 2016-2018 Richard Hughes <richard@hughsie.com>
Richard Hughesd0905142016-03-13 09:46:49 +00003 *
Mario Limonciello51308e62018-05-28 20:05:46 -05004 * SPDX-License-Identifier: LGPL-2.1+
Richard Hughesd0905142016-03-13 09:46:49 +00005 */
6
Richard Hughesb08e7bc2018-09-11 10:51:13 +01007#define G_LOG_DOMAIN "FuPlugin"
8
Richard Hughesd0905142016-03-13 09:46:49 +00009#include "config.h"
10
Richard Hughescff38bc2016-12-12 12:03:37 +000011#include <fwupd.h>
12#include <gmodule.h>
Richard Hughescff38bc2016-12-12 12:03:37 +000013#include <errno.h>
14#include <string.h>
Richard Hughes68f12dd2018-08-09 14:43:31 +010015#include <unistd.h>
Mario Limonciello6d0aa3d2017-02-28 08:22:27 -060016#ifdef HAVE_VALGRIND
Richard Hughes576c0122017-02-24 09:47:00 +000017#include <valgrind.h>
Mario Limonciello6d0aa3d2017-02-28 08:22:27 -060018#endif /* HAVE_VALGRIND */
Richard Hughesd0905142016-03-13 09:46:49 +000019
Richard Hughes9dde04f2017-09-13 12:07:15 +010020#include "fu-device-private.h"
Richard Hughescff38bc2016-12-12 12:03:37 +000021#include "fu-plugin-private.h"
Richard Hughes37d09432018-09-09 10:39:45 +010022#include "fu-mutex.h"
Richard Hughesd0905142016-03-13 09:46:49 +000023
Richard Hughes4eada342017-10-03 21:20:32 +010024/**
25 * SECTION:fu-plugin
26 * @short_description: a daemon plugin
27 *
28 * An object that represents a plugin run by the daemon.
29 *
30 * See also: #FuDevice
31 */
32
Richard Hughesb0829032017-01-10 09:27:08 +000033#define FU_PLUGIN_COLDPLUG_DELAY_MAXIMUM 3000u /* ms */
34
Richard Hughescff38bc2016-12-12 12:03:37 +000035static void fu_plugin_finalize (GObject *object);
36
37typedef struct {
38 GModule *module;
39 GUsbContext *usb_ctx;
Richard Hughes08a37992017-09-12 12:57:43 +010040 guint order;
Richard Hughes81c427c2018-08-06 15:20:17 +010041 guint priority;
Richard Hughes08a37992017-09-12 12:57:43 +010042 GPtrArray *rules[FU_PLUGIN_RULE_LAST];
Richard Hughesf425d292019-01-18 17:57:39 +000043 gchar *build_hash;
Richard Hughesd7704d42017-08-08 20:29:09 +010044 FuHwids *hwids;
Richard Hughes9c028f02017-10-28 21:14:28 +010045 FuQuirks *quirks;
Richard Hughes0eb123b2018-04-19 12:00:04 +010046 GHashTable *runtime_versions;
Richard Hughes34e0dab2018-04-20 16:43:00 +010047 GHashTable *compile_versions;
Richard Hughes9d6e0e72018-08-24 20:20:17 +010048 GPtrArray *udev_subsystems;
Richard Hughes1354ea92017-09-19 15:58:31 +010049 FuSmbios *smbios;
Richard Hughes989acf12019-10-05 20:16:47 +010050 GType device_gtype;
Richard Hughes371f6b22020-06-22 15:21:17 +010051 GHashTable *devices; /* (nullable): platform_id:GObject */
Richard Hughes161e9b52019-06-12 14:22:45 +010052 GRWLock devices_mutex;
Richard Hughes1d900f72020-06-22 15:17:39 +010053 GHashTable *report_metadata; /* (nullable): key:value */
Richard Hughescff38bc2016-12-12 12:03:37 +000054 FuPluginData *data;
55} FuPluginPrivate;
56
57enum {
58 SIGNAL_DEVICE_ADDED,
59 SIGNAL_DEVICE_REMOVED,
Richard Hughese1fd34d2017-08-24 14:19:51 +010060 SIGNAL_DEVICE_REGISTER,
Richard Hughes75b965d2018-11-15 13:51:21 +000061 SIGNAL_RULES_CHANGED,
Richard Hughes362d6d72017-01-07 21:42:14 +000062 SIGNAL_RECOLDPLUG,
Richard Hughesb0829032017-01-10 09:27:08 +000063 SIGNAL_SET_COLDPLUG_DELAY,
Richard Hughesaabdc372018-11-14 10:11:08 +000064 SIGNAL_CHECK_SUPPORTED,
Richard Hughes95c98a92019-10-22 16:03:15 +010065 SIGNAL_ADD_FIRMWARE_GTYPE,
Richard Hughes399859e2020-05-11 19:44:03 +010066 SIGNAL_SECURITY_CHANGED,
Richard Hughescff38bc2016-12-12 12:03:37 +000067 SIGNAL_LAST
68};
69
70static guint signals[SIGNAL_LAST] = { 0 };
71
Richard Hughes7bcb8d42020-10-08 15:47:47 +010072G_DEFINE_TYPE_WITH_PRIVATE (FuPlugin, fu_plugin, FWUPD_TYPE_PLUGIN)
Richard Hughescff38bc2016-12-12 12:03:37 +000073#define GET_PRIVATE(o) (fu_plugin_get_instance_private (o))
74
75typedef const gchar *(*FuPluginGetNameFunc) (void);
Richard Hughes12724852018-09-04 13:53:44 +010076typedef void (*FuPluginInitFunc) (FuPlugin *self);
77typedef gboolean (*FuPluginStartupFunc) (FuPlugin *self,
Richard Hughescff38bc2016-12-12 12:03:37 +000078 GError **error);
Richard Hughes12724852018-09-04 13:53:44 +010079typedef void (*FuPluginDeviceRegisterFunc) (FuPlugin *self,
Richard Hughese1fd34d2017-08-24 14:19:51 +010080 FuDevice *device);
Richard Hughes12724852018-09-04 13:53:44 +010081typedef gboolean (*FuPluginDeviceFunc) (FuPlugin *self,
Richard Hughescff38bc2016-12-12 12:03:37 +000082 FuDevice *device,
83 GError **error);
Richard Hughes12724852018-09-04 13:53:44 +010084typedef gboolean (*FuPluginFlaggedDeviceFunc) (FuPlugin *self,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -050085 FwupdInstallFlags flags,
86 FuDevice *device,
87 GError **error);
Richard Hughes12724852018-09-04 13:53:44 +010088typedef gboolean (*FuPluginDeviceArrayFunc) (FuPlugin *self,
Richard Hughesdbd8c762018-06-15 20:31:40 +010089 GPtrArray *devices,
90 GError **error);
Richard Hughes12724852018-09-04 13:53:44 +010091typedef gboolean (*FuPluginVerifyFunc) (FuPlugin *self,
Richard Hughescff38bc2016-12-12 12:03:37 +000092 FuDevice *device,
93 FuPluginVerifyFlags flags,
94 GError **error);
Richard Hughes12724852018-09-04 13:53:44 +010095typedef gboolean (*FuPluginUpdateFunc) (FuPlugin *self,
Richard Hughescff38bc2016-12-12 12:03:37 +000096 FuDevice *device,
97 GBytes *blob_fw,
98 FwupdInstallFlags flags,
99 GError **error);
Richard Hughes12724852018-09-04 13:53:44 +0100100typedef gboolean (*FuPluginUsbDeviceAddedFunc) (FuPlugin *self,
Richard Hughesff704412018-09-04 11:28:32 +0100101 FuUsbDevice *device,
Richard Hughes104f6512017-11-24 11:44:57 +0000102 GError **error);
Richard Hughes12724852018-09-04 13:53:44 +0100103typedef gboolean (*FuPluginUdevDeviceAddedFunc) (FuPlugin *self,
Richard Hughesff704412018-09-04 11:28:32 +0100104 FuUdevDevice *device,
Richard Hughes9d6e0e72018-08-24 20:20:17 +0100105 GError **error);
Richard Hughesf58ac732020-05-12 15:23:44 +0100106typedef void (*FuPluginSecurityAttrsFunc) (FuPlugin *self,
107 FuSecurityAttrs *attrs);
Richard Hughescff38bc2016-12-12 12:03:37 +0000108
Richard Hughes57d18222017-01-10 16:02:59 +0000109/**
Mario Limonciello52e75ba2019-11-22 13:21:19 -0600110 * fu_plugin_is_open:
111 * @self: A #FuPlugin
112 *
113 * Determines if the plugin is opened
114 *
115 * Returns: TRUE for opened, FALSE for not
116 *
117 * Since: 1.3.5
118 **/
119gboolean
120fu_plugin_is_open (FuPlugin *self)
121{
122 FuPluginPrivate *priv = GET_PRIVATE (self);
123 return priv->module != NULL;
124}
125
126/**
Richard Hughes57d18222017-01-10 16:02:59 +0000127 * fu_plugin_get_name:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100128 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000129 *
130 * Gets the plugin name.
131 *
132 * Returns: a plugin name, or %NULL for unknown.
133 *
134 * Since: 0.8.0
135 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000136const gchar *
Richard Hughes12724852018-09-04 13:53:44 +0100137fu_plugin_get_name (FuPlugin *self)
Richard Hughesd0905142016-03-13 09:46:49 +0000138{
Richard Hughes12724852018-09-04 13:53:44 +0100139 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100140 return fwupd_plugin_get_name (FWUPD_PLUGIN (self));
Richard Hughescff38bc2016-12-12 12:03:37 +0000141}
Richard Hughesd0905142016-03-13 09:46:49 +0000142
Mario Limonciello1a680f32019-11-25 19:44:53 -0600143/**
144 * fu_plugin_set_name:
145 * @self: A #FuPlugin
146 * @name: A string
147 *
148 * Sets the plugin name.
149 *
150 * Since: 0.8.0
151 **/
Richard Hughes34834102017-11-21 21:55:00 +0000152void
Richard Hughes12724852018-09-04 13:53:44 +0100153fu_plugin_set_name (FuPlugin *self, const gchar *name)
Richard Hughes34834102017-11-21 21:55:00 +0000154{
Richard Hughes12724852018-09-04 13:53:44 +0100155 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100156 fwupd_plugin_set_name (FWUPD_PLUGIN (self), name);
Richard Hughes34834102017-11-21 21:55:00 +0000157}
158
Richard Hughes57d18222017-01-10 16:02:59 +0000159/**
Richard Hughesf425d292019-01-18 17:57:39 +0000160 * fu_plugin_set_build_hash:
161 * @self: A #FuPlugin
162 * @build_hash: A checksum
163 *
164 * Sets the plugin build hash, typically a SHA256 checksum. All plugins must
165 * set the correct checksum to avoid the daemon being marked as tainted.
166 *
167 * Since: 1.2.4
168 **/
169void
170fu_plugin_set_build_hash (FuPlugin *self, const gchar *build_hash)
171{
172 FuPluginPrivate *priv = GET_PRIVATE (self);
173 g_return_if_fail (FU_IS_PLUGIN (self));
174 g_return_if_fail (build_hash != NULL);
175 g_free (priv->build_hash);
176 priv->build_hash = g_strdup (build_hash);
177}
178
Mario Limonciello1a680f32019-11-25 19:44:53 -0600179/**
180 * fu_plugin_get_build_hash:
181 * @self: A #FuPlugin
182 *
183 * Gets the build hash a plugin was generated with.
184 *
185 * Returns: (transfer none): a #gchar, or %NULL for unset.
186 *
187 * Since: 1.2.4
188 **/
Richard Hughesf425d292019-01-18 17:57:39 +0000189const gchar *
190fu_plugin_get_build_hash (FuPlugin *self)
191{
192 FuPluginPrivate *priv = GET_PRIVATE (self);
193 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
194 return priv->build_hash;
195}
196
197/**
Richard Hughes57d18222017-01-10 16:02:59 +0000198 * fu_plugin_cache_lookup:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100199 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000200 * @id: the key
201 *
202 * Finds an object in the per-plugin cache.
203 *
204 * Returns: (transfer none): a #GObject, or %NULL for unfound.
205 *
206 * Since: 0.8.0
207 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000208gpointer
Richard Hughes12724852018-09-04 13:53:44 +0100209fu_plugin_cache_lookup (FuPlugin *self, const gchar *id)
Richard Hughescff38bc2016-12-12 12:03:37 +0000210{
Richard Hughes12724852018-09-04 13:53:44 +0100211 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes161e9b52019-06-12 14:22:45 +0100212 g_autoptr(GRWLockReaderLocker) locker = g_rw_lock_reader_locker_new (&priv->devices_mutex);
Richard Hughes12724852018-09-04 13:53:44 +0100213 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughesccd78a92017-01-11 16:57:41 +0000214 g_return_val_if_fail (id != NULL, NULL);
Richard Hughes37d09432018-09-09 10:39:45 +0100215 g_return_val_if_fail (locker != NULL, NULL);
Richard Hughes371f6b22020-06-22 15:21:17 +0100216 if (priv->devices == NULL)
217 return NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +0000218 return g_hash_table_lookup (priv->devices, id);
219}
Richard Hughesd0905142016-03-13 09:46:49 +0000220
Richard Hughes57d18222017-01-10 16:02:59 +0000221/**
222 * fu_plugin_cache_add:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100223 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000224 * @id: the key
225 * @dev: a #GObject, typically a #FuDevice
226 *
227 * Adds an object to the per-plugin cache.
228 *
229 * Since: 0.8.0
230 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000231void
Richard Hughes12724852018-09-04 13:53:44 +0100232fu_plugin_cache_add (FuPlugin *self, const gchar *id, gpointer dev)
Richard Hughescff38bc2016-12-12 12:03:37 +0000233{
Richard Hughes12724852018-09-04 13:53:44 +0100234 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes0fe49142019-11-22 16:56:38 +0000235 g_autoptr(GRWLockWriterLocker) locker = g_rw_lock_writer_locker_new (&priv->devices_mutex);
Richard Hughes12724852018-09-04 13:53:44 +0100236 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughesccd78a92017-01-11 16:57:41 +0000237 g_return_if_fail (id != NULL);
Richard Hughes37d09432018-09-09 10:39:45 +0100238 g_return_if_fail (locker != NULL);
Richard Hughes371f6b22020-06-22 15:21:17 +0100239 if (priv->devices == NULL) {
240 priv->devices = g_hash_table_new_full (g_str_hash,
241 g_str_equal,
242 g_free,
243 (GDestroyNotify) g_object_unref);
244 }
Richard Hughescff38bc2016-12-12 12:03:37 +0000245 g_hash_table_insert (priv->devices, g_strdup (id), g_object_ref (dev));
246}
247
Richard Hughes57d18222017-01-10 16:02:59 +0000248/**
249 * fu_plugin_cache_remove:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100250 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000251 * @id: the key
252 *
253 * Removes an object from the per-plugin cache.
254 *
255 * Since: 0.8.0
256 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000257void
Richard Hughes12724852018-09-04 13:53:44 +0100258fu_plugin_cache_remove (FuPlugin *self, const gchar *id)
Richard Hughescff38bc2016-12-12 12:03:37 +0000259{
Richard Hughes12724852018-09-04 13:53:44 +0100260 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes0fe49142019-11-22 16:56:38 +0000261 g_autoptr(GRWLockWriterLocker) locker = g_rw_lock_writer_locker_new (&priv->devices_mutex);
Richard Hughes12724852018-09-04 13:53:44 +0100262 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughesccd78a92017-01-11 16:57:41 +0000263 g_return_if_fail (id != NULL);
Richard Hughes37d09432018-09-09 10:39:45 +0100264 g_return_if_fail (locker != NULL);
Richard Hughes371f6b22020-06-22 15:21:17 +0100265 if (priv->devices == NULL)
266 return;
Richard Hughescff38bc2016-12-12 12:03:37 +0000267 g_hash_table_remove (priv->devices, id);
268}
269
Richard Hughes57d18222017-01-10 16:02:59 +0000270/**
271 * fu_plugin_get_data:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100272 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000273 *
Richard Hughes4eada342017-10-03 21:20:32 +0100274 * Gets the per-plugin allocated private data. This will return %NULL unless
275 * fu_plugin_alloc_data() has been called by the plugin.
Richard Hughes57d18222017-01-10 16:02:59 +0000276 *
Richard Hughes4eada342017-10-03 21:20:32 +0100277 * Returns: (transfer none): a pointer to a structure, or %NULL for unset.
Richard Hughes57d18222017-01-10 16:02:59 +0000278 *
279 * Since: 0.8.0
280 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000281FuPluginData *
Richard Hughes12724852018-09-04 13:53:44 +0100282fu_plugin_get_data (FuPlugin *self)
Richard Hughescff38bc2016-12-12 12:03:37 +0000283{
Richard Hughes12724852018-09-04 13:53:44 +0100284 FuPluginPrivate *priv = GET_PRIVATE (self);
285 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughescff38bc2016-12-12 12:03:37 +0000286 return priv->data;
287}
288
Richard Hughes57d18222017-01-10 16:02:59 +0000289/**
Richard Hughes00f66f62019-11-27 11:42:53 +0000290 * fu_plugin_alloc_data: (skip):
Richard Hughes2c0635a2018-09-04 14:52:46 +0100291 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000292 * @data_sz: the size to allocate
293 *
294 * Allocates the per-plugin allocated private data.
295 *
296 * Returns: (transfer full): a pointer to a structure, or %NULL for unset.
297 *
298 * Since: 0.8.0
299 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000300FuPluginData *
Richard Hughes12724852018-09-04 13:53:44 +0100301fu_plugin_alloc_data (FuPlugin *self, gsize data_sz)
Richard Hughescff38bc2016-12-12 12:03:37 +0000302{
Richard Hughes12724852018-09-04 13:53:44 +0100303 FuPluginPrivate *priv = GET_PRIVATE (self);
304 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughes44dee882017-01-11 08:31:10 +0000305 if (priv->data != NULL) {
306 g_critical ("fu_plugin_alloc_data() already used by plugin");
307 return priv->data;
308 }
Richard Hughescff38bc2016-12-12 12:03:37 +0000309 priv->data = g_malloc0 (data_sz);
310 return priv->data;
Richard Hughesd0905142016-03-13 09:46:49 +0000311}
312
Richard Hughes57d18222017-01-10 16:02:59 +0000313/**
314 * fu_plugin_get_usb_context:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100315 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000316 *
317 * Gets the shared USB context that all plugins can use.
318 *
319 * Returns: (transfer none): a #GUsbContext.
320 *
321 * Since: 0.8.0
322 **/
Richard Hughesbc93e4a2016-12-08 17:29:51 +0000323GUsbContext *
Richard Hughes12724852018-09-04 13:53:44 +0100324fu_plugin_get_usb_context (FuPlugin *self)
Richard Hughesbc93e4a2016-12-08 17:29:51 +0000325{
Richard Hughes12724852018-09-04 13:53:44 +0100326 FuPluginPrivate *priv = GET_PRIVATE (self);
327 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughescff38bc2016-12-12 12:03:37 +0000328 return priv->usb_ctx;
Richard Hughesbc93e4a2016-12-08 17:29:51 +0000329}
330
Mario Limonciello1a680f32019-11-25 19:44:53 -0600331/**
332 * fu_plugin_set_usb_context:
333 * @self: A #FuPlugin
334 * @usb_ctx: A #FGUsbContext
335 *
336 * Sets the shared USB context for a plugin
337 *
338 * Since: 0.8.0
339 **/
Richard Hughesbc93e4a2016-12-08 17:29:51 +0000340void
Richard Hughes12724852018-09-04 13:53:44 +0100341fu_plugin_set_usb_context (FuPlugin *self, GUsbContext *usb_ctx)
Richard Hughesbc93e4a2016-12-08 17:29:51 +0000342{
Richard Hughes12724852018-09-04 13:53:44 +0100343 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughescff38bc2016-12-12 12:03:37 +0000344 g_set_object (&priv->usb_ctx, usb_ctx);
345}
346
Richard Hughes57d18222017-01-10 16:02:59 +0000347/**
348 * fu_plugin_get_enabled:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100349 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000350 *
Richard Hughes4eada342017-10-03 21:20:32 +0100351 * Returns if the plugin is enabled. Plugins may self-disable using
352 * fu_plugin_set_enabled() or can be disabled by the daemon.
Richard Hughes57d18222017-01-10 16:02:59 +0000353 *
354 * Returns: %TRUE if the plugin is currently enabled.
355 *
356 * Since: 0.8.0
357 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000358gboolean
Richard Hughes12724852018-09-04 13:53:44 +0100359fu_plugin_get_enabled (FuPlugin *self)
Richard Hughescff38bc2016-12-12 12:03:37 +0000360{
Richard Hughes12724852018-09-04 13:53:44 +0100361 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100362 return !fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED);
Richard Hughesbc93e4a2016-12-08 17:29:51 +0000363}
364
Richard Hughes57d18222017-01-10 16:02:59 +0000365/**
366 * fu_plugin_set_enabled:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100367 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000368 * @enabled: the enabled value
369 *
370 * Enables or disables a plugin. Plugins can self-disable at any point.
371 *
372 * Since: 0.8.0
373 **/
Richard Hughesd0905142016-03-13 09:46:49 +0000374void
Richard Hughes12724852018-09-04 13:53:44 +0100375fu_plugin_set_enabled (FuPlugin *self, gboolean enabled)
Richard Hughesd0905142016-03-13 09:46:49 +0000376{
Richard Hughes12724852018-09-04 13:53:44 +0100377 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100378 if (enabled) {
379 fwupd_plugin_remove_flag (FWUPD_PLUGIN (self),
380 FWUPD_PLUGIN_FLAG_DISABLED);
381 } else {
382 fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_DISABLED);
383 }
Richard Hughescff38bc2016-12-12 12:03:37 +0000384}
385
Mario Limonciello1a680f32019-11-25 19:44:53 -0600386/**
387 * fu_plugin_guess_name_from_fn:
388 * @filename: filename to guess
389 *
390 * Tries to guess the name of the plugin from a filename
391 *
392 * Returns: (transfer full): the guessed name of the plugin
393 *
394 * Since: 1.0.8
395 **/
Richard Hughes1e456bc2018-05-10 20:16:16 +0100396gchar *
397fu_plugin_guess_name_from_fn (const gchar *filename)
398{
399 const gchar *prefix = "libfu_plugin_";
400 gchar *name;
401 gchar *str = g_strstr_len (filename, -1, prefix);
402 if (str == NULL)
403 return NULL;
404 name = g_strdup (str + strlen (prefix));
405 g_strdelimit (name, ".", '\0');
406 return name;
407}
408
Mario Limonciello1a680f32019-11-25 19:44:53 -0600409/**
410 * fu_plugin_open:
411 * @self: A #FuPlugin
412 * @filename: The shared object filename to open
413 * @error: A #GError or NULL
414 *
415 * Opens the plugin module
416 *
417 * Returns: TRUE for success, FALSE for fail
418 *
419 * Since: 0.8.0
420 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000421gboolean
Richard Hughes12724852018-09-04 13:53:44 +0100422fu_plugin_open (FuPlugin *self, const gchar *filename, GError **error)
Richard Hughescff38bc2016-12-12 12:03:37 +0000423{
Richard Hughes12724852018-09-04 13:53:44 +0100424 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughescff38bc2016-12-12 12:03:37 +0000425 FuPluginInitFunc func = NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +0000426
427 priv->module = g_module_open (filename, 0);
428 if (priv->module == NULL) {
429 g_set_error (error,
430 G_IO_ERROR,
431 G_IO_ERROR_FAILED,
Mario Limonciellof5605532019-11-04 07:49:50 -0600432 "failed to open plugin %s: %s",
433 filename, g_module_error ());
Mario Limoncielloc3a81732020-10-20 09:16:18 -0500434 fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_FAILED_OPEN);
435 fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_USER_WARNING);
Richard Hughescff38bc2016-12-12 12:03:37 +0000436 return FALSE;
437 }
438
439 /* set automatically */
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100440 if (fu_plugin_get_name (self) == NULL) {
441 g_autofree gchar *str = fu_plugin_guess_name_from_fn (filename);
442 fu_plugin_set_name (self, str);
443 }
Richard Hughesd0905142016-03-13 09:46:49 +0000444
445 /* optional */
Richard Hughescff38bc2016-12-12 12:03:37 +0000446 g_module_symbol (priv->module, "fu_plugin_init", (gpointer *) &func);
447 if (func != NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -0500448 g_debug ("init(%s)", filename);
Richard Hughes12724852018-09-04 13:53:44 +0100449 func (self);
Richard Hughesd0905142016-03-13 09:46:49 +0000450 }
451
Richard Hughescff38bc2016-12-12 12:03:37 +0000452 return TRUE;
453}
454
Richard Hughes203ed842020-11-02 14:25:13 +0000455/* order of usefulness to the user */
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100456static const gchar *
457fu_plugin_build_device_update_error (FuPlugin *self)
458{
459 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_NO_HARDWARE))
460 return "Not updatable as required hardware was not found";
461 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_LEGACY_BIOS))
462 return "Not updatable in legacy BIOS mode";
463 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_CAPSULES_UNSUPPORTED))
464 return "Not updatable as UEFI capsule updates not enabled";
465 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_UNLOCK_REQUIRED))
466 return "Not updatable as requires unlock";
467 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_EFIVAR_NOT_MOUNTED))
468 return "Not updatable as efivarfs was not found";
469 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_ESP_NOT_FOUND))
470 return "Not updatable as UEFI ESP partition not detected";
471 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
472 return "Not updatable as plugin was disabled";
473 return NULL;
474}
475
Richard Hughes57d18222017-01-10 16:02:59 +0000476/**
477 * fu_plugin_device_add:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100478 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000479 * @device: A #FuDevice
480 *
481 * Asks the daemon to add a device to the exported list. If this device ID
482 * has already been added by a different plugin then this request will be
483 * ignored.
484 *
485 * Plugins should use fu_plugin_device_add_delay() if they are not capable of
486 * actually flashing an image to the hardware so that higher-priority plugins
487 * can add the device themselves.
488 *
489 * Since: 0.8.0
490 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000491void
Richard Hughes12724852018-09-04 13:53:44 +0100492fu_plugin_device_add (FuPlugin *self, FuDevice *device)
Richard Hughescff38bc2016-12-12 12:03:37 +0000493{
Richard Hughes5e447292018-04-27 14:25:54 +0100494 GPtrArray *children;
Richard Hughesc125ec02018-09-05 19:35:17 +0100495 g_autoptr(GError) error = NULL;
Richard Hughes5e447292018-04-27 14:25:54 +0100496
Richard Hughes12724852018-09-04 13:53:44 +0100497 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughesccd78a92017-01-11 16:57:41 +0000498 g_return_if_fail (FU_IS_DEVICE (device));
499
Richard Hughesc125ec02018-09-05 19:35:17 +0100500 /* ensure the device ID is set from the physical and logical IDs */
501 if (!fu_device_ensure_id (device, &error)) {
502 g_warning ("ignoring add: %s", error->message);
503 return;
504 }
505
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100506 /* proxy to device where required */
507 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_CLEAR_UPDATABLE)) {
508 g_debug ("plugin %s has _CLEAR_UPDATABLE, so removing from %s",
509 fu_plugin_get_name (self),
510 fu_device_get_id (device));
511 fu_device_remove_flag (device, FWUPD_DEVICE_FLAG_UPDATABLE);
512 }
513 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_USER_WARNING) &&
514 fu_device_get_update_error (device) == NULL) {
515 const gchar *tmp = fu_plugin_build_device_update_error (self);
516 g_debug ("setting %s update error to '%s' from %s",
517 fu_device_get_id (device), tmp, fu_plugin_get_name (self));
518 fu_device_set_update_error (device, tmp);
519 }
520
Richard Hughescff38bc2016-12-12 12:03:37 +0000521 g_debug ("emit added from %s: %s",
Richard Hughes12724852018-09-04 13:53:44 +0100522 fu_plugin_get_name (self),
Richard Hughescff38bc2016-12-12 12:03:37 +0000523 fu_device_get_id (device));
524 fu_device_set_created (device, (guint64) g_get_real_time () / G_USEC_PER_SEC);
Richard Hughes12724852018-09-04 13:53:44 +0100525 fu_device_set_plugin (device, fu_plugin_get_name (self));
526 g_signal_emit (self, signals[SIGNAL_DEVICE_ADDED], 0, device);
Richard Hughes5e447292018-04-27 14:25:54 +0100527
Richard Hughes128c0162018-08-10 11:00:29 +0100528 /* add children if they have not already been added */
Richard Hughes5e447292018-04-27 14:25:54 +0100529 children = fu_device_get_children (device);
530 for (guint i = 0; i < children->len; i++) {
531 FuDevice *child = g_ptr_array_index (children, i);
Richard Hughes128c0162018-08-10 11:00:29 +0100532 if (fu_device_get_created (child) == 0)
Richard Hughes12724852018-09-04 13:53:44 +0100533 fu_plugin_device_add (self, child);
Richard Hughes5e447292018-04-27 14:25:54 +0100534 }
Richard Hughescff38bc2016-12-12 12:03:37 +0000535}
536
Richard Hughese1fd34d2017-08-24 14:19:51 +0100537/**
538 * fu_plugin_device_register:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100539 * @self: A #FuPlugin
Richard Hughese1fd34d2017-08-24 14:19:51 +0100540 * @device: A #FuDevice
541 *
542 * Registers the device with other plugins so they can set metadata.
543 *
544 * Plugins do not have to call this manually as this is done automatically
545 * when using fu_plugin_device_add(). They may wish to use this manually
Richard Hughes21eaeef2020-01-14 12:10:01 +0000546 * if for instance the coldplug should be ignored based on the metadata
Richard Hughese1fd34d2017-08-24 14:19:51 +0100547 * set from other plugins.
548 *
549 * Since: 0.9.7
550 **/
551void
Richard Hughes12724852018-09-04 13:53:44 +0100552fu_plugin_device_register (FuPlugin *self, FuDevice *device)
Richard Hughese1fd34d2017-08-24 14:19:51 +0100553{
Richard Hughesc125ec02018-09-05 19:35:17 +0100554 g_autoptr(GError) error = NULL;
555
Richard Hughes12724852018-09-04 13:53:44 +0100556 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughese1fd34d2017-08-24 14:19:51 +0100557 g_return_if_fail (FU_IS_DEVICE (device));
558
Richard Hughesc125ec02018-09-05 19:35:17 +0100559 /* ensure the device ID is set from the physical and logical IDs */
560 if (!fu_device_ensure_id (device, &error)) {
561 g_warning ("ignoring registration: %s", error->message);
562 return;
563 }
564
Richard Hughese1fd34d2017-08-24 14:19:51 +0100565 g_debug ("emit device-register from %s: %s",
Richard Hughes12724852018-09-04 13:53:44 +0100566 fu_plugin_get_name (self),
Richard Hughese1fd34d2017-08-24 14:19:51 +0100567 fu_device_get_id (device));
Richard Hughes12724852018-09-04 13:53:44 +0100568 g_signal_emit (self, signals[SIGNAL_DEVICE_REGISTER], 0, device);
Richard Hughese1fd34d2017-08-24 14:19:51 +0100569}
570
Richard Hughes57d18222017-01-10 16:02:59 +0000571/**
Richard Hughes4eada342017-10-03 21:20:32 +0100572 * fu_plugin_device_remove:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100573 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000574 * @device: A #FuDevice
575 *
576 * Asks the daemon to remove a device from the exported list.
577 *
578 * Since: 0.8.0
579 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000580void
Richard Hughes12724852018-09-04 13:53:44 +0100581fu_plugin_device_remove (FuPlugin *self, FuDevice *device)
Richard Hughescff38bc2016-12-12 12:03:37 +0000582{
Richard Hughes12724852018-09-04 13:53:44 +0100583 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughesccd78a92017-01-11 16:57:41 +0000584 g_return_if_fail (FU_IS_DEVICE (device));
585
Richard Hughescff38bc2016-12-12 12:03:37 +0000586 g_debug ("emit removed from %s: %s",
Richard Hughes12724852018-09-04 13:53:44 +0100587 fu_plugin_get_name (self),
Richard Hughescff38bc2016-12-12 12:03:37 +0000588 fu_device_get_id (device));
Richard Hughes12724852018-09-04 13:53:44 +0100589 g_signal_emit (self, signals[SIGNAL_DEVICE_REMOVED], 0, device);
Richard Hughescff38bc2016-12-12 12:03:37 +0000590}
591
Richard Hughes57d18222017-01-10 16:02:59 +0000592/**
Richard Hughes2de8f132018-01-17 09:12:02 +0000593 * fu_plugin_request_recoldplug:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100594 * @self: A #FuPlugin
Richard Hughes362d6d72017-01-07 21:42:14 +0000595 *
596 * Ask all the plugins to coldplug all devices, which will include the prepare()
597 * and cleanup() phases. Duplicate devices added will be ignored.
598 *
599 * Since: 0.8.0
600 **/
601void
Richard Hughes12724852018-09-04 13:53:44 +0100602fu_plugin_request_recoldplug (FuPlugin *self)
Richard Hughes362d6d72017-01-07 21:42:14 +0000603{
Richard Hughes12724852018-09-04 13:53:44 +0100604 g_return_if_fail (FU_IS_PLUGIN (self));
605 g_signal_emit (self, signals[SIGNAL_RECOLDPLUG], 0);
Richard Hughes362d6d72017-01-07 21:42:14 +0000606}
607
Richard Hughesb0829032017-01-10 09:27:08 +0000608/**
Richard Hughes399859e2020-05-11 19:44:03 +0100609 * fu_plugin_security_changed:
610 * @self: A #FuPlugin
611 *
612 * Informs the daemon that the HSI state may have changed.
613 *
614 * Since: 1.5.0
615 **/
616void
617fu_plugin_security_changed (FuPlugin *self)
618{
619 g_return_if_fail (FU_IS_PLUGIN (self));
620 g_signal_emit (self, signals[SIGNAL_SECURITY_CHANGED], 0);
621}
622
623/**
Richard Hughesb8f8db22017-04-25 15:56:00 +0100624 * fu_plugin_check_hwid:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100625 * @self: A #FuPlugin
Richard Hughes4eada342017-10-03 21:20:32 +0100626 * @hwid: A Hardware ID GUID, e.g. `6de5d951-d755-576b-bd09-c5cf66b27234`
Richard Hughesb8f8db22017-04-25 15:56:00 +0100627 *
Richard Hughesd7704d42017-08-08 20:29:09 +0100628 * Checks to see if a specific GUID exists. All hardware IDs on a
Richard Hughesb8f8db22017-04-25 15:56:00 +0100629 * specific system can be shown using the `fwupdmgr hwids` command.
630 *
Richard Hughes4eada342017-10-03 21:20:32 +0100631 * Returns: %TRUE if the HwId is found on the system.
632 *
Richard Hughesb8f8db22017-04-25 15:56:00 +0100633 * Since: 0.9.1
634 **/
635gboolean
Richard Hughes12724852018-09-04 13:53:44 +0100636fu_plugin_check_hwid (FuPlugin *self, const gchar *hwid)
Richard Hughesb8f8db22017-04-25 15:56:00 +0100637{
Richard Hughes12724852018-09-04 13:53:44 +0100638 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesb8f8db22017-04-25 15:56:00 +0100639 if (priv->hwids == NULL)
640 return FALSE;
Richard Hughesd7704d42017-08-08 20:29:09 +0100641 return fu_hwids_has_guid (priv->hwids, hwid);
642}
643
644/**
Patrick Rudolpha60b5472019-10-16 10:43:03 +0200645 * fu_plugin_get_hwid_replace_value:
646 * @self: A #FuPlugin
647 * @keys: A key, e.g. `HardwareID-3` or %FU_HWIDS_KEY_PRODUCT_SKU
648 * @error: A #GError or %NULL
649 *
650 * Gets the replacement value for a specific key. All hardware IDs on a
651 * specific system can be shown using the `fwupdmgr hwids` command.
652 *
653 * Returns: (transfer full): a string, or %NULL for error.
654 *
655 * Since: 1.3.3
656 **/
657gchar *
658fu_plugin_get_hwid_replace_value (FuPlugin *self, const gchar *keys, GError **error)
659{
660 FuPluginPrivate *priv = GET_PRIVATE (self);
661 if (priv->hwids == NULL)
662 return NULL;
663
664 return fu_hwids_get_replace_values (priv->hwids, keys, error);
665}
666
667/**
Richard Hughes69a5f352018-08-08 11:58:15 +0100668 * fu_plugin_get_hwids:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100669 * @self: A #FuPlugin
Richard Hughes69a5f352018-08-08 11:58:15 +0100670 *
671 * Returns all the HWIDs defined in the system. All hardware IDs on a
672 * specific system can be shown using the `fwupdmgr hwids` command.
673 *
Mario Limonciello1a680f32019-11-25 19:44:53 -0600674 * Returns: (transfer none) (element-type utf8): An array of GUIDs
Richard Hughes69a5f352018-08-08 11:58:15 +0100675 *
676 * Since: 1.1.1
677 **/
678GPtrArray *
Richard Hughes12724852018-09-04 13:53:44 +0100679fu_plugin_get_hwids (FuPlugin *self)
Richard Hughes69a5f352018-08-08 11:58:15 +0100680{
Richard Hughes12724852018-09-04 13:53:44 +0100681 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes69a5f352018-08-08 11:58:15 +0100682 if (priv->hwids == NULL)
683 return NULL;
684 return fu_hwids_get_guids (priv->hwids);
685}
686
687/**
Richard Hughes19841802019-09-10 16:48:00 +0100688 * fu_plugin_has_custom_flag:
689 * @self: A #FuPlugin
690 * @flag: A custom text flag, specific to the plugin, e.g. `uefi-force-enable`
691 *
692 * Returns if a per-plugin HwId custom flag exists, typically added from a DMI quirk.
693 *
694 * Returns: %TRUE if the quirk entry exists
695 *
696 * Since: 1.3.1
697 **/
698gboolean
699fu_plugin_has_custom_flag (FuPlugin *self, const gchar *flag)
700{
701 FuPluginPrivate *priv = GET_PRIVATE (self);
702 GPtrArray *hwids = fu_plugin_get_hwids (self);
703
704 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
705 g_return_val_if_fail (flag != NULL, FALSE);
706
707 /* never set up, e.g. in tests */
708 if (hwids == NULL)
709 return FALSE;
710
711 /* search each hwid */
712 for (guint i = 0; i < hwids->len; i++) {
713 const gchar *hwid = g_ptr_array_index (hwids, i);
714 const gchar *value;
715 g_autofree gchar *key = g_strdup_printf ("HwId=%s", hwid);
716
717 /* does prefixed quirk exist */
718 value = fu_quirks_lookup_by_id (priv->quirks, key, FU_QUIRKS_FLAGS);
719 if (value != NULL) {
720 g_auto(GStrv) quirks = g_strsplit (value, ",", -1);
721 if (g_strv_contains ((const gchar * const *) quirks, flag))
722 return TRUE;
723 }
724 }
725 return FALSE;
726}
727
728/**
Richard Hughes1354ea92017-09-19 15:58:31 +0100729 * fu_plugin_check_supported:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100730 * @self: A #FuPlugin
Richard Hughes4eada342017-10-03 21:20:32 +0100731 * @guid: A Hardware ID GUID, e.g. `6de5d951-d755-576b-bd09-c5cf66b27234`
Richard Hughes1354ea92017-09-19 15:58:31 +0100732 *
733 * Checks to see if a specific device GUID is supported, i.e. available in the
734 * AppStream metadata.
735 *
Richard Hughes4eada342017-10-03 21:20:32 +0100736 * Returns: %TRUE if the device is supported.
737 *
Richard Hughes1354ea92017-09-19 15:58:31 +0100738 * Since: 1.0.0
739 **/
Richard Hughesd8a8d5e2019-10-08 13:05:02 +0100740static gboolean
Richard Hughes12724852018-09-04 13:53:44 +0100741fu_plugin_check_supported (FuPlugin *self, const gchar *guid)
Richard Hughes1354ea92017-09-19 15:58:31 +0100742{
Richard Hughesaabdc372018-11-14 10:11:08 +0000743 gboolean retval = FALSE;
744 g_signal_emit (self, signals[SIGNAL_CHECK_SUPPORTED], 0, guid, &retval);
745 return retval;
Richard Hughes1354ea92017-09-19 15:58:31 +0100746}
747
748/**
Richard Hughesd7704d42017-08-08 20:29:09 +0100749 * fu_plugin_get_dmi_value:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100750 * @self: A #FuPlugin
Richard Hughes4eada342017-10-03 21:20:32 +0100751 * @dmi_id: A DMI ID, e.g. `BiosVersion`
Richard Hughesd7704d42017-08-08 20:29:09 +0100752 *
753 * Gets a hardware DMI value.
754 *
Richard Hughes4eada342017-10-03 21:20:32 +0100755 * Returns: The string, or %NULL
756 *
Richard Hughesd7704d42017-08-08 20:29:09 +0100757 * Since: 0.9.7
758 **/
759const gchar *
Richard Hughes12724852018-09-04 13:53:44 +0100760fu_plugin_get_dmi_value (FuPlugin *self, const gchar *dmi_id)
Richard Hughesd7704d42017-08-08 20:29:09 +0100761{
Richard Hughes12724852018-09-04 13:53:44 +0100762 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesd7704d42017-08-08 20:29:09 +0100763 if (priv->hwids == NULL)
Richard Hughes7ef96b82017-08-23 18:28:24 +0100764 return NULL;
Richard Hughesd7704d42017-08-08 20:29:09 +0100765 return fu_hwids_get_value (priv->hwids, dmi_id);
Richard Hughesb8f8db22017-04-25 15:56:00 +0100766}
767
Richard Hughes49e5e052017-09-03 12:15:41 +0100768/**
769 * fu_plugin_get_smbios_string:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100770 * @self: A #FuPlugin
Richard Hughes49e5e052017-09-03 12:15:41 +0100771 * @structure_type: A SMBIOS structure type, e.g. %FU_SMBIOS_STRUCTURE_TYPE_BIOS
772 * @offset: A SMBIOS offset
773 *
774 * Gets a hardware SMBIOS string.
775 *
776 * The @type and @offset can be referenced from the DMTF SMBIOS specification:
777 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.1.1.pdf
778 *
Richard Hughes4eada342017-10-03 21:20:32 +0100779 * Returns: A string, or %NULL
780 *
Richard Hughes49e5e052017-09-03 12:15:41 +0100781 * Since: 0.9.8
782 **/
783const gchar *
Richard Hughes12724852018-09-04 13:53:44 +0100784fu_plugin_get_smbios_string (FuPlugin *self, guint8 structure_type, guint8 offset)
Richard Hughes49e5e052017-09-03 12:15:41 +0100785{
Richard Hughes12724852018-09-04 13:53:44 +0100786 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes49e5e052017-09-03 12:15:41 +0100787 if (priv->smbios == NULL)
788 return NULL;
789 return fu_smbios_get_string (priv->smbios, structure_type, offset, NULL);
790}
791
792/**
793 * fu_plugin_get_smbios_data:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100794 * @self: A #FuPlugin
Richard Hughes49e5e052017-09-03 12:15:41 +0100795 * @structure_type: A SMBIOS structure type, e.g. %FU_SMBIOS_STRUCTURE_TYPE_BIOS
796 *
797 * Gets a hardware SMBIOS data.
798 *
Richard Hughesdfaca2d2019-08-01 08:08:03 +0100799 * Returns: (transfer full): A #GBytes, or %NULL
Richard Hughes4eada342017-10-03 21:20:32 +0100800 *
Richard Hughes49e5e052017-09-03 12:15:41 +0100801 * Since: 0.9.8
802 **/
803GBytes *
Richard Hughes12724852018-09-04 13:53:44 +0100804fu_plugin_get_smbios_data (FuPlugin *self, guint8 structure_type)
Richard Hughes49e5e052017-09-03 12:15:41 +0100805{
Richard Hughes12724852018-09-04 13:53:44 +0100806 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes49e5e052017-09-03 12:15:41 +0100807 if (priv->smbios == NULL)
808 return NULL;
809 return fu_smbios_get_data (priv->smbios, structure_type, NULL);
810}
811
Mario Limonciello1a680f32019-11-25 19:44:53 -0600812/**
813 * fu_plugin_set_hwids:
814 * @self: A #FuPlugin
815 * @hwids: A #FuHwids
816 *
817 * Sets the hwids for a plugin
818 *
819 * Since: 0.9.7
820 **/
Richard Hughesb8f8db22017-04-25 15:56:00 +0100821void
Richard Hughes12724852018-09-04 13:53:44 +0100822fu_plugin_set_hwids (FuPlugin *self, FuHwids *hwids)
Richard Hughesb8f8db22017-04-25 15:56:00 +0100823{
Richard Hughes12724852018-09-04 13:53:44 +0100824 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesd7704d42017-08-08 20:29:09 +0100825 g_set_object (&priv->hwids, hwids);
Richard Hughesb8f8db22017-04-25 15:56:00 +0100826}
827
Mario Limonciello1a680f32019-11-25 19:44:53 -0600828/**
829 * fu_plugin_set_udev_subsystems:
830 * @self: A #FuPlugin
Richard Hughesa0d81c72019-11-27 11:41:54 +0000831 * @udev_subsystems: (element-type utf8): A #GPtrArray
Mario Limonciello1a680f32019-11-25 19:44:53 -0600832 *
833 * Sets the udev subsystems used by a plugin
834 *
835 * Since: 1.1.2
836 **/
Richard Hughes49e5e052017-09-03 12:15:41 +0100837void
Richard Hughes12724852018-09-04 13:53:44 +0100838fu_plugin_set_udev_subsystems (FuPlugin *self, GPtrArray *udev_subsystems)
Richard Hughes9d6e0e72018-08-24 20:20:17 +0100839{
Richard Hughes12724852018-09-04 13:53:44 +0100840 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes9d6e0e72018-08-24 20:20:17 +0100841 if (priv->udev_subsystems != NULL)
842 g_ptr_array_unref (priv->udev_subsystems);
843 priv->udev_subsystems = g_ptr_array_ref (udev_subsystems);
844}
845
Mario Limonciello1a680f32019-11-25 19:44:53 -0600846/**
847 * fu_plugin_set_quirks:
848 * @self: A #FuPlugin
849 * @quirks: A #FuQuirks
850 *
851 * Sets the quirks for a plugin
852 *
853 * Since: 1.0.1
854 **/
Richard Hughes9d6e0e72018-08-24 20:20:17 +0100855void
Richard Hughes12724852018-09-04 13:53:44 +0100856fu_plugin_set_quirks (FuPlugin *self, FuQuirks *quirks)
Richard Hughes9c028f02017-10-28 21:14:28 +0100857{
Richard Hughes12724852018-09-04 13:53:44 +0100858 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes9c028f02017-10-28 21:14:28 +0100859 g_set_object (&priv->quirks, quirks);
860}
861
862/**
863 * fu_plugin_get_quirks:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100864 * @self: A #FuPlugin
Richard Hughes9c028f02017-10-28 21:14:28 +0100865 *
866 * Returns the hardware database object. This can be used to discover device
867 * quirks or other device-specific settings.
868 *
869 * Returns: (transfer none): a #FuQuirks, or %NULL if not set
870 *
871 * Since: 1.0.1
872 **/
873FuQuirks *
Richard Hughes12724852018-09-04 13:53:44 +0100874fu_plugin_get_quirks (FuPlugin *self)
Richard Hughes9c028f02017-10-28 21:14:28 +0100875{
Richard Hughes12724852018-09-04 13:53:44 +0100876 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes9c028f02017-10-28 21:14:28 +0100877 return priv->quirks;
878}
879
Mario Limonciello1a680f32019-11-25 19:44:53 -0600880/**
881 * fu_plugin_set_runtime_versions:
882 * @self: A #FuPlugin
883 * @runtime_versions: A #GHashTables
884 *
885 * Sets the runtime versions for a plugin
886 *
887 * Since: 1.0.7
888 **/
Richard Hughes0eb123b2018-04-19 12:00:04 +0100889void
Richard Hughes12724852018-09-04 13:53:44 +0100890fu_plugin_set_runtime_versions (FuPlugin *self, GHashTable *runtime_versions)
Richard Hughes0eb123b2018-04-19 12:00:04 +0100891{
Richard Hughes12724852018-09-04 13:53:44 +0100892 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes0eb123b2018-04-19 12:00:04 +0100893 priv->runtime_versions = g_hash_table_ref (runtime_versions);
894}
895
896/**
897 * fu_plugin_add_runtime_version:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100898 * @self: A #FuPlugin
Richard Hughes0eb123b2018-04-19 12:00:04 +0100899 * @component_id: An AppStream component id, e.g. "org.gnome.Software"
900 * @version: A version string, e.g. "1.2.3"
901 *
Richard Hughesdce91202019-04-08 12:47:45 +0100902 * Sets a runtime version of a specific dependency.
Richard Hughes0eb123b2018-04-19 12:00:04 +0100903 *
904 * Since: 1.0.7
905 **/
906void
Richard Hughes12724852018-09-04 13:53:44 +0100907fu_plugin_add_runtime_version (FuPlugin *self,
Richard Hughes0eb123b2018-04-19 12:00:04 +0100908 const gchar *component_id,
909 const gchar *version)
910{
Richard Hughes12724852018-09-04 13:53:44 +0100911 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesb01b4862018-04-20 16:39:48 +0100912 if (priv->runtime_versions == NULL)
913 return;
Richard Hughes0eb123b2018-04-19 12:00:04 +0100914 g_hash_table_insert (priv->runtime_versions,
915 g_strdup (component_id),
916 g_strdup (version));
917}
918
Mario Limonciello1a680f32019-11-25 19:44:53 -0600919/**
920 * fu_plugin_set_compile_versions:
921 * @self: A #FuPlugin
922 * @compile_versions: A #GHashTables
923 *
924 * Sets the compile time versions for a plugin
925 *
926 * Since: 1.0.7
927 **/
Richard Hughes34e0dab2018-04-20 16:43:00 +0100928void
Richard Hughes12724852018-09-04 13:53:44 +0100929fu_plugin_set_compile_versions (FuPlugin *self, GHashTable *compile_versions)
Richard Hughes34e0dab2018-04-20 16:43:00 +0100930{
Richard Hughes12724852018-09-04 13:53:44 +0100931 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes34e0dab2018-04-20 16:43:00 +0100932 priv->compile_versions = g_hash_table_ref (compile_versions);
933}
934
935/**
936 * fu_plugin_add_compile_version:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100937 * @self: A #FuPlugin
Richard Hughes34e0dab2018-04-20 16:43:00 +0100938 * @component_id: An AppStream component id, e.g. "org.gnome.Software"
939 * @version: A version string, e.g. "1.2.3"
940 *
Richard Hughesdce91202019-04-08 12:47:45 +0100941 * Sets a compile-time version of a specific dependency.
Richard Hughes34e0dab2018-04-20 16:43:00 +0100942 *
943 * Since: 1.0.7
944 **/
945void
Richard Hughes12724852018-09-04 13:53:44 +0100946fu_plugin_add_compile_version (FuPlugin *self,
Richard Hughes34e0dab2018-04-20 16:43:00 +0100947 const gchar *component_id,
948 const gchar *version)
949{
Richard Hughes12724852018-09-04 13:53:44 +0100950 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes34e0dab2018-04-20 16:43:00 +0100951 if (priv->compile_versions == NULL)
952 return;
953 g_hash_table_insert (priv->compile_versions,
954 g_strdup (component_id),
955 g_strdup (version));
956}
957
Richard Hughes9c028f02017-10-28 21:14:28 +0100958/**
959 * fu_plugin_lookup_quirk_by_id:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100960 * @self: A #FuPlugin
Richard Hughes87fb9ff2018-06-28 12:55:59 +0100961 * @group: A string, e.g. "DfuFlags"
962 * @key: An ID to match the entry, e.g. "Summary"
Richard Hughes9c028f02017-10-28 21:14:28 +0100963 *
964 * Looks up an entry in the hardware database using a string value.
965 *
966 * Returns: (transfer none): values from the database, or %NULL if not found
967 *
968 * Since: 1.0.1
969 **/
970const gchar *
Richard Hughes12724852018-09-04 13:53:44 +0100971fu_plugin_lookup_quirk_by_id (FuPlugin *self, const gchar *group, const gchar *key)
Richard Hughes9c028f02017-10-28 21:14:28 +0100972{
Richard Hughes12724852018-09-04 13:53:44 +0100973 FuPluginPrivate *priv = GET_PRIVATE (self);
974 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughes9c028f02017-10-28 21:14:28 +0100975
Richard Hughes9c028f02017-10-28 21:14:28 +0100976 /* exact ID */
Richard Hughes87fb9ff2018-06-28 12:55:59 +0100977 return fu_quirks_lookup_by_id (priv->quirks, group, key);
Richard Hughes9c028f02017-10-28 21:14:28 +0100978}
979
980/**
Richard Hughes8fe7cdd2018-08-23 10:02:44 +0100981 * fu_plugin_lookup_quirk_by_id_as_uint64:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100982 * @self: A #FuPlugin
Richard Hughes8fe7cdd2018-08-23 10:02:44 +0100983 * @group: A string, e.g. "DfuFlags"
984 * @key: An ID to match the entry, e.g. "Size"
985 *
986 * Looks up an entry in the hardware database using a string key, returning
987 * an integer value. Values are assumed base 10, unless prefixed with "0x"
988 * where they are parsed as base 16.
989 *
Mario Limonciello1a680f32019-11-25 19:44:53 -0600990 * Returns: guint64 id or 0 if not found
Richard Hughes8fe7cdd2018-08-23 10:02:44 +0100991 *
992 * Since: 1.1.2
993 **/
994guint64
Richard Hughes12724852018-09-04 13:53:44 +0100995fu_plugin_lookup_quirk_by_id_as_uint64 (FuPlugin *self, const gchar *group, const gchar *key)
Richard Hughes8fe7cdd2018-08-23 10:02:44 +0100996{
Richard Hughes12724852018-09-04 13:53:44 +0100997 return fu_common_strtoull (fu_plugin_lookup_quirk_by_id (self, group, key));
Richard Hughes8fe7cdd2018-08-23 10:02:44 +0100998}
999
Mario Limonciello1a680f32019-11-25 19:44:53 -06001000/**
1001 * fu_plugin_set_smbios:
1002 * @self: A #FuPlugin
1003 * @smbios: A #FuSmbios
1004 *
1005 * Sets the smbios for a plugin
1006 *
1007 * Since: 1.0.0
1008 **/
Richard Hughes1354ea92017-09-19 15:58:31 +01001009void
Richard Hughes12724852018-09-04 13:53:44 +01001010fu_plugin_set_smbios (FuPlugin *self, FuSmbios *smbios)
Richard Hughes49e5e052017-09-03 12:15:41 +01001011{
Richard Hughes12724852018-09-04 13:53:44 +01001012 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes49e5e052017-09-03 12:15:41 +01001013 g_set_object (&priv->smbios, smbios);
1014}
1015
Richard Hughesb8f8db22017-04-25 15:56:00 +01001016/**
Richard Hughesb0829032017-01-10 09:27:08 +00001017 * fu_plugin_set_coldplug_delay:
Richard Hughes2c0635a2018-09-04 14:52:46 +01001018 * @self: A #FuPlugin
Richard Hughesb0829032017-01-10 09:27:08 +00001019 * @duration: A delay in milliseconds
1020 *
Richard Hughes21eaeef2020-01-14 12:10:01 +00001021 * Set the minimum time that should be waited in-between the call to
Richard Hughesb0829032017-01-10 09:27:08 +00001022 * fu_plugin_coldplug_prepare() and fu_plugin_coldplug(). This is usually going
Richard Hughes203ed842020-11-02 14:25:13 +00001023 * to be the minimum hardware initialization time from a datasheet.
Richard Hughesb0829032017-01-10 09:27:08 +00001024 *
1025 * It is better to use this function rather than using a sleep() in the plugin
1026 * itself as then only one delay is done in the daemon rather than waiting for
1027 * each coldplug prepare in a serial way.
1028 *
1029 * Additionally, very long delays should be avoided as the daemon will be
1030 * blocked from processing requests whilst the coldplug delay is being
1031 * performed.
1032 *
1033 * Since: 0.8.0
1034 **/
1035void
Richard Hughes12724852018-09-04 13:53:44 +01001036fu_plugin_set_coldplug_delay (FuPlugin *self, guint duration)
Richard Hughesb0829032017-01-10 09:27:08 +00001037{
Richard Hughes12724852018-09-04 13:53:44 +01001038 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughesb0829032017-01-10 09:27:08 +00001039 g_return_if_fail (duration > 0);
1040
1041 /* check sanity */
1042 if (duration > FU_PLUGIN_COLDPLUG_DELAY_MAXIMUM) {
1043 g_warning ("duration of %ums is crazy, truncating to %ums",
1044 duration,
1045 FU_PLUGIN_COLDPLUG_DELAY_MAXIMUM);
1046 duration = FU_PLUGIN_COLDPLUG_DELAY_MAXIMUM;
1047 }
1048
1049 /* emit */
Richard Hughes12724852018-09-04 13:53:44 +01001050 g_signal_emit (self, signals[SIGNAL_SET_COLDPLUG_DELAY], 0, duration);
Richard Hughesb0829032017-01-10 09:27:08 +00001051}
1052
Richard Hughes4b303802019-10-04 13:22:51 +01001053static gboolean
1054fu_plugin_device_attach (FuPlugin *self, FuDevice *device, GError **error)
1055{
1056 g_autoptr(FuDeviceLocker) locker = NULL;
Richard Hughes4b303802019-10-04 13:22:51 +01001057 locker = fu_device_locker_new (device, error);
1058 if (locker == NULL)
1059 return FALSE;
1060 return fu_device_attach (device, error);
1061}
1062
1063static gboolean
1064fu_plugin_device_detach (FuPlugin *self, FuDevice *device, GError **error)
1065{
1066 g_autoptr(FuDeviceLocker) locker = NULL;
Richard Hughes4b303802019-10-04 13:22:51 +01001067 locker = fu_device_locker_new (device, error);
1068 if (locker == NULL)
1069 return FALSE;
1070 return fu_device_detach (device, error);
1071}
1072
1073static gboolean
Richard Hughes4b303802019-10-04 13:22:51 +01001074fu_plugin_device_activate (FuPlugin *self, FuDevice *device, GError **error)
1075{
1076 g_autoptr(FuDeviceLocker) locker = NULL;
1077 locker = fu_device_locker_new (device, error);
1078 if (locker == NULL)
1079 return FALSE;
1080 return fu_device_activate (device, error);
1081}
1082
1083static gboolean
1084fu_plugin_device_write_firmware (FuPlugin *self, FuDevice *device,
1085 GBytes *fw, FwupdInstallFlags flags,
1086 GError **error)
1087{
1088 g_autoptr(FuDeviceLocker) locker = NULL;
1089 locker = fu_device_locker_new (device, error);
1090 if (locker == NULL)
1091 return FALSE;
Richard Hughes1a612582020-09-29 19:39:38 +01001092
1093 /* back the old firmware up to /var/lib/fwupd */
1094 if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL)) {
1095 g_autoptr(GBytes) fw_old = NULL;
1096 g_autofree gchar *path = NULL;
1097 g_autofree gchar *fn = NULL;
1098 g_autofree gchar *localstatedir = NULL;
1099
1100 fw_old = fu_device_dump_firmware (device, error);
1101 if (fw_old == NULL) {
1102 g_prefix_error (error, "failed to backup old firmware: ");
1103 return FALSE;
1104 }
1105 localstatedir = fu_common_get_path (FU_PATH_KIND_LOCALSTATEDIR_PKG);
1106 fn = g_strdup_printf ("%s.bin", fu_device_get_version (device));
1107 path = g_build_filename (localstatedir,
1108 "backup",
1109 fu_device_get_id (device),
1110 fu_device_get_serial (device) != NULL ?
1111 fu_device_get_serial (device) :
1112 "default",
1113 fn, NULL);
1114 if (!fu_common_set_contents_bytes (path, fw_old, error))
1115 return FALSE;
1116 }
1117
Richard Hughes4b303802019-10-04 13:22:51 +01001118 return fu_device_write_firmware (device, fw, flags, error);
1119}
1120
Richard Hughes7f677212019-10-05 16:19:40 +01001121static gboolean
1122fu_plugin_device_read_firmware (FuPlugin *self, FuDevice *device, GError **error)
1123{
1124 g_autoptr(FuDeviceLocker) locker = NULL;
Richard Hughesf0eb0912019-10-10 11:37:22 +01001125 g_autoptr(FuFirmware) firmware = NULL;
Richard Hughes7f677212019-10-05 16:19:40 +01001126 g_autoptr(GBytes) fw = NULL;
1127 GChecksumType checksum_types[] = {
1128 G_CHECKSUM_SHA1,
1129 G_CHECKSUM_SHA256,
1130 0 };
1131 locker = fu_device_locker_new (device, error);
1132 if (locker == NULL)
1133 return FALSE;
1134 if (!fu_device_detach (device, error))
1135 return FALSE;
Richard Hughesf0eb0912019-10-10 11:37:22 +01001136 firmware = fu_device_read_firmware (device, error);
1137 if (firmware == NULL) {
1138 g_autoptr(GError) error_local = NULL;
1139 if (!fu_device_attach (device, &error_local))
1140 g_debug ("ignoring attach failure: %s", error_local->message);
1141 g_prefix_error (error, "failed to read firmware: ");
1142 return FALSE;
1143 }
1144 fw = fu_firmware_write (firmware, error);
Richard Hughes7f677212019-10-05 16:19:40 +01001145 if (fw == NULL) {
1146 g_autoptr(GError) error_local = NULL;
1147 if (!fu_device_attach (device, &error_local))
Richard Hughesf0eb0912019-10-10 11:37:22 +01001148 g_debug ("ignoring attach failure: %s", error_local->message);
1149 g_prefix_error (error, "failed to write firmware: ");
Richard Hughes7f677212019-10-05 16:19:40 +01001150 return FALSE;
1151 }
1152 for (guint i = 0; checksum_types[i] != 0; i++) {
1153 g_autofree gchar *hash = NULL;
1154 hash = g_compute_checksum_for_bytes (checksum_types[i], fw);
1155 fu_device_add_checksum (device, hash);
1156 }
1157 return fu_device_attach (device, error);
1158}
1159
Mario Limonciello1a680f32019-11-25 19:44:53 -06001160/**
1161 * fu_plugin_runner_startup:
1162 * @self: a #FuPlugin
1163 * @error: a #GError or NULL
1164 *
1165 * Runs the startup routine for the plugin
1166 *
1167 * Returns: #TRUE for success, #FALSE for failure
1168 *
1169 * Since: 0.8.0
1170 **/
Richard Hughesd0905142016-03-13 09:46:49 +00001171gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001172fu_plugin_runner_startup (FuPlugin *self, GError **error)
Richard Hughesd0905142016-03-13 09:46:49 +00001173{
Richard Hughes12724852018-09-04 13:53:44 +01001174 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes7b8b2022016-12-12 16:15:03 +00001175 FuPluginStartupFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001176 g_autoptr(GError) error_local = NULL;
Richard Hughesd0905142016-03-13 09:46:49 +00001177
1178 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001179 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughesd0905142016-03-13 09:46:49 +00001180 return TRUE;
1181
Richard Hughes639da472018-01-06 22:35:04 +00001182 /* no object loaded */
1183 if (priv->module == NULL)
1184 return TRUE;
1185
Richard Hughesd0905142016-03-13 09:46:49 +00001186 /* optional */
Richard Hughescff38bc2016-12-12 12:03:37 +00001187 g_module_symbol (priv->module, "fu_plugin_startup", (gpointer *) &func);
1188 if (func == NULL)
Richard Hughesd0905142016-03-13 09:46:49 +00001189 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001190 g_debug ("startup(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001191 if (!func (self, &error_local)) {
1192 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001193 g_critical ("unset plugin error in startup(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001194 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001195 g_set_error_literal (&error_local,
1196 FWUPD_ERROR,
1197 FWUPD_ERROR_INTERNAL,
1198 "unspecified error");
1199 }
1200 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1201 "failed to startup using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001202 fu_plugin_get_name (self));
Richard Hughescff38bc2016-12-12 12:03:37 +00001203 return FALSE;
1204 }
1205 return TRUE;
1206}
1207
1208static gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001209fu_plugin_runner_device_generic (FuPlugin *self, FuDevice *device,
Richard Hughes4b303802019-10-04 13:22:51 +01001210 const gchar *symbol_name,
1211 FuPluginDeviceFunc device_func,
1212 GError **error)
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001213{
Richard Hughes12724852018-09-04 13:53:44 +01001214 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001215 FuPluginDeviceFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001216 g_autoptr(GError) error_local = NULL;
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001217
1218 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001219 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001220 return TRUE;
1221
Richard Hughesd3d96cc2017-11-14 11:34:33 +00001222 /* no object loaded */
1223 if (priv->module == NULL)
1224 return TRUE;
1225
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001226 /* optional */
1227 g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
Richard Hughes4b303802019-10-04 13:22:51 +01001228 if (func == NULL) {
1229 if (device_func != NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001230 g_debug ("running superclassed %s(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001231 symbol_name + 10, fu_plugin_get_name (self));
Richard Hughes4b303802019-10-04 13:22:51 +01001232 return device_func (self, device, error);
1233 }
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001234 return TRUE;
Richard Hughes4b303802019-10-04 13:22:51 +01001235 }
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001236 g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001237 if (!func (self, device, &error_local)) {
1238 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001239 g_critical ("unset plugin error in %s(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001240 fu_plugin_get_name (self), symbol_name + 10);
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001241 g_set_error_literal (&error_local,
1242 FWUPD_ERROR,
1243 FWUPD_ERROR_INTERNAL,
1244 "unspecified error");
1245 }
1246 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1247 "failed to %s using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001248 symbol_name + 10, fu_plugin_get_name (self));
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001249 return FALSE;
1250 }
1251 return TRUE;
1252}
1253
Richard Hughesdbd8c762018-06-15 20:31:40 +01001254static gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001255fu_plugin_runner_flagged_device_generic (FuPlugin *self, FwupdInstallFlags flags,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001256 FuDevice *device,
1257 const gchar *symbol_name, GError **error)
1258{
Richard Hughes12724852018-09-04 13:53:44 +01001259 FuPluginPrivate *priv = GET_PRIVATE (self);
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001260 FuPluginFlaggedDeviceFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001261 g_autoptr(GError) error_local = NULL;
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001262
1263 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001264 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001265 return TRUE;
1266
1267 /* no object loaded */
1268 if (priv->module == NULL)
1269 return TRUE;
1270
1271 /* optional */
1272 g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
1273 if (func == NULL)
1274 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001275 g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001276 if (!func (self, flags, device, &error_local)) {
1277 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001278 g_critical ("unset plugin error in %s(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001279 fu_plugin_get_name (self), symbol_name + 10);
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001280 g_set_error_literal (&error_local,
1281 FWUPD_ERROR,
1282 FWUPD_ERROR_INTERNAL,
1283 "unspecified error");
1284 }
1285 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1286 "failed to %s using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001287 symbol_name + 10, fu_plugin_get_name (self));
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001288 return FALSE;
1289 }
1290 return TRUE;
1291
1292}
1293
1294static gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001295fu_plugin_runner_device_array_generic (FuPlugin *self, GPtrArray *devices,
Richard Hughesdbd8c762018-06-15 20:31:40 +01001296 const gchar *symbol_name, GError **error)
1297{
Richard Hughes12724852018-09-04 13:53:44 +01001298 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesdbd8c762018-06-15 20:31:40 +01001299 FuPluginDeviceArrayFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001300 g_autoptr(GError) error_local = NULL;
Richard Hughesdbd8c762018-06-15 20:31:40 +01001301
1302 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001303 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughesdbd8c762018-06-15 20:31:40 +01001304 return TRUE;
1305
1306 /* no object loaded */
1307 if (priv->module == NULL)
1308 return TRUE;
1309
1310 /* optional */
1311 g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
1312 if (func == NULL)
1313 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001314 g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001315 if (!func (self, devices, &error_local)) {
1316 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001317 g_critical ("unset plugin error in for %s(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001318 fu_plugin_get_name (self), symbol_name + 10);
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001319 g_set_error_literal (&error_local,
1320 FWUPD_ERROR,
1321 FWUPD_ERROR_INTERNAL,
1322 "unspecified error");
1323 }
1324 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1325 "failed to %s using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001326 symbol_name + 10, fu_plugin_get_name (self));
Richard Hughesdbd8c762018-06-15 20:31:40 +01001327 return FALSE;
1328 }
1329 return TRUE;
1330}
1331
Mario Limonciello1a680f32019-11-25 19:44:53 -06001332/**
1333 * fu_plugin_runner_coldplug:
1334 * @self: a #FuPlugin
1335 * @error: a #GError or NULL
1336 *
1337 * Runs the coldplug routine for the plugin
1338 *
1339 * Returns: #TRUE for success, #FALSE for failure
1340 *
1341 * Since: 0.8.0
1342 **/
Richard Hughesd0905142016-03-13 09:46:49 +00001343gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001344fu_plugin_runner_coldplug (FuPlugin *self, GError **error)
Richard Hughesd0905142016-03-13 09:46:49 +00001345{
Richard Hughes12724852018-09-04 13:53:44 +01001346 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes7b8b2022016-12-12 16:15:03 +00001347 FuPluginStartupFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001348 g_autoptr(GError) error_local = NULL;
Richard Hughesd0905142016-03-13 09:46:49 +00001349
1350 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001351 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughesd0905142016-03-13 09:46:49 +00001352 return TRUE;
1353
Richard Hughes639da472018-01-06 22:35:04 +00001354 /* no object loaded */
1355 if (priv->module == NULL)
1356 return TRUE;
1357
Richard Hughesd0905142016-03-13 09:46:49 +00001358 /* optional */
Richard Hughescff38bc2016-12-12 12:03:37 +00001359 g_module_symbol (priv->module, "fu_plugin_coldplug", (gpointer *) &func);
1360 if (func == NULL)
Richard Hughesd0905142016-03-13 09:46:49 +00001361 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001362 g_debug ("coldplug(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001363 if (!func (self, &error_local)) {
1364 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001365 g_critical ("unset plugin error in coldplug(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001366 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001367 g_set_error_literal (&error_local,
1368 FWUPD_ERROR,
1369 FWUPD_ERROR_INTERNAL,
1370 "unspecified error");
1371 }
1372 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001373 "failed to coldplug using %s: ", fu_plugin_get_name (self));
Richard Hughescff38bc2016-12-12 12:03:37 +00001374 return FALSE;
1375 }
1376 return TRUE;
1377}
1378
Mario Limonciello1a680f32019-11-25 19:44:53 -06001379/**
1380 * fu_plugin_runner_recoldplug:
1381 * @self: a #FuPlugin
1382 * @error: a #GError or NULL
1383 *
1384 * Runs the recoldplug routine for the plugin
1385 *
1386 * Returns: #TRUE for success, #FALSE for failure
1387 *
1388 * Since: 1.0.4
1389 **/
Richard Hughes7b8b2022016-12-12 16:15:03 +00001390gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001391fu_plugin_runner_recoldplug (FuPlugin *self, GError **error)
Richard Hughes2de8f132018-01-17 09:12:02 +00001392{
Richard Hughes12724852018-09-04 13:53:44 +01001393 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes2de8f132018-01-17 09:12:02 +00001394 FuPluginStartupFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001395 g_autoptr(GError) error_local = NULL;
Richard Hughes2de8f132018-01-17 09:12:02 +00001396
1397 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001398 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes2de8f132018-01-17 09:12:02 +00001399 return TRUE;
1400
1401 /* no object loaded */
1402 if (priv->module == NULL)
1403 return TRUE;
1404
1405 /* optional */
1406 g_module_symbol (priv->module, "fu_plugin_recoldplug", (gpointer *) &func);
1407 if (func == NULL)
1408 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001409 g_debug ("recoldplug(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001410 if (!func (self, &error_local)) {
1411 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001412 g_critical ("unset plugin error in recoldplug(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001413 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001414 g_set_error_literal (&error_local,
1415 FWUPD_ERROR,
1416 FWUPD_ERROR_INTERNAL,
1417 "unspecified error");
1418 }
1419 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1420 "failed to recoldplug using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001421 fu_plugin_get_name (self));
Richard Hughes2de8f132018-01-17 09:12:02 +00001422 return FALSE;
1423 }
1424 return TRUE;
1425}
1426
Mario Limonciello1a680f32019-11-25 19:44:53 -06001427/**
1428 * fu_plugin_runner_coldplug_prepare:
1429 * @self: a #FuPlugin
1430 * @error: a #GError or NULL
1431 *
1432 * Runs the coldplug_prepare routine for the plugin
1433 *
1434 * Returns: #TRUE for success, #FALSE for failure
1435 *
1436 * Since: 0.8.0
1437 **/
Richard Hughes2de8f132018-01-17 09:12:02 +00001438gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001439fu_plugin_runner_coldplug_prepare (FuPlugin *self, GError **error)
Richard Hughes46487c92017-01-07 21:26:34 +00001440{
Richard Hughes12724852018-09-04 13:53:44 +01001441 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes46487c92017-01-07 21:26:34 +00001442 FuPluginStartupFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001443 g_autoptr(GError) error_local = NULL;
Richard Hughes46487c92017-01-07 21:26:34 +00001444
1445 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001446 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes46487c92017-01-07 21:26:34 +00001447 return TRUE;
1448
Richard Hughes639da472018-01-06 22:35:04 +00001449 /* no object loaded */
1450 if (priv->module == NULL)
1451 return TRUE;
1452
Richard Hughes46487c92017-01-07 21:26:34 +00001453 /* optional */
1454 g_module_symbol (priv->module, "fu_plugin_coldplug_prepare", (gpointer *) &func);
1455 if (func == NULL)
1456 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001457 g_debug ("coldplug_prepare(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001458 if (!func (self, &error_local)) {
1459 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001460 g_critical ("unset plugin error in coldplug_prepare(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001461 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001462 g_set_error_literal (&error_local,
1463 FWUPD_ERROR,
1464 FWUPD_ERROR_INTERNAL,
1465 "unspecified error");
1466 }
1467 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1468 "failed to coldplug_prepare using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001469 fu_plugin_get_name (self));
Richard Hughes46487c92017-01-07 21:26:34 +00001470 return FALSE;
1471 }
1472 return TRUE;
1473}
1474
Mario Limonciello1a680f32019-11-25 19:44:53 -06001475/**
1476 * fu_plugin_runner_coldplug_cleanup:
1477 * @self: a #FuPlugin
1478 * @error: a #GError or NULL
1479 *
1480 * Runs the coldplug_cleanup routine for the plugin
1481 *
1482 * Returns: #TRUE for success, #FALSE for failure
1483 *
1484 * Since: 0.8.0
1485 **/
Richard Hughes46487c92017-01-07 21:26:34 +00001486gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001487fu_plugin_runner_coldplug_cleanup (FuPlugin *self, GError **error)
Richard Hughes46487c92017-01-07 21:26:34 +00001488{
Richard Hughes12724852018-09-04 13:53:44 +01001489 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes46487c92017-01-07 21:26:34 +00001490 FuPluginStartupFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001491 g_autoptr(GError) error_local = NULL;
Richard Hughes46487c92017-01-07 21:26:34 +00001492
1493 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001494 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes46487c92017-01-07 21:26:34 +00001495 return TRUE;
1496
Richard Hughes639da472018-01-06 22:35:04 +00001497 /* no object loaded */
1498 if (priv->module == NULL)
1499 return TRUE;
1500
Richard Hughes46487c92017-01-07 21:26:34 +00001501 /* optional */
1502 g_module_symbol (priv->module, "fu_plugin_coldplug_cleanup", (gpointer *) &func);
1503 if (func == NULL)
1504 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001505 g_debug ("coldplug_cleanup(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001506 if (!func (self, &error_local)) {
1507 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001508 g_critical ("unset plugin error in coldplug_cleanup(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001509 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001510 g_set_error_literal (&error_local,
1511 FWUPD_ERROR,
1512 FWUPD_ERROR_INTERNAL,
1513 "unspecified error");
1514 }
1515 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1516 "failed to coldplug_cleanup using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001517 fu_plugin_get_name (self));
Richard Hughes46487c92017-01-07 21:26:34 +00001518 return FALSE;
1519 }
1520 return TRUE;
1521}
1522
Mario Limonciello1a680f32019-11-25 19:44:53 -06001523/**
1524 * fu_plugin_runner_composite_prepare:
1525 * @self: a #FuPlugin
Richard Hughesa0d81c72019-11-27 11:41:54 +00001526 * @devices: (element-type FuDevice): a #GPtrArray of devices
Mario Limonciello1a680f32019-11-25 19:44:53 -06001527 * @error: a #GError or NULL
1528 *
1529 * Runs the composite_prepare routine for the plugin
1530 *
1531 * Returns: #TRUE for success, #FALSE for failure
1532 *
1533 * Since: 1.0.9
1534 **/
Richard Hughes46487c92017-01-07 21:26:34 +00001535gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001536fu_plugin_runner_composite_prepare (FuPlugin *self, GPtrArray *devices, GError **error)
Richard Hughesdbd8c762018-06-15 20:31:40 +01001537{
Richard Hughes12724852018-09-04 13:53:44 +01001538 return fu_plugin_runner_device_array_generic (self, devices,
Richard Hughesdbd8c762018-06-15 20:31:40 +01001539 "fu_plugin_composite_prepare",
1540 error);
1541}
1542
Mario Limonciello1a680f32019-11-25 19:44:53 -06001543/**
1544 * fu_plugin_runner_composite_cleanup:
1545 * @self: a #FuPlugin
Richard Hughesa0d81c72019-11-27 11:41:54 +00001546 * @devices: (element-type FuDevice): a #GPtrArray of devices
Mario Limonciello1a680f32019-11-25 19:44:53 -06001547 * @error: a #GError or NULL
1548 *
1549 * Runs the composite_cleanup routine for the plugin
1550 *
1551 * Returns: #TRUE for success, #FALSE for failure
1552 *
1553 * Since: 1.0.9
1554 **/
Richard Hughesdbd8c762018-06-15 20:31:40 +01001555gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001556fu_plugin_runner_composite_cleanup (FuPlugin *self, GPtrArray *devices, GError **error)
Richard Hughesdbd8c762018-06-15 20:31:40 +01001557{
Richard Hughes12724852018-09-04 13:53:44 +01001558 return fu_plugin_runner_device_array_generic (self, devices,
Richard Hughesdbd8c762018-06-15 20:31:40 +01001559 "fu_plugin_composite_cleanup",
1560 error);
1561}
1562
Mario Limonciello1a680f32019-11-25 19:44:53 -06001563/**
1564 * fu_plugin_runner_update_prepare:
1565 * @self: a #FuPlugin
Richard Hughes2bbb7d22020-11-30 09:18:45 +00001566 * @flags: #FwupdInstallFlags
1567 * @device: a #FuDevice
Mario Limonciello1a680f32019-11-25 19:44:53 -06001568 * @error: a #GError or NULL
1569 *
1570 * Runs the update_prepare routine for the plugin
1571 *
1572 * Returns: #TRUE for success, #FALSE for failure
1573 *
1574 * Since: 1.1.2
1575 **/
Richard Hughesdbd8c762018-06-15 20:31:40 +01001576gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001577fu_plugin_runner_update_prepare (FuPlugin *self, FwupdInstallFlags flags, FuDevice *device,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001578 GError **error)
Richard Hughes7b8b2022016-12-12 16:15:03 +00001579{
Richard Hughes12724852018-09-04 13:53:44 +01001580 return fu_plugin_runner_flagged_device_generic (self, flags, device,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001581 "fu_plugin_update_prepare",
1582 error);
Richard Hughes7b8b2022016-12-12 16:15:03 +00001583}
1584
Mario Limonciello1a680f32019-11-25 19:44:53 -06001585/**
1586 * fu_plugin_runner_update_cleanup:
1587 * @self: a #FuPlugin
Richard Hughes2bbb7d22020-11-30 09:18:45 +00001588 * @flags: #FwupdInstallFlags
1589 * @device: a #FuDevice
Mario Limonciello1a680f32019-11-25 19:44:53 -06001590 * @error: a #GError or NULL
1591 *
1592 * Runs the update_cleanup routine for the plugin
1593 *
1594 * Returns: #TRUE for success, #FALSE for failure
1595 *
1596 * Since: 1.1.2
1597 **/
Richard Hughes7b8b2022016-12-12 16:15:03 +00001598gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001599fu_plugin_runner_update_cleanup (FuPlugin *self, FwupdInstallFlags flags, FuDevice *device,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001600 GError **error)
Richard Hughes7b8b2022016-12-12 16:15:03 +00001601{
Richard Hughes12724852018-09-04 13:53:44 +01001602 return fu_plugin_runner_flagged_device_generic (self, flags, device,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001603 "fu_plugin_update_cleanup",
1604 error);
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001605}
Richard Hughes7b8b2022016-12-12 16:15:03 +00001606
Mario Limonciello1a680f32019-11-25 19:44:53 -06001607/**
1608 * fu_plugin_runner_update_attach:
1609 * @self: a #FuPlugin
1610 * @device: a #FuDevice
1611 * @error: a #GError or NULL
1612 *
1613 * Runs the update_attach routine for the plugin
1614 *
1615 * Returns: #TRUE for success, #FALSE for failure
1616 *
1617 * Since: 1.1.2
1618 **/
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001619gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001620fu_plugin_runner_update_attach (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001621{
Richard Hughes12724852018-09-04 13:53:44 +01001622 return fu_plugin_runner_device_generic (self, device,
Richard Hughes4b303802019-10-04 13:22:51 +01001623 "fu_plugin_update_attach",
1624 fu_plugin_device_attach,
1625 error);
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001626}
Richard Hughes7b8b2022016-12-12 16:15:03 +00001627
Mario Limonciello1a680f32019-11-25 19:44:53 -06001628/**
1629 * fu_plugin_runner_update_detach:
1630 * @self: a #FuPlugin
1631 * @device: A #FuDevice
1632 * @error: a #GError or NULL
1633 *
1634 * Runs the update_detach routine for the plugin
1635 *
1636 * Returns: #TRUE for success, #FALSE for failure
1637 *
1638 * Since: 1.1.2
1639 **/
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001640gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001641fu_plugin_runner_update_detach (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001642{
Richard Hughes12724852018-09-04 13:53:44 +01001643 return fu_plugin_runner_device_generic (self, device,
Richard Hughes4b303802019-10-04 13:22:51 +01001644 "fu_plugin_update_detach",
1645 fu_plugin_device_detach,
1646 error);
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001647}
1648
Mario Limonciello1a680f32019-11-25 19:44:53 -06001649/**
1650 * fu_plugin_runner_update_reload:
1651 * @self: a #FuPlugin
Richard Hughes2bbb7d22020-11-30 09:18:45 +00001652 * @device: A #FuDevice
Mario Limonciello1a680f32019-11-25 19:44:53 -06001653 * @error: a #GError or NULL
1654 *
1655 * Runs reload routine for a device
1656 *
1657 * Returns: #TRUE for success, #FALSE for failure
1658 *
1659 * Since: 1.1.2
1660 **/
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001661gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001662fu_plugin_runner_update_reload (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001663{
Richard Hughes42f33df2019-10-05 20:52:33 +01001664 g_autoptr(FuDeviceLocker) locker = NULL;
1665
1666 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001667 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes42f33df2019-10-05 20:52:33 +01001668 return TRUE;
1669
1670 /* no object loaded */
1671 locker = fu_device_locker_new (device, error);
1672 if (locker == NULL)
1673 return FALSE;
1674 return fu_device_reload (device, error);
Richard Hughes7b8b2022016-12-12 16:15:03 +00001675}
1676
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001677/**
Richard Hughes196c6c62020-05-11 19:42:47 +01001678 * fu_plugin_runner_add_security_attrs:
1679 * @self: a #FuPlugin
Richard Hughes3ecd22c2020-05-19 20:13:47 +01001680 * @attrs: a #FuSecurityAttrs
Richard Hughes196c6c62020-05-11 19:42:47 +01001681 *
Richard Hughes3ecd22c2020-05-19 20:13:47 +01001682 * Runs the `add_security_attrs()` routine for the plugin
Richard Hughes196c6c62020-05-11 19:42:47 +01001683 *
1684 * Since: 1.5.0
1685 **/
Richard Hughesf58ac732020-05-12 15:23:44 +01001686void
1687fu_plugin_runner_add_security_attrs (FuPlugin *self, FuSecurityAttrs *attrs)
Richard Hughes196c6c62020-05-11 19:42:47 +01001688{
Richard Hughesf58ac732020-05-12 15:23:44 +01001689 FuPluginPrivate *priv = GET_PRIVATE (self);
1690 FuPluginSecurityAttrsFunc func = NULL;
1691 const gchar *symbol_name = "fu_plugin_add_security_attrs";
1692
1693 /* no object loaded */
1694 if (priv->module == NULL)
1695 return;
1696
1697 /* optional, but gets called even for disabled plugins */
1698 g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
1699 if (func == NULL)
1700 return;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001701 g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
Richard Hughesf58ac732020-05-12 15:23:44 +01001702 func (self, attrs);
Richard Hughes196c6c62020-05-11 19:42:47 +01001703}
1704
1705/**
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001706 * fu_plugin_add_udev_subsystem:
Richard Hughes2c0635a2018-09-04 14:52:46 +01001707 * @self: a #FuPlugin
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001708 * @subsystem: a subsystem name, e.g. `pciport`
1709 *
1710 * Registers the udev subsystem to be watched by the daemon.
1711 *
1712 * Plugins can use this method only in fu_plugin_init()
Mario Limonciello1a680f32019-11-25 19:44:53 -06001713 *
1714 * Since: 1.1.2
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001715 **/
1716void
Richard Hughes12724852018-09-04 13:53:44 +01001717fu_plugin_add_udev_subsystem (FuPlugin *self, const gchar *subsystem)
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001718{
Richard Hughes12724852018-09-04 13:53:44 +01001719 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesea327fc2020-06-22 15:23:29 +01001720 if (priv->udev_subsystems == NULL)
1721 priv->udev_subsystems = g_ptr_array_new_with_free_func (g_free);
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001722 for (guint i = 0; i < priv->udev_subsystems->len; i++) {
1723 const gchar *subsystem_tmp = g_ptr_array_index (priv->udev_subsystems, i);
1724 if (g_strcmp0 (subsystem_tmp, subsystem) == 0)
1725 return;
1726 }
1727 g_debug ("added udev subsystem watch of %s", subsystem);
1728 g_ptr_array_add (priv->udev_subsystems, g_strdup (subsystem));
1729}
1730
Richard Hughes989acf12019-10-05 20:16:47 +01001731/**
1732 * fu_plugin_set_device_gtype:
1733 * @self: a #FuPlugin
1734 * @device_gtype: a #GType `FU_TYPE_DEVICE`
1735 *
1736 * Sets the device #GType which is used when creating devices.
1737 *
1738 * If this method is used then fu_plugin_usb_device_added() is not called, and
1739 * instead the object is created in the daemon for the plugin.
1740 *
1741 * Plugins can use this method only in fu_plugin_init()
1742 *
1743 * Since: 1.3.3
1744 **/
1745void
1746fu_plugin_set_device_gtype (FuPlugin *self, GType device_gtype)
1747{
1748 FuPluginPrivate *priv = GET_PRIVATE (self);
1749 priv->device_gtype = device_gtype;
1750}
1751
Mario Limonciello1a680f32019-11-25 19:44:53 -06001752/**
1753 * fu_plugin_add_firmware_gtype:
1754 * @self: a #FuPlugin
1755 * @id: A string describing the type
1756 * @gtype: a #GType `FU_TYPE_DEVICE`
1757 *
1758 * Adds a firmware #GType which is used when creating devices.
1759 * *
1760 * Plugins can use this method only in fu_plugin_init()
1761 *
1762 * Since: 1.3.3
1763 **/
Richard Hughes95c98a92019-10-22 16:03:15 +01001764void
1765fu_plugin_add_firmware_gtype (FuPlugin *self, const gchar *id, GType gtype)
1766{
1767 g_signal_emit (self, signals[SIGNAL_ADD_FIRMWARE_GTYPE], 0, id, gtype);
1768}
1769
Richard Hughes989acf12019-10-05 20:16:47 +01001770static gboolean
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001771fu_plugin_check_supported_device (FuPlugin *self, FuDevice *device)
1772{
1773 GPtrArray *instance_ids = fu_device_get_instance_ids (device);
1774 for (guint i = 0; i < instance_ids->len; i++) {
1775 const gchar *instance_id = g_ptr_array_index (instance_ids, i);
1776 g_autofree gchar *guid = fwupd_guid_hash_string (instance_id);
1777 if (fu_plugin_check_supported (self, guid))
1778 return TRUE;
1779 }
1780 return FALSE;
1781}
1782
1783static gboolean
Richard Hughes989acf12019-10-05 20:16:47 +01001784fu_plugin_usb_device_added (FuPlugin *self, FuUsbDevice *device, GError **error)
1785{
1786 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001787 GType device_gtype = fu_device_get_specialized_gtype (FU_DEVICE (device));
Richard Hughes989acf12019-10-05 20:16:47 +01001788 g_autoptr(FuDevice) dev = NULL;
1789 g_autoptr(FuDeviceLocker) locker = NULL;
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001790
1791 /* fall back to plugin default */
1792 if (device_gtype == G_TYPE_INVALID)
1793 device_gtype = priv->device_gtype;
1794
1795 /* create new device and incorporate existing properties */
1796 dev = g_object_new (device_gtype, NULL);
1797 fu_device_incorporate (dev, FU_DEVICE (device));
Richard Hughes0f66a022020-02-19 18:54:38 +00001798 if (!fu_plugin_runner_device_created (self, dev, error))
1799 return FALSE;
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001800
1801 /* there are a lot of different devices that match, but not all respond
1802 * well to opening -- so limit some ones with issued updates */
1803 if (fu_device_has_flag (dev, FWUPD_DEVICE_FLAG_ONLY_SUPPORTED)) {
1804 if (!fu_device_probe (dev, error))
1805 return FALSE;
1806 fu_device_convert_instance_ids (dev);
1807 if (!fu_plugin_check_supported_device (self, dev)) {
1808 g_autofree gchar *guids = fu_device_get_guids_as_str (dev);
1809 g_debug ("%s has no updates, so ignoring device", guids);
1810 return TRUE;
1811 }
1812 }
1813
1814 /* open and add */
1815 locker = fu_device_locker_new (dev, error);
1816 if (locker == NULL)
1817 return FALSE;
1818 fu_plugin_device_add (self, dev);
Richard Hughes6a078702020-05-09 20:36:33 +01001819 fu_plugin_runner_device_added (self, dev);
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001820 return TRUE;
1821}
1822
1823static gboolean
1824fu_plugin_udev_device_added (FuPlugin *self, FuUdevDevice *device, GError **error)
1825{
1826 FuPluginPrivate *priv = GET_PRIVATE (self);
1827 GType device_gtype = fu_device_get_specialized_gtype (FU_DEVICE (device));
1828 g_autoptr(FuDevice) dev = NULL;
1829 g_autoptr(FuDeviceLocker) locker = NULL;
1830
1831 /* fall back to plugin default */
1832 if (device_gtype == G_TYPE_INVALID)
1833 device_gtype = priv->device_gtype;
1834
1835 /* create new device and incorporate existing properties */
1836 dev = g_object_new (device_gtype, NULL);
Richard Hughes989acf12019-10-05 20:16:47 +01001837 fu_device_incorporate (FU_DEVICE (dev), FU_DEVICE (device));
Richard Hughes0f66a022020-02-19 18:54:38 +00001838 if (!fu_plugin_runner_device_created (self, dev, error))
1839 return FALSE;
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001840
1841 /* there are a lot of different devices that match, but not all respond
1842 * well to opening -- so limit some ones with issued updates */
1843 if (fu_device_has_flag (dev, FWUPD_DEVICE_FLAG_ONLY_SUPPORTED)) {
1844 if (!fu_device_probe (dev, error))
1845 return FALSE;
1846 fu_device_convert_instance_ids (dev);
1847 if (!fu_plugin_check_supported_device (self, dev)) {
1848 g_autofree gchar *guids = fu_device_get_guids_as_str (dev);
1849 g_debug ("%s has no updates, so ignoring device", guids);
1850 return TRUE;
1851 }
1852 }
1853
1854 /* open and add */
Richard Hughes989acf12019-10-05 20:16:47 +01001855 locker = fu_device_locker_new (dev, error);
1856 if (locker == NULL)
1857 return FALSE;
1858 fu_plugin_device_add (self, FU_DEVICE (dev));
Richard Hughes6a078702020-05-09 20:36:33 +01001859 fu_plugin_runner_device_added (self, dev);
Richard Hughes989acf12019-10-05 20:16:47 +01001860 return TRUE;
1861}
1862
Mario Limonciello1a680f32019-11-25 19:44:53 -06001863/**
1864 * fu_plugin_runner_usb_device_added:
1865 * @self: a #FuPlugin
1866 * @device: a #FuUsbDevice
1867 * @error: a #GError or NULL
1868 *
1869 * Call the usb_device_added routine for the plugin
1870 *
1871 * Returns: #TRUE for success, #FALSE for failure
1872 *
1873 * Since: 1.0.2
1874 **/
Richard Hughes104f6512017-11-24 11:44:57 +00001875gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001876fu_plugin_runner_usb_device_added (FuPlugin *self, FuUsbDevice *device, GError **error)
Richard Hughes104f6512017-11-24 11:44:57 +00001877{
Richard Hughes12724852018-09-04 13:53:44 +01001878 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes104f6512017-11-24 11:44:57 +00001879 FuPluginUsbDeviceAddedFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001880 g_autoptr(GError) error_local = NULL;
Richard Hughes104f6512017-11-24 11:44:57 +00001881
1882 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001883 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes104f6512017-11-24 11:44:57 +00001884 return TRUE;
Richard Hughes639da472018-01-06 22:35:04 +00001885
1886 /* no object loaded */
Richard Hughes104f6512017-11-24 11:44:57 +00001887 if (priv->module == NULL)
1888 return TRUE;
1889
1890 /* optional */
1891 g_module_symbol (priv->module, "fu_plugin_usb_device_added", (gpointer *) &func);
Richard Hughes989acf12019-10-05 20:16:47 +01001892 if (func == NULL) {
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001893 if (priv->device_gtype != G_TYPE_INVALID ||
1894 fu_device_get_specialized_gtype (FU_DEVICE (device)) != G_TYPE_INVALID) {
Mario Limonciello0e500322019-10-17 18:41:04 -05001895 if (!fu_plugin_usb_device_added (self, device, error))
Mario Limoncielloa9be5362019-10-12 13:17:45 -05001896 return FALSE;
Richard Hughes989acf12019-10-05 20:16:47 +01001897 }
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001898 return TRUE;
Richard Hughes989acf12019-10-05 20:16:47 +01001899 }
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001900 g_debug ("usb_device_added(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001901 if (!func (self, device, &error_local)) {
1902 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001903 g_critical ("unset plugin error in usb_device_added(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001904 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001905 g_set_error_literal (&error_local,
1906 FWUPD_ERROR,
1907 FWUPD_ERROR_INTERNAL,
1908 "unspecified error");
1909 }
1910 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1911 "failed to add device using on %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001912 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001913 return FALSE;
Richard Hughes104f6512017-11-24 11:44:57 +00001914 }
1915 return TRUE;
1916}
1917
Mario Limonciello1a680f32019-11-25 19:44:53 -06001918/**
1919 * fu_plugin_runner_udev_device_added:
1920 * @self: a #FuPlugin
1921 * @device: a #FuUdevDevice
1922 * @error: a #GError or NULL
1923 *
1924 * Call the udev_device_added routine for the plugin
1925 *
1926 * Returns: #TRUE for success, #FALSE for failure
1927 *
1928 * Since: 1.0.2
1929 **/
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001930gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001931fu_plugin_runner_udev_device_added (FuPlugin *self, FuUdevDevice *device, GError **error)
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001932{
Richard Hughes12724852018-09-04 13:53:44 +01001933 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001934 FuPluginUdevDeviceAddedFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001935 g_autoptr(GError) error_local = NULL;
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001936
1937 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001938 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001939 return TRUE;
1940
1941 /* no object loaded */
1942 if (priv->module == NULL)
1943 return TRUE;
1944
1945 /* optional */
1946 g_module_symbol (priv->module, "fu_plugin_udev_device_added", (gpointer *) &func);
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001947 if (func == NULL) {
1948 if (priv->device_gtype != G_TYPE_INVALID ||
1949 fu_device_get_specialized_gtype (FU_DEVICE (device)) != G_TYPE_INVALID) {
Mario Limonciello0e500322019-10-17 18:41:04 -05001950 if (!fu_plugin_udev_device_added (self, device, error))
Mario Limoncielloa9be5362019-10-12 13:17:45 -05001951 return FALSE;
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001952 }
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001953 return TRUE;
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001954 }
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001955 g_debug ("udev_device_added(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001956 if (!func (self, device, &error_local)) {
1957 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001958 g_critical ("unset plugin error in udev_device_added(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001959 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001960 g_set_error_literal (&error_local,
1961 FWUPD_ERROR,
1962 FWUPD_ERROR_INTERNAL,
1963 "unspecified error");
1964 }
1965 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1966 "failed to add device using on %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001967 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001968 return FALSE;
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001969 }
1970 return TRUE;
1971}
1972
Mario Limonciello1a680f32019-11-25 19:44:53 -06001973/**
1974 * fu_plugin_runner_udev_device_changed:
1975 * @self: a #FuPlugin
1976 * @device: a #FuUdevDevice
1977 * @error: a #GError or NULL
1978 *
1979 * Call the udev_device_changed routine for the plugin
1980 *
1981 * Returns: #TRUE for success, #FALSE for failure
1982 *
1983 * Since: 1.0.2
1984 **/
Richard Hughes5e952ce2019-08-26 11:09:46 +01001985gboolean
1986fu_plugin_runner_udev_device_changed (FuPlugin *self, FuUdevDevice *device, GError **error)
1987{
1988 FuPluginPrivate *priv = GET_PRIVATE (self);
1989 FuPluginUdevDeviceAddedFunc func = NULL;
1990 g_autoptr(GError) error_local = NULL;
1991
1992 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001993 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes5e952ce2019-08-26 11:09:46 +01001994 return TRUE;
1995
1996 /* no object loaded */
1997 if (priv->module == NULL)
1998 return TRUE;
1999
2000 /* optional */
2001 g_module_symbol (priv->module, "fu_plugin_udev_device_changed", (gpointer *) &func);
Mario Limonciello6d235142020-09-10 21:35:17 -05002002 if (func == NULL)
Richard Hughes5e952ce2019-08-26 11:09:46 +01002003 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002004 g_debug ("udev_device_changed(%s)", fu_plugin_get_name (self));
Richard Hughes5e952ce2019-08-26 11:09:46 +01002005 if (!func (self, device, &error_local)) {
2006 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05002007 g_critical ("unset plugin error in udev_device_changed(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002008 fu_plugin_get_name (self));
Richard Hughes5e952ce2019-08-26 11:09:46 +01002009 g_set_error_literal (&error_local,
2010 FWUPD_ERROR,
2011 FWUPD_ERROR_INTERNAL,
2012 "unspecified error");
2013 }
2014 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
2015 "failed to change device on %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002016 fu_plugin_get_name (self));
Richard Hughes5e952ce2019-08-26 11:09:46 +01002017 return FALSE;
2018 }
2019 return TRUE;
2020}
2021
Mario Limonciello1a680f32019-11-25 19:44:53 -06002022/**
Richard Hughes6a078702020-05-09 20:36:33 +01002023 * fu_plugin_runner_device_added:
2024 * @self: a #FuPlugin
2025 * @device: a #FuDevice
2026 *
2027 * Call the device_added routine for the plugin
2028 *
2029 * Since: 1.5.0
2030 **/
2031void
2032fu_plugin_runner_device_added (FuPlugin *self, FuDevice *device)
2033{
2034 FuPluginPrivate *priv = GET_PRIVATE (self);
2035 FuPluginDeviceRegisterFunc func = NULL;
2036
2037 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002038 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes6a078702020-05-09 20:36:33 +01002039 return;
2040 if (priv->module == NULL)
2041 return;
2042
2043 /* optional */
2044 g_module_symbol (priv->module, "fu_plugin_device_added", (gpointer *) &func);
2045 if (func == NULL)
2046 return;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002047 g_debug ("fu_plugin_device_added(%s)", fu_plugin_get_name (self));
Richard Hughes6a078702020-05-09 20:36:33 +01002048 func (self, device);
2049}
2050
2051/**
Mario Limonciello1a680f32019-11-25 19:44:53 -06002052 * fu_plugin_runner_device_removed:
2053 * @self: a #FuPlugin
2054 * @device: a #FuDevice
2055 *
2056 * Call the device_removed routine for the plugin
2057 *
2058 * Since: 1.1.2
2059 **/
Richard Hughese1fd34d2017-08-24 14:19:51 +01002060void
Richard Hughes12724852018-09-04 13:53:44 +01002061fu_plugin_runner_device_removed (FuPlugin *self, FuDevice *device)
Mario Limoncielloe260ead2018-09-01 09:19:24 -05002062{
2063 g_autoptr(GError) error_local= NULL;
2064
Richard Hughes12724852018-09-04 13:53:44 +01002065 if (!fu_plugin_runner_device_generic (self, device,
Mario Limoncielloe260ead2018-09-01 09:19:24 -05002066 "fu_plugin_device_removed",
Richard Hughes4b303802019-10-04 13:22:51 +01002067 NULL,
Mario Limoncielloe260ead2018-09-01 09:19:24 -05002068 &error_local))
2069 g_warning ("%s", error_local->message);
2070}
2071
Mario Limonciello1a680f32019-11-25 19:44:53 -06002072/**
2073 * fu_plugin_runner_device_register:
2074 * @self: a #FuPlugin
2075 * @device: a #FuDevice
2076 *
2077 * Call the device_registered routine for the plugin
2078 *
2079 * Since: 0.9.7
2080 **/
Mario Limoncielloe260ead2018-09-01 09:19:24 -05002081void
Richard Hughes12724852018-09-04 13:53:44 +01002082fu_plugin_runner_device_register (FuPlugin *self, FuDevice *device)
Richard Hughese1fd34d2017-08-24 14:19:51 +01002083{
Richard Hughes12724852018-09-04 13:53:44 +01002084 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughese1fd34d2017-08-24 14:19:51 +01002085 FuPluginDeviceRegisterFunc func = NULL;
2086
2087 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002088 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughese1fd34d2017-08-24 14:19:51 +01002089 return;
Richard Hughes34834102017-11-21 21:55:00 +00002090 if (priv->module == NULL)
2091 return;
Richard Hughese1fd34d2017-08-24 14:19:51 +01002092
Mario Limonciello4910b242018-06-22 15:04:21 -05002093 /* don't notify plugins on their own devices */
Richard Hughes12724852018-09-04 13:53:44 +01002094 if (g_strcmp0 (fu_device_get_plugin (device), fu_plugin_get_name (self)) == 0)
Mario Limonciello4910b242018-06-22 15:04:21 -05002095 return;
2096
Richard Hughese1fd34d2017-08-24 14:19:51 +01002097 /* optional */
2098 g_module_symbol (priv->module, "fu_plugin_device_registered", (gpointer *) &func);
2099 if (func != NULL) {
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002100 g_debug ("fu_plugin_device_registered(%s)", fu_plugin_get_name (self));
Richard Hughes12724852018-09-04 13:53:44 +01002101 func (self, device);
Richard Hughese1fd34d2017-08-24 14:19:51 +01002102 }
2103}
2104
Mario Limonciello1a680f32019-11-25 19:44:53 -06002105/**
Richard Hughes0f66a022020-02-19 18:54:38 +00002106 * fu_plugin_runner_device_created:
2107 * @self: a #FuPlugin
2108 * @device: a #FuDevice
2109 * @error: a #GError or NULL
2110 *
2111 * Call the device_created routine for the plugin
2112 *
2113 * Returns: #TRUE for success, #FALSE for failure
2114 *
Mario Limonciello96117d12020-02-28 10:17:56 -06002115 * Since: 1.4.0
Richard Hughes0f66a022020-02-19 18:54:38 +00002116 **/
2117gboolean
2118fu_plugin_runner_device_created (FuPlugin *self, FuDevice *device, GError **error)
2119{
2120 FuPluginPrivate *priv = GET_PRIVATE (self);
2121 FuPluginDeviceFunc func = NULL;
2122
2123 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002124 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes0f66a022020-02-19 18:54:38 +00002125 return TRUE;
2126 if (priv->module == NULL)
2127 return TRUE;
2128
2129 /* optional */
2130 g_module_symbol (priv->module, "fu_plugin_device_created", (gpointer *) &func);
2131 if (func == NULL)
2132 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002133 g_debug ("fu_plugin_device_created(%s)", fu_plugin_get_name (self));
Richard Hughes0f66a022020-02-19 18:54:38 +00002134 return func (self, device, error);
2135}
2136
2137/**
Mario Limonciello1a680f32019-11-25 19:44:53 -06002138 * fu_plugin_runner_verify:
2139 * @self: a #FuPlugin
2140 * @device: a #FuDevice
2141 * @flags: #FuPluginVerifyFlags
2142 * @error: A #GError or NULL
2143 *
2144 * Call into the plugin's verify routine
2145 *
2146 * Returns: #TRUE for success, #FALSE for failure
2147 *
2148 * Since: 0.8.0
2149 **/
Richard Hughescff38bc2016-12-12 12:03:37 +00002150gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002151fu_plugin_runner_verify (FuPlugin *self,
Richard Hughescff38bc2016-12-12 12:03:37 +00002152 FuDevice *device,
2153 FuPluginVerifyFlags flags,
2154 GError **error)
2155{
Richard Hughes12724852018-09-04 13:53:44 +01002156 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes7b8b2022016-12-12 16:15:03 +00002157 FuPluginVerifyFunc func = NULL;
Richard Hughesababbb72017-06-15 20:18:36 +01002158 GPtrArray *checksums;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002159 g_autoptr(GError) error_local = NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +00002160
2161 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002162 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughescff38bc2016-12-12 12:03:37 +00002163 return TRUE;
2164
Richard Hughes639da472018-01-06 22:35:04 +00002165 /* no object loaded */
2166 if (priv->module == NULL)
2167 return TRUE;
2168
Richard Hughescff38bc2016-12-12 12:03:37 +00002169 /* optional */
2170 g_module_symbol (priv->module, "fu_plugin_verify", (gpointer *) &func);
Richard Hughes7f677212019-10-05 16:19:40 +01002171 if (func == NULL) {
Richard Hughes7f677212019-10-05 16:19:40 +01002172 return fu_plugin_device_read_firmware (self, device, error);
2173 }
Richard Hughes1812fc72018-12-14 11:37:54 +00002174
2175 /* clear any existing verification checksums */
2176 checksums = fu_device_get_checksums (device);
2177 g_ptr_array_set_size (checksums, 0);
2178
Richard Hughesc9223be2019-03-18 08:46:42 +00002179 /* run additional detach */
2180 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes42f33df2019-10-05 20:52:33 +01002181 "fu_plugin_update_detach",
Richard Hughes4b303802019-10-04 13:22:51 +01002182 fu_plugin_device_detach,
Richard Hughesc9223be2019-03-18 08:46:42 +00002183 error))
2184 return FALSE;
2185
Richard Hughes1812fc72018-12-14 11:37:54 +00002186 /* run vfunc */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002187 g_debug ("verify(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002188 if (!func (self, device, flags, &error_local)) {
Richard Hughesc9223be2019-03-18 08:46:42 +00002189 g_autoptr(GError) error_attach = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002190 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05002191 g_critical ("unset plugin error in verify(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002192 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002193 g_set_error_literal (&error_local,
2194 FWUPD_ERROR,
2195 FWUPD_ERROR_INTERNAL,
2196 "unspecified error");
2197 }
2198 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
2199 "failed to verify using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002200 fu_plugin_get_name (self));
Richard Hughesc9223be2019-03-18 08:46:42 +00002201 /* make the device "work" again, but don't prefix the error */
2202 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes42f33df2019-10-05 20:52:33 +01002203 "fu_plugin_update_attach",
Richard Hughes4b303802019-10-04 13:22:51 +01002204 fu_plugin_device_attach,
Richard Hughesc9223be2019-03-18 08:46:42 +00002205 &error_attach)) {
2206 g_warning ("failed to attach whilst aborting verify(): %s",
2207 error_attach->message);
2208 }
Richard Hughesd0905142016-03-13 09:46:49 +00002209 return FALSE;
2210 }
Richard Hughesc9223be2019-03-18 08:46:42 +00002211
2212 /* run optional attach */
2213 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes42f33df2019-10-05 20:52:33 +01002214 "fu_plugin_update_attach",
Richard Hughes4b303802019-10-04 13:22:51 +01002215 fu_plugin_device_attach,
Richard Hughesc9223be2019-03-18 08:46:42 +00002216 error))
2217 return FALSE;
2218
2219 /* success */
Richard Hughesd0905142016-03-13 09:46:49 +00002220 return TRUE;
2221}
2222
Mario Limonciello1a680f32019-11-25 19:44:53 -06002223/**
2224 * fu_plugin_runner_activate:
2225 * @self: a #FuPlugin
2226 * @device: a #FuDevice
2227 * @error: A #GError or NULL
2228 *
2229 * Call into the plugin's activate routine
2230 *
2231 * Returns: #TRUE for success, #FALSE for failure
2232 *
2233 * Since: 1.2.6
2234 **/
Richard Hughesd0905142016-03-13 09:46:49 +00002235gboolean
Mario Limonciello96a0dd52019-02-25 13:50:03 -06002236fu_plugin_runner_activate (FuPlugin *self, FuDevice *device, GError **error)
2237{
2238 guint64 flags;
2239
2240 /* final check */
2241 flags = fu_device_get_flags (device);
2242 if ((flags & FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION) == 0) {
2243 g_set_error (error,
2244 FWUPD_ERROR,
2245 FWUPD_ERROR_NOT_SUPPORTED,
2246 "Device %s does not need activation",
2247 fu_device_get_id (device));
2248 return FALSE;
2249 }
2250
2251 /* run vfunc */
2252 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes4b303802019-10-04 13:22:51 +01002253 "fu_plugin_activate",
2254 fu_plugin_device_activate,
2255 error))
Mario Limonciello96a0dd52019-02-25 13:50:03 -06002256 return FALSE;
2257
2258 /* update with correct flags */
2259 fu_device_remove_flag (device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION);
2260 fu_device_set_modified (device, (guint64) g_get_real_time () / G_USEC_PER_SEC);
2261 return TRUE;
2262}
2263
Mario Limonciello1a680f32019-11-25 19:44:53 -06002264/**
2265 * fu_plugin_runner_unlock:
2266 * @self: a #FuPlugin
2267 * @device: a #FuDevice
2268 * @error: A #GError or NULL
2269 *
2270 * Call into the plugin's unlock routine
2271 *
2272 * Returns: #TRUE for success, #FALSE for failure
2273 *
2274 * Since: 0.8.0
2275 **/
Mario Limonciello96a0dd52019-02-25 13:50:03 -06002276gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002277fu_plugin_runner_unlock (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughesd0905142016-03-13 09:46:49 +00002278{
Richard Hughescff38bc2016-12-12 12:03:37 +00002279 guint64 flags;
Richard Hughescff38bc2016-12-12 12:03:37 +00002280
2281 /* final check */
2282 flags = fu_device_get_flags (device);
2283 if ((flags & FWUPD_DEVICE_FLAG_LOCKED) == 0) {
2284 g_set_error (error,
2285 FWUPD_ERROR,
2286 FWUPD_ERROR_NOT_SUPPORTED,
2287 "Device %s is not locked",
2288 fu_device_get_id (device));
2289 return FALSE;
2290 }
2291
Richard Hughes9c4b5312017-11-14 11:34:53 +00002292 /* run vfunc */
Richard Hughes12724852018-09-04 13:53:44 +01002293 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes4b303802019-10-04 13:22:51 +01002294 "fu_plugin_unlock",
2295 NULL,
2296 error))
Richard Hughes9c4b5312017-11-14 11:34:53 +00002297 return FALSE;
Richard Hughescff38bc2016-12-12 12:03:37 +00002298
2299 /* update with correct flags */
2300 flags = fu_device_get_flags (device);
2301 fu_device_set_flags (device, flags &= ~FWUPD_DEVICE_FLAG_LOCKED);
2302 fu_device_set_modified (device, (guint64) g_get_real_time () / G_USEC_PER_SEC);
2303 return TRUE;
2304}
2305
Mario Limonciello1a680f32019-11-25 19:44:53 -06002306/**
2307 * fu_plugin_runner_update:
2308 * @self: a #FuPlugin
2309 * @device: a #FuDevice
2310 * @blob_fw: A #GBytes
2311 * @flags: A #FwupdInstallFlags
2312 * @error: A #GError or NULL
2313 *
2314 * Call into the plugin's update routine
2315 *
2316 * Returns: #TRUE for success, #FALSE for failure
2317 *
2318 * Since: 0.8.0
2319 **/
Richard Hughescff38bc2016-12-12 12:03:37 +00002320gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002321fu_plugin_runner_update (FuPlugin *self,
Richard Hughesa785a1c2017-08-25 16:00:58 +01002322 FuDevice *device,
Richard Hughesa785a1c2017-08-25 16:00:58 +01002323 GBytes *blob_fw,
2324 FwupdInstallFlags flags,
2325 GError **error)
Richard Hughescff38bc2016-12-12 12:03:37 +00002326{
Richard Hughes12724852018-09-04 13:53:44 +01002327 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesa785a1c2017-08-25 16:00:58 +01002328 FuPluginUpdateFunc update_func;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002329 g_autoptr(GError) error_local = NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +00002330
2331 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002332 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED)) {
Richard Hughes41c15482018-02-01 22:07:21 +00002333 g_debug ("plugin not enabled, skipping");
Richard Hughesd0905142016-03-13 09:46:49 +00002334 return TRUE;
Richard Hughes41c15482018-02-01 22:07:21 +00002335 }
Richard Hughesd0905142016-03-13 09:46:49 +00002336
Richard Hughes639da472018-01-06 22:35:04 +00002337 /* no object loaded */
Richard Hughes41c15482018-02-01 22:07:21 +00002338 if (priv->module == NULL) {
2339 g_debug ("module not enabled, skipping");
Richard Hughes639da472018-01-06 22:35:04 +00002340 return TRUE;
Richard Hughes41c15482018-02-01 22:07:21 +00002341 }
Richard Hughes639da472018-01-06 22:35:04 +00002342
Richard Hughesd0905142016-03-13 09:46:49 +00002343 /* optional */
Richard Hughesa785a1c2017-08-25 16:00:58 +01002344 g_module_symbol (priv->module, "fu_plugin_update", (gpointer *) &update_func);
2345 if (update_func == NULL) {
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002346 g_debug ("superclassed write_firmware(%s)", fu_plugin_get_name (self));
Richard Hughes4b303802019-10-04 13:22:51 +01002347 return fu_plugin_device_write_firmware (self, device, blob_fw, flags, error);
Richard Hughesa785a1c2017-08-25 16:00:58 +01002348 }
Richard Hughesd0905142016-03-13 09:46:49 +00002349
Richard Hughescff38bc2016-12-12 12:03:37 +00002350 /* online */
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002351 if (!update_func (self, device, blob_fw, flags, &error_local)) {
2352 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05002353 g_critical ("unset plugin error in update(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002354 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002355 g_set_error_literal (&error_local,
Richard Hughes3c8ada32018-10-12 10:08:58 +01002356 FWUPD_ERROR,
2357 FWUPD_ERROR_INTERNAL,
2358 "unspecified error");
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002359 return FALSE;
Richard Hughes3c8ada32018-10-12 10:08:58 +01002360 }
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002361 fu_device_set_update_error (device, error_local->message);
2362 g_propagate_error (error, g_steal_pointer (&error_local));
Richard Hughescff38bc2016-12-12 12:03:37 +00002363 return FALSE;
2364 }
2365
Richard Hughesf556d372017-06-15 19:49:18 +01002366 /* no longer valid */
Richard Hughesf8039642019-01-16 12:22:22 +00002367 if (!fu_device_has_flag (device, FWUPD_DEVICE_FLAG_NEEDS_REBOOT) &&
2368 !fu_device_has_flag (device, FWUPD_DEVICE_FLAG_NEEDS_SHUTDOWN)) {
Richard Hughes08435162018-12-12 10:34:16 +00002369 GPtrArray *checksums = fu_device_get_checksums (device);
2370 g_ptr_array_set_size (checksums, 0);
2371 }
Richard Hughesf556d372017-06-15 19:49:18 +01002372
Richard Hughes019a1bc2019-11-26 10:19:33 +00002373 /* success */
Richard Hughesd0905142016-03-13 09:46:49 +00002374 return TRUE;
2375}
Richard Hughescff38bc2016-12-12 12:03:37 +00002376
Mario Limonciello1a680f32019-11-25 19:44:53 -06002377/**
2378 * fu_plugin_runner_clear_results:
2379 * @self: a #FuPlugin
2380 * @device: a #FuDevice
2381 * @error: A #GError or NULL
2382 *
2383 * Call into the plugin's clear results routine
2384 *
2385 * Returns: #TRUE for success, #FALSE for failure
2386 *
2387 * Since: 0.8.0
2388 **/
Richard Hughescff38bc2016-12-12 12:03:37 +00002389gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002390fu_plugin_runner_clear_results (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughescff38bc2016-12-12 12:03:37 +00002391{
Richard Hughes12724852018-09-04 13:53:44 +01002392 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes7b8b2022016-12-12 16:15:03 +00002393 FuPluginDeviceFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002394 g_autoptr(GError) error_local = NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +00002395
2396 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002397 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughescff38bc2016-12-12 12:03:37 +00002398 return TRUE;
2399
Richard Hughes639da472018-01-06 22:35:04 +00002400 /* no object loaded */
2401 if (priv->module == NULL)
2402 return TRUE;
2403
Richard Hughes65e44ca2018-01-30 17:26:30 +00002404 /* optional */
Richard Hughescd644902019-11-01 12:35:17 +00002405 g_module_symbol (priv->module, "fu_plugin_clear_results", (gpointer *) &func);
Richard Hughes65e44ca2018-01-30 17:26:30 +00002406 if (func == NULL)
Richard Hughescff38bc2016-12-12 12:03:37 +00002407 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002408 g_debug ("clear_result(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002409 if (!func (self, device, &error_local)) {
2410 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05002411 g_critical ("unset plugin error in clear_result(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002412 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002413 g_set_error_literal (&error_local,
2414 FWUPD_ERROR,
2415 FWUPD_ERROR_INTERNAL,
2416 "unspecified error");
2417 }
2418 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
2419 "failed to clear_result using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002420 fu_plugin_get_name (self));
Richard Hughescff38bc2016-12-12 12:03:37 +00002421 return FALSE;
2422 }
Richard Hughes65e44ca2018-01-30 17:26:30 +00002423 return TRUE;
Richard Hughescff38bc2016-12-12 12:03:37 +00002424}
2425
Mario Limonciello1a680f32019-11-25 19:44:53 -06002426/**
2427 * fu_plugin_runner_get_results:
2428 * @self: a #FuPlugin
2429 * @device: a #FuDevice
2430 * @error: A #GError or NULL
2431 *
2432 * Call into the plugin's get results routine
2433 *
2434 * Returns: #TRUE for success, #FALSE for failure
2435 *
2436 * Since: 0.8.0
2437 **/
Richard Hughescff38bc2016-12-12 12:03:37 +00002438gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002439fu_plugin_runner_get_results (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughescff38bc2016-12-12 12:03:37 +00002440{
Richard Hughes12724852018-09-04 13:53:44 +01002441 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes7b8b2022016-12-12 16:15:03 +00002442 FuPluginDeviceFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002443 g_autoptr(GError) error_local = NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +00002444
2445 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002446 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughescff38bc2016-12-12 12:03:37 +00002447 return TRUE;
2448
Richard Hughes639da472018-01-06 22:35:04 +00002449 /* no object loaded */
2450 if (priv->module == NULL)
2451 return TRUE;
2452
Richard Hughes65e44ca2018-01-30 17:26:30 +00002453 /* optional */
Richard Hughescff38bc2016-12-12 12:03:37 +00002454 g_module_symbol (priv->module, "fu_plugin_get_results", (gpointer *) &func);
Richard Hughes65e44ca2018-01-30 17:26:30 +00002455 if (func == NULL)
Richard Hughescff38bc2016-12-12 12:03:37 +00002456 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002457 g_debug ("get_results(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002458 if (!func (self, device, &error_local)) {
2459 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05002460 g_critical ("unset plugin error in get_results(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002461 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002462 g_set_error_literal (&error_local,
2463 FWUPD_ERROR,
2464 FWUPD_ERROR_INTERNAL,
2465 "unspecified error");
2466 }
2467 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
2468 "failed to get_results using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002469 fu_plugin_get_name (self));
Richard Hughescff38bc2016-12-12 12:03:37 +00002470 return FALSE;
2471 }
Richard Hughescff38bc2016-12-12 12:03:37 +00002472 return TRUE;
2473}
2474
Richard Hughes08a37992017-09-12 12:57:43 +01002475/**
2476 * fu_plugin_get_order:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002477 * @self: a #FuPlugin
Richard Hughes08a37992017-09-12 12:57:43 +01002478 *
2479 * Gets the plugin order, where higher numbers are run after lower
2480 * numbers.
2481 *
2482 * Returns: the integer value
Mario Limonciello1a680f32019-11-25 19:44:53 -06002483 *
2484 * Since: 1.0.0
Richard Hughes08a37992017-09-12 12:57:43 +01002485 **/
2486guint
Richard Hughes12724852018-09-04 13:53:44 +01002487fu_plugin_get_order (FuPlugin *self)
Richard Hughes08a37992017-09-12 12:57:43 +01002488{
Richard Hughes12724852018-09-04 13:53:44 +01002489 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes08a37992017-09-12 12:57:43 +01002490 return priv->order;
2491}
2492
2493/**
2494 * fu_plugin_set_order:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002495 * @self: a #FuPlugin
Richard Hughes08a37992017-09-12 12:57:43 +01002496 * @order: a integer value
2497 *
2498 * Sets the plugin order, where higher numbers are run after lower
2499 * numbers.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002500 *
2501 * Since: 1.0.0
Richard Hughes08a37992017-09-12 12:57:43 +01002502 **/
2503void
Richard Hughes12724852018-09-04 13:53:44 +01002504fu_plugin_set_order (FuPlugin *self, guint order)
Richard Hughes08a37992017-09-12 12:57:43 +01002505{
Richard Hughes12724852018-09-04 13:53:44 +01002506 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes08a37992017-09-12 12:57:43 +01002507 priv->order = order;
2508}
2509
2510/**
Richard Hughes81c427c2018-08-06 15:20:17 +01002511 * fu_plugin_get_priority:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002512 * @self: a #FuPlugin
Richard Hughes81c427c2018-08-06 15:20:17 +01002513 *
2514 * Gets the plugin priority, where higher numbers are better.
2515 *
2516 * Returns: the integer value
Mario Limonciello1a680f32019-11-25 19:44:53 -06002517 *
2518 * Since: 1.1.1
Richard Hughes81c427c2018-08-06 15:20:17 +01002519 **/
2520guint
Richard Hughes12724852018-09-04 13:53:44 +01002521fu_plugin_get_priority (FuPlugin *self)
Richard Hughes81c427c2018-08-06 15:20:17 +01002522{
Richard Hughes12724852018-09-04 13:53:44 +01002523 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes81c427c2018-08-06 15:20:17 +01002524 return priv->priority;
2525}
2526
2527/**
2528 * fu_plugin_set_priority:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002529 * @self: a #FuPlugin
Richard Hughes81c427c2018-08-06 15:20:17 +01002530 * @priority: a integer value
2531 *
2532 * Sets the plugin priority, where higher numbers are better.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002533 *
2534 * Since: 1.0.0
Richard Hughes81c427c2018-08-06 15:20:17 +01002535 **/
2536void
Richard Hughes12724852018-09-04 13:53:44 +01002537fu_plugin_set_priority (FuPlugin *self, guint priority)
Richard Hughes81c427c2018-08-06 15:20:17 +01002538{
Richard Hughes12724852018-09-04 13:53:44 +01002539 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes81c427c2018-08-06 15:20:17 +01002540 priv->priority = priority;
2541}
2542
2543/**
Richard Hughes08a37992017-09-12 12:57:43 +01002544 * fu_plugin_add_rule:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002545 * @self: a #FuPlugin
Richard Hughes08a37992017-09-12 12:57:43 +01002546 * @rule: a #FuPluginRule, e.g. %FU_PLUGIN_RULE_CONFLICTS
Richard Hughes4eada342017-10-03 21:20:32 +01002547 * @name: a plugin name, e.g. `upower`
Richard Hughes08a37992017-09-12 12:57:43 +01002548 *
2549 * If the plugin name is found, the rule will be used to sort the plugin list,
2550 * for example the plugin specified by @name will be ordered after this plugin
2551 * when %FU_PLUGIN_RULE_RUN_AFTER is used.
2552 *
2553 * NOTE: The depsolver is iterative and may not solve overly-complicated rules;
2554 * If depsolving fails then fwupd will not start.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002555 *
2556 * Since: 1.0.0
Richard Hughes08a37992017-09-12 12:57:43 +01002557 **/
2558void
Richard Hughes12724852018-09-04 13:53:44 +01002559fu_plugin_add_rule (FuPlugin *self, FuPluginRule rule, const gchar *name)
Richard Hughes08a37992017-09-12 12:57:43 +01002560{
Richard Hughes12724852018-09-04 13:53:44 +01002561 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes11c59412020-06-22 15:29:48 +01002562 if (priv->rules[rule] == NULL)
2563 priv->rules[rule] = g_ptr_array_new_with_free_func (g_free);
Richard Hughes08a37992017-09-12 12:57:43 +01002564 g_ptr_array_add (priv->rules[rule], g_strdup (name));
Richard Hughes75b965d2018-11-15 13:51:21 +00002565 g_signal_emit (self, signals[SIGNAL_RULES_CHANGED], 0);
Richard Hughes08a37992017-09-12 12:57:43 +01002566}
2567
2568/**
2569 * fu_plugin_get_rules:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002570 * @self: a #FuPlugin
Richard Hughes08a37992017-09-12 12:57:43 +01002571 * @rule: a #FuPluginRule, e.g. %FU_PLUGIN_RULE_CONFLICTS
2572 *
2573 * Gets the plugin IDs that should be run after this plugin.
2574 *
Richard Hughes11c59412020-06-22 15:29:48 +01002575 * Returns: (element-type utf8) (transfer none) (nullable): the list of plugin names, e.g. ['appstream']
Mario Limonciello1a680f32019-11-25 19:44:53 -06002576 *
2577 * Since: 1.0.0
Richard Hughes08a37992017-09-12 12:57:43 +01002578 **/
2579GPtrArray *
Richard Hughes12724852018-09-04 13:53:44 +01002580fu_plugin_get_rules (FuPlugin *self, FuPluginRule rule)
Richard Hughes08a37992017-09-12 12:57:43 +01002581{
Richard Hughes12724852018-09-04 13:53:44 +01002582 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughesdad35972019-12-06 11:00:25 +00002583 g_return_val_if_fail (rule < FU_PLUGIN_RULE_LAST, NULL);
Richard Hughes08a37992017-09-12 12:57:43 +01002584 return priv->rules[rule];
2585}
2586
Richard Hughes80b79bb2018-01-11 21:11:06 +00002587/**
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002588 * fu_plugin_has_rule:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002589 * @self: a #FuPlugin
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002590 * @rule: a #FuPluginRule, e.g. %FU_PLUGIN_RULE_CONFLICTS
2591 * @name: a plugin name, e.g. `upower`
2592 *
Richard Hughes87fb9ff2018-06-28 12:55:59 +01002593 * Gets the plugin IDs that should be run after this plugin.
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002594 *
2595 * Returns: %TRUE if the name exists for the specific rule
Mario Limonciello1a680f32019-11-25 19:44:53 -06002596 *
2597 * Since: 1.0.0
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002598 **/
2599gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002600fu_plugin_has_rule (FuPlugin *self, FuPluginRule rule, const gchar *name)
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002601{
Richard Hughes12724852018-09-04 13:53:44 +01002602 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes11c59412020-06-22 15:29:48 +01002603 if (priv->rules[rule] == NULL)
2604 return FALSE;
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002605 for (guint i = 0; i < priv->rules[rule]->len; i++) {
2606 const gchar *tmp = g_ptr_array_index (priv->rules[rule], i);
2607 if (g_strcmp0 (tmp, name) == 0)
2608 return TRUE;
2609 }
2610 return FALSE;
2611}
2612
2613/**
Richard Hughes80b79bb2018-01-11 21:11:06 +00002614 * fu_plugin_add_report_metadata:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002615 * @self: a #FuPlugin
Richard Hughes80b79bb2018-01-11 21:11:06 +00002616 * @key: a string, e.g. `FwupdateVersion`
2617 * @value: a string, e.g. `10`
2618 *
2619 * Sets any additional metadata to be included in the firmware report to aid
2620 * debugging problems.
2621 *
2622 * Any data included here will be sent to the metadata server after user
2623 * confirmation.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002624 *
2625 * Since: 1.0.4
Richard Hughes80b79bb2018-01-11 21:11:06 +00002626 **/
2627void
Richard Hughes12724852018-09-04 13:53:44 +01002628fu_plugin_add_report_metadata (FuPlugin *self, const gchar *key, const gchar *value)
Richard Hughes80b79bb2018-01-11 21:11:06 +00002629{
Richard Hughes12724852018-09-04 13:53:44 +01002630 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes1d900f72020-06-22 15:17:39 +01002631 if (priv->report_metadata == NULL) {
2632 priv->report_metadata = g_hash_table_new_full (g_str_hash,
2633 g_str_equal,
2634 g_free,
2635 g_free);
2636 }
Richard Hughes80b79bb2018-01-11 21:11:06 +00002637 g_hash_table_insert (priv->report_metadata, g_strdup (key), g_strdup (value));
2638}
2639
2640/**
2641 * fu_plugin_get_report_metadata:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002642 * @self: a #FuPlugin
Richard Hughes80b79bb2018-01-11 21:11:06 +00002643 *
2644 * Returns the list of additional metadata to be added when filing a report.
2645 *
Richard Hughes1d900f72020-06-22 15:17:39 +01002646 * Returns: (transfer none) (nullable): the map of report metadata
Mario Limonciello1a680f32019-11-25 19:44:53 -06002647 *
2648 * Since: 1.0.4
Richard Hughes80b79bb2018-01-11 21:11:06 +00002649 **/
2650GHashTable *
Richard Hughes12724852018-09-04 13:53:44 +01002651fu_plugin_get_report_metadata (FuPlugin *self)
Richard Hughes80b79bb2018-01-11 21:11:06 +00002652{
Richard Hughes12724852018-09-04 13:53:44 +01002653 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes80b79bb2018-01-11 21:11:06 +00002654 return priv->report_metadata;
2655}
2656
Mario Limonciello963dc422018-02-27 14:26:58 -06002657/**
2658 * fu_plugin_get_config_value:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002659 * @self: a #FuPlugin
Mario Limonciello963dc422018-02-27 14:26:58 -06002660 * @key: A settings key
2661 *
2662 * Return the value of a key if it's been configured
2663 *
2664 * Since: 1.0.6
2665 **/
2666gchar *
Richard Hughes12724852018-09-04 13:53:44 +01002667fu_plugin_get_config_value (FuPlugin *self, const gchar *key)
Mario Limonciello963dc422018-02-27 14:26:58 -06002668{
Richard Hughes4be17d12018-05-30 20:36:29 +01002669 g_autofree gchar *conf_dir = NULL;
Mario Limonciello963dc422018-02-27 14:26:58 -06002670 g_autofree gchar *conf_file = NULL;
2671 g_autofree gchar *conf_path = NULL;
2672 g_autoptr(GKeyFile) keyfile = NULL;
2673 const gchar *plugin_name;
2674
Richard Hughes4be17d12018-05-30 20:36:29 +01002675 conf_dir = fu_common_get_path (FU_PATH_KIND_SYSCONFDIR_PKG);
Richard Hughes12724852018-09-04 13:53:44 +01002676 plugin_name = fu_plugin_get_name (self);
Mario Limonciello963dc422018-02-27 14:26:58 -06002677 conf_file = g_strdup_printf ("%s.conf", plugin_name);
Richard Hughes4be17d12018-05-30 20:36:29 +01002678 conf_path = g_build_filename (conf_dir, conf_file, NULL);
Mario Limonciello963dc422018-02-27 14:26:58 -06002679 if (!g_file_test (conf_path, G_FILE_TEST_IS_REGULAR))
2680 return NULL;
2681 keyfile = g_key_file_new ();
2682 if (!g_key_file_load_from_file (keyfile, conf_path,
2683 G_KEY_FILE_NONE, NULL))
2684 return NULL;
2685 return g_key_file_get_string (keyfile, plugin_name, key, NULL);
2686}
2687
Richard Hughes8c71a3f2018-05-22 19:19:52 +01002688/**
Richard Hughes334ba792020-02-19 20:44:56 +00002689 * fu_plugin_get_config_value_boolean:
2690 * @self: a #FuPlugin
2691 * @key: A settings key
2692 *
2693 * Return the boolean value of a key if it's been configured
2694 *
2695 * Returns: %TRUE if the value is `true` (case insensitive), %FALSE otherwise
2696 *
Mario Limonciello96117d12020-02-28 10:17:56 -06002697 * Since: 1.4.0
Richard Hughes334ba792020-02-19 20:44:56 +00002698 **/
2699gboolean
2700fu_plugin_get_config_value_boolean (FuPlugin *self, const gchar *key)
2701{
2702 g_autofree gchar *tmp = fu_plugin_get_config_value (self, key);
2703 if (tmp == NULL)
2704 return FALSE;
Richard Hughes5337a432020-02-21 12:04:32 +00002705 return g_ascii_strcasecmp (tmp, "true") == 0;
Richard Hughes334ba792020-02-19 20:44:56 +00002706}
2707
2708/**
Richard Hughes8c71a3f2018-05-22 19:19:52 +01002709 * fu_plugin_name_compare:
2710 * @plugin1: first #FuPlugin to compare.
2711 * @plugin2: second #FuPlugin to compare.
2712 *
2713 * Compares two plugins by their names.
2714 *
2715 * Returns: 1, 0 or -1 if @plugin1 is greater, equal, or less than @plugin2.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002716 *
2717 * Since: 1.0.8
Richard Hughes8c71a3f2018-05-22 19:19:52 +01002718 **/
2719gint
2720fu_plugin_name_compare (FuPlugin *plugin1, FuPlugin *plugin2)
2721{
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002722 return g_strcmp0 (fu_plugin_get_name (plugin1), fu_plugin_get_name (plugin2));
Richard Hughes8c71a3f2018-05-22 19:19:52 +01002723}
2724
2725/**
2726 * fu_plugin_order_compare:
2727 * @plugin1: first #FuPlugin to compare.
2728 * @plugin2: second #FuPlugin to compare.
2729 *
2730 * Compares two plugins by their depsolved order.
2731 *
2732 * Returns: 1, 0 or -1 if @plugin1 is greater, equal, or less than @plugin2.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002733 *
2734 * Since: 1.0.8
Richard Hughes8c71a3f2018-05-22 19:19:52 +01002735 **/
2736gint
2737fu_plugin_order_compare (FuPlugin *plugin1, FuPlugin *plugin2)
2738{
2739 FuPluginPrivate *priv1 = fu_plugin_get_instance_private (plugin1);
2740 FuPluginPrivate *priv2 = fu_plugin_get_instance_private (plugin2);
2741 if (priv1->order < priv2->order)
2742 return -1;
2743 if (priv1->order > priv2->order)
2744 return 1;
2745 return 0;
2746}
2747
Richard Hughescff38bc2016-12-12 12:03:37 +00002748static void
2749fu_plugin_class_init (FuPluginClass *klass)
2750{
2751 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2752 object_class->finalize = fu_plugin_finalize;
2753 signals[SIGNAL_DEVICE_ADDED] =
2754 g_signal_new ("device-added",
2755 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2756 G_STRUCT_OFFSET (FuPluginClass, device_added),
2757 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2758 G_TYPE_NONE, 1, FU_TYPE_DEVICE);
2759 signals[SIGNAL_DEVICE_REMOVED] =
2760 g_signal_new ("device-removed",
2761 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2762 G_STRUCT_OFFSET (FuPluginClass, device_removed),
2763 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2764 G_TYPE_NONE, 1, FU_TYPE_DEVICE);
Richard Hughese1fd34d2017-08-24 14:19:51 +01002765 signals[SIGNAL_DEVICE_REGISTER] =
2766 g_signal_new ("device-register",
2767 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2768 G_STRUCT_OFFSET (FuPluginClass, device_register),
2769 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2770 G_TYPE_NONE, 1, FU_TYPE_DEVICE);
Richard Hughes362d6d72017-01-07 21:42:14 +00002771 signals[SIGNAL_RECOLDPLUG] =
2772 g_signal_new ("recoldplug",
2773 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2774 G_STRUCT_OFFSET (FuPluginClass, recoldplug),
2775 NULL, NULL, g_cclosure_marshal_VOID__VOID,
2776 G_TYPE_NONE, 0);
Richard Hughes399859e2020-05-11 19:44:03 +01002777 signals[SIGNAL_SECURITY_CHANGED] =
2778 g_signal_new ("security-changed",
2779 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2780 G_STRUCT_OFFSET (FuPluginClass, security_changed),
2781 NULL, NULL, g_cclosure_marshal_VOID__VOID,
2782 G_TYPE_NONE, 0);
Richard Hughesb0829032017-01-10 09:27:08 +00002783 signals[SIGNAL_SET_COLDPLUG_DELAY] =
2784 g_signal_new ("set-coldplug-delay",
2785 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2786 G_STRUCT_OFFSET (FuPluginClass, set_coldplug_delay),
2787 NULL, NULL, g_cclosure_marshal_VOID__UINT,
2788 G_TYPE_NONE, 1, G_TYPE_UINT);
Richard Hughesaabdc372018-11-14 10:11:08 +00002789 signals[SIGNAL_CHECK_SUPPORTED] =
2790 g_signal_new ("check-supported",
2791 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2792 G_STRUCT_OFFSET (FuPluginClass, check_supported),
2793 NULL, NULL, g_cclosure_marshal_generic,
2794 G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
Richard Hughes75b965d2018-11-15 13:51:21 +00002795 signals[SIGNAL_RULES_CHANGED] =
2796 g_signal_new ("rules-changed",
2797 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2798 G_STRUCT_OFFSET (FuPluginClass, rules_changed),
2799 NULL, NULL, g_cclosure_marshal_VOID__VOID,
2800 G_TYPE_NONE, 0);
Richard Hughes95c98a92019-10-22 16:03:15 +01002801 signals[SIGNAL_ADD_FIRMWARE_GTYPE] =
2802 g_signal_new ("add-firmware-gtype",
2803 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2804 G_STRUCT_OFFSET (FuPluginClass, add_firmware_gtype),
2805 NULL, NULL, g_cclosure_marshal_generic,
2806 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_GTYPE);
Richard Hughescff38bc2016-12-12 12:03:37 +00002807}
2808
2809static void
Richard Hughes12724852018-09-04 13:53:44 +01002810fu_plugin_init (FuPlugin *self)
Richard Hughescff38bc2016-12-12 12:03:37 +00002811{
Richard Hughes12724852018-09-04 13:53:44 +01002812 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes161e9b52019-06-12 14:22:45 +01002813 g_rw_lock_init (&priv->devices_mutex);
Richard Hughescff38bc2016-12-12 12:03:37 +00002814}
2815
2816static void
2817fu_plugin_finalize (GObject *object)
2818{
Richard Hughes12724852018-09-04 13:53:44 +01002819 FuPlugin *self = FU_PLUGIN (object);
2820 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughescff38bc2016-12-12 12:03:37 +00002821 FuPluginInitFunc func = NULL;
2822
Richard Hughesaae22e42020-06-22 21:32:59 +01002823 g_rw_lock_clear (&priv->devices_mutex);
2824
Richard Hughescff38bc2016-12-12 12:03:37 +00002825 /* optional */
2826 if (priv->module != NULL) {
2827 g_module_symbol (priv->module, "fu_plugin_destroy", (gpointer *) &func);
2828 if (func != NULL) {
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002829 g_debug ("destroy(%s)", fu_plugin_get_name (self));
Richard Hughes12724852018-09-04 13:53:44 +01002830 func (self);
Richard Hughescff38bc2016-12-12 12:03:37 +00002831 }
2832 }
2833
Richard Hughes11c59412020-06-22 15:29:48 +01002834 for (guint i = 0; i < FU_PLUGIN_RULE_LAST; i++) {
2835 if (priv->rules[i] != NULL)
2836 g_ptr_array_unref (priv->rules[i]);
2837 }
Richard Hughescff38bc2016-12-12 12:03:37 +00002838 if (priv->usb_ctx != NULL)
2839 g_object_unref (priv->usb_ctx);
Richard Hughesb8f8db22017-04-25 15:56:00 +01002840 if (priv->hwids != NULL)
Richard Hughesd7704d42017-08-08 20:29:09 +01002841 g_object_unref (priv->hwids);
Richard Hughes9c028f02017-10-28 21:14:28 +01002842 if (priv->quirks != NULL)
2843 g_object_unref (priv->quirks);
Richard Hughes9d6e0e72018-08-24 20:20:17 +01002844 if (priv->udev_subsystems != NULL)
2845 g_ptr_array_unref (priv->udev_subsystems);
Richard Hughes49e5e052017-09-03 12:15:41 +01002846 if (priv->smbios != NULL)
2847 g_object_unref (priv->smbios);
Richard Hughes275d3b42018-04-20 16:40:37 +01002848 if (priv->runtime_versions != NULL)
2849 g_hash_table_unref (priv->runtime_versions);
Richard Hughes34e0dab2018-04-20 16:43:00 +01002850 if (priv->compile_versions != NULL)
2851 g_hash_table_unref (priv->compile_versions);
Richard Hughes1d900f72020-06-22 15:17:39 +01002852 if (priv->report_metadata != NULL)
2853 g_hash_table_unref (priv->report_metadata);
Richard Hughes371f6b22020-06-22 15:21:17 +01002854 if (priv->devices != NULL)
2855 g_hash_table_unref (priv->devices);
Richard Hughes84999302019-05-02 10:18:32 +01002856 g_free (priv->build_hash);
Richard Hughescff38bc2016-12-12 12:03:37 +00002857 g_free (priv->data);
Mario Limonciello3f9a1c12018-06-06 14:06:40 -05002858 /* Must happen as the last step to avoid prematurely
2859 * freeing memory held by the plugin */
Richard Hughes862ec5c2020-05-22 14:38:02 +01002860#ifdef RUNNING_ON_VALGRIND
2861 if (priv->module != NULL && RUNNING_ON_VALGRIND == 0)
2862#else
Mario Limonciello3f9a1c12018-06-06 14:06:40 -05002863 if (priv->module != NULL)
Mario Limonciello3f9a1c12018-06-06 14:06:40 -05002864#endif
Richard Hughes862ec5c2020-05-22 14:38:02 +01002865 g_module_close (priv->module);
Richard Hughescff38bc2016-12-12 12:03:37 +00002866
2867 G_OBJECT_CLASS (fu_plugin_parent_class)->finalize (object);
2868}
2869
Mario Limonciello1a680f32019-11-25 19:44:53 -06002870/**
2871 * fu_plugin_new:
2872 *
2873 * Creates a new #FuPlugin
2874 *
2875 * Since: 0.8.0
2876 **/
Richard Hughescff38bc2016-12-12 12:03:37 +00002877FuPlugin *
2878fu_plugin_new (void)
2879{
Richard Hughes12724852018-09-04 13:53:44 +01002880 return FU_PLUGIN (g_object_new (FU_TYPE_PLUGIN, NULL));
Richard Hughescff38bc2016-12-12 12:03:37 +00002881}