blob: de246f33a0b9d6647353ed733b4db2012f7c782c [file] [log] [blame]
Richard Hughes02c90d82018-08-09 12:13:03 +01001/*
Richard Hughes5c9b1fc2021-01-07 14:20:49 +00002 * Copyright (C) 2016 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;
Richard Hughes08a37992017-09-12 12:57:43 +010039 guint order;
Richard Hughes81c427c2018-08-06 15:20:17 +010040 guint priority;
Richard Hughes08a37992017-09-12 12:57:43 +010041 GPtrArray *rules[FU_PLUGIN_RULE_LAST];
Richard Hughes68ab1e42021-01-13 14:01:17 +000042 GPtrArray *devices; /* (nullable) (element-type FuDevice) */
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 Hughesfaf2afe2021-01-13 14:00:20 +000051 GHashTable *cache; /* (nullable): platform_id:GObject */
52 GRWLock cache_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 Hughesf58ac732020-05-12 15:23:44 +0100100typedef void (*FuPluginSecurityAttrsFunc) (FuPlugin *self,
101 FuSecurityAttrs *attrs);
Richard Hughescff38bc2016-12-12 12:03:37 +0000102
Richard Hughes57d18222017-01-10 16:02:59 +0000103/**
Mario Limonciello52e75ba2019-11-22 13:21:19 -0600104 * fu_plugin_is_open:
105 * @self: A #FuPlugin
106 *
107 * Determines if the plugin is opened
108 *
109 * Returns: TRUE for opened, FALSE for not
110 *
111 * Since: 1.3.5
112 **/
113gboolean
114fu_plugin_is_open (FuPlugin *self)
115{
116 FuPluginPrivate *priv = GET_PRIVATE (self);
117 return priv->module != NULL;
118}
119
120/**
Richard Hughes57d18222017-01-10 16:02:59 +0000121 * fu_plugin_get_name:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100122 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000123 *
124 * Gets the plugin name.
125 *
126 * Returns: a plugin name, or %NULL for unknown.
127 *
128 * Since: 0.8.0
129 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000130const gchar *
Richard Hughes12724852018-09-04 13:53:44 +0100131fu_plugin_get_name (FuPlugin *self)
Richard Hughesd0905142016-03-13 09:46:49 +0000132{
Richard Hughes12724852018-09-04 13:53:44 +0100133 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100134 return fwupd_plugin_get_name (FWUPD_PLUGIN (self));
Richard Hughescff38bc2016-12-12 12:03:37 +0000135}
Richard Hughesd0905142016-03-13 09:46:49 +0000136
Mario Limonciello1a680f32019-11-25 19:44:53 -0600137/**
138 * fu_plugin_set_name:
139 * @self: A #FuPlugin
140 * @name: A string
141 *
142 * Sets the plugin name.
143 *
144 * Since: 0.8.0
145 **/
Richard Hughes34834102017-11-21 21:55:00 +0000146void
Richard Hughes12724852018-09-04 13:53:44 +0100147fu_plugin_set_name (FuPlugin *self, const gchar *name)
Richard Hughes34834102017-11-21 21:55:00 +0000148{
Richard Hughes12724852018-09-04 13:53:44 +0100149 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100150 fwupd_plugin_set_name (FWUPD_PLUGIN (self), name);
Richard Hughes34834102017-11-21 21:55:00 +0000151}
152
Richard Hughes57d18222017-01-10 16:02:59 +0000153/**
Richard Hughesf425d292019-01-18 17:57:39 +0000154 * fu_plugin_set_build_hash:
155 * @self: A #FuPlugin
156 * @build_hash: A checksum
157 *
158 * Sets the plugin build hash, typically a SHA256 checksum. All plugins must
159 * set the correct checksum to avoid the daemon being marked as tainted.
160 *
161 * Since: 1.2.4
162 **/
163void
164fu_plugin_set_build_hash (FuPlugin *self, const gchar *build_hash)
165{
166 FuPluginPrivate *priv = GET_PRIVATE (self);
167 g_return_if_fail (FU_IS_PLUGIN (self));
168 g_return_if_fail (build_hash != NULL);
Richard Hughes382524d2021-01-28 13:14:35 +0000169
170 /* not changed */
171 if (g_strcmp0 (priv->build_hash, build_hash) == 0)
172 return;
173
Richard Hughesf425d292019-01-18 17:57:39 +0000174 g_free (priv->build_hash);
175 priv->build_hash = g_strdup (build_hash);
176}
177
Mario Limonciello1a680f32019-11-25 19:44:53 -0600178/**
179 * fu_plugin_get_build_hash:
180 * @self: A #FuPlugin
181 *
182 * Gets the build hash a plugin was generated with.
183 *
184 * Returns: (transfer none): a #gchar, or %NULL for unset.
185 *
186 * Since: 1.2.4
187 **/
Richard Hughesf425d292019-01-18 17:57:39 +0000188const gchar *
189fu_plugin_get_build_hash (FuPlugin *self)
190{
191 FuPluginPrivate *priv = GET_PRIVATE (self);
192 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
193 return priv->build_hash;
194}
195
196/**
Richard Hughes57d18222017-01-10 16:02:59 +0000197 * fu_plugin_cache_lookup:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100198 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000199 * @id: the key
200 *
201 * Finds an object in the per-plugin cache.
202 *
203 * Returns: (transfer none): a #GObject, or %NULL for unfound.
204 *
205 * Since: 0.8.0
206 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000207gpointer
Richard Hughes12724852018-09-04 13:53:44 +0100208fu_plugin_cache_lookup (FuPlugin *self, const gchar *id)
Richard Hughescff38bc2016-12-12 12:03:37 +0000209{
Richard Hughes12724852018-09-04 13:53:44 +0100210 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesfaf2afe2021-01-13 14:00:20 +0000211 g_autoptr(GRWLockReaderLocker) locker = g_rw_lock_reader_locker_new (&priv->cache_mutex);
Richard Hughes12724852018-09-04 13:53:44 +0100212 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughesccd78a92017-01-11 16:57:41 +0000213 g_return_val_if_fail (id != NULL, NULL);
Richard Hughes37d09432018-09-09 10:39:45 +0100214 g_return_val_if_fail (locker != NULL, NULL);
Richard Hughesfaf2afe2021-01-13 14:00:20 +0000215 if (priv->cache == NULL)
Richard Hughes371f6b22020-06-22 15:21:17 +0100216 return NULL;
Richard Hughesfaf2afe2021-01-13 14:00:20 +0000217 return g_hash_table_lookup (priv->cache, id);
Richard Hughescff38bc2016-12-12 12:03:37 +0000218}
Richard Hughesd0905142016-03-13 09:46:49 +0000219
Richard Hughes57d18222017-01-10 16:02:59 +0000220/**
221 * fu_plugin_cache_add:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100222 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000223 * @id: the key
224 * @dev: a #GObject, typically a #FuDevice
225 *
226 * Adds an object to the per-plugin cache.
227 *
228 * Since: 0.8.0
229 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000230void
Richard Hughes12724852018-09-04 13:53:44 +0100231fu_plugin_cache_add (FuPlugin *self, const gchar *id, gpointer dev)
Richard Hughescff38bc2016-12-12 12:03:37 +0000232{
Richard Hughes12724852018-09-04 13:53:44 +0100233 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesfaf2afe2021-01-13 14:00:20 +0000234 g_autoptr(GRWLockWriterLocker) locker = g_rw_lock_writer_locker_new (&priv->cache_mutex);
Richard Hughes12724852018-09-04 13:53:44 +0100235 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughesccd78a92017-01-11 16:57:41 +0000236 g_return_if_fail (id != NULL);
Richard Hughes37d09432018-09-09 10:39:45 +0100237 g_return_if_fail (locker != NULL);
Richard Hughesfaf2afe2021-01-13 14:00:20 +0000238 if (priv->cache == NULL) {
239 priv->cache = g_hash_table_new_full (g_str_hash,
240 g_str_equal,
241 g_free,
242 (GDestroyNotify) g_object_unref);
Richard Hughes371f6b22020-06-22 15:21:17 +0100243 }
Richard Hughesfaf2afe2021-01-13 14:00:20 +0000244 g_hash_table_insert (priv->cache, g_strdup (id), g_object_ref (dev));
Richard Hughescff38bc2016-12-12 12:03:37 +0000245}
246
Richard Hughes57d18222017-01-10 16:02:59 +0000247/**
248 * fu_plugin_cache_remove:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100249 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000250 * @id: the key
251 *
252 * Removes an object from the per-plugin cache.
253 *
254 * Since: 0.8.0
255 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000256void
Richard Hughes12724852018-09-04 13:53:44 +0100257fu_plugin_cache_remove (FuPlugin *self, const gchar *id)
Richard Hughescff38bc2016-12-12 12:03:37 +0000258{
Richard Hughes12724852018-09-04 13:53:44 +0100259 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesfaf2afe2021-01-13 14:00:20 +0000260 g_autoptr(GRWLockWriterLocker) locker = g_rw_lock_writer_locker_new (&priv->cache_mutex);
Richard Hughes12724852018-09-04 13:53:44 +0100261 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughesccd78a92017-01-11 16:57:41 +0000262 g_return_if_fail (id != NULL);
Richard Hughes37d09432018-09-09 10:39:45 +0100263 g_return_if_fail (locker != NULL);
Richard Hughesfaf2afe2021-01-13 14:00:20 +0000264 if (priv->cache == NULL)
Richard Hughes371f6b22020-06-22 15:21:17 +0100265 return;
Richard Hughesfaf2afe2021-01-13 14:00:20 +0000266 g_hash_table_remove (priv->cache, id);
Richard Hughescff38bc2016-12-12 12:03:37 +0000267}
268
Richard Hughes57d18222017-01-10 16:02:59 +0000269/**
270 * fu_plugin_get_data:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100271 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000272 *
Richard Hughes4eada342017-10-03 21:20:32 +0100273 * Gets the per-plugin allocated private data. This will return %NULL unless
274 * fu_plugin_alloc_data() has been called by the plugin.
Richard Hughes57d18222017-01-10 16:02:59 +0000275 *
Richard Hughes4eada342017-10-03 21:20:32 +0100276 * Returns: (transfer none): a pointer to a structure, or %NULL for unset.
Richard Hughes57d18222017-01-10 16:02:59 +0000277 *
278 * Since: 0.8.0
279 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000280FuPluginData *
Richard Hughes12724852018-09-04 13:53:44 +0100281fu_plugin_get_data (FuPlugin *self)
Richard Hughescff38bc2016-12-12 12:03:37 +0000282{
Richard Hughes12724852018-09-04 13:53:44 +0100283 FuPluginPrivate *priv = GET_PRIVATE (self);
284 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughescff38bc2016-12-12 12:03:37 +0000285 return priv->data;
286}
287
Richard Hughes57d18222017-01-10 16:02:59 +0000288/**
Richard Hughes00f66f62019-11-27 11:42:53 +0000289 * fu_plugin_alloc_data: (skip):
Richard Hughes2c0635a2018-09-04 14:52:46 +0100290 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000291 * @data_sz: the size to allocate
292 *
293 * Allocates the per-plugin allocated private data.
294 *
295 * Returns: (transfer full): a pointer to a structure, or %NULL for unset.
296 *
297 * Since: 0.8.0
298 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000299FuPluginData *
Richard Hughes12724852018-09-04 13:53:44 +0100300fu_plugin_alloc_data (FuPlugin *self, gsize data_sz)
Richard Hughescff38bc2016-12-12 12:03:37 +0000301{
Richard Hughes12724852018-09-04 13:53:44 +0100302 FuPluginPrivate *priv = GET_PRIVATE (self);
303 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughes44dee882017-01-11 08:31:10 +0000304 if (priv->data != NULL) {
305 g_critical ("fu_plugin_alloc_data() already used by plugin");
306 return priv->data;
307 }
Richard Hughescff38bc2016-12-12 12:03:37 +0000308 priv->data = g_malloc0 (data_sz);
309 return priv->data;
Richard Hughesd0905142016-03-13 09:46:49 +0000310}
311
Richard Hughes57d18222017-01-10 16:02:59 +0000312/**
313 * fu_plugin_get_usb_context:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100314 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000315 *
Richard Hughes9e9b73f2021-02-09 13:37:41 +0000316 * This used to get the shared USB context that all plugins can use; it now
317 * returns %NULL;
Richard Hughes57d18222017-01-10 16:02:59 +0000318 *
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 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughes9e9b73f2021-02-09 13:37:41 +0000327 return NULL;
Richard Hughesbc93e4a2016-12-08 17:29:51 +0000328}
329
Mario Limonciello1a680f32019-11-25 19:44:53 -0600330/**
331 * fu_plugin_set_usb_context:
332 * @self: A #FuPlugin
333 * @usb_ctx: A #FGUsbContext
334 *
Richard Hughes9e9b73f2021-02-09 13:37:41 +0000335 * This used to set the shared USB context for a plugin. It now does nothing.
Mario Limonciello1a680f32019-11-25 19:44:53 -0600336 *
337 * Since: 0.8.0
338 **/
Richard Hughesbc93e4a2016-12-08 17:29:51 +0000339void
Richard Hughes12724852018-09-04 13:53:44 +0100340fu_plugin_set_usb_context (FuPlugin *self, GUsbContext *usb_ctx)
Richard Hughesbc93e4a2016-12-08 17:29:51 +0000341{
Richard Hughescff38bc2016-12-12 12:03:37 +0000342}
343
Richard Hughes57d18222017-01-10 16:02:59 +0000344/**
345 * fu_plugin_get_enabled:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100346 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000347 *
Richard Hughes4eada342017-10-03 21:20:32 +0100348 * Returns if the plugin is enabled. Plugins may self-disable using
349 * fu_plugin_set_enabled() or can be disabled by the daemon.
Richard Hughes57d18222017-01-10 16:02:59 +0000350 *
351 * Returns: %TRUE if the plugin is currently enabled.
352 *
353 * Since: 0.8.0
354 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000355gboolean
Richard Hughes12724852018-09-04 13:53:44 +0100356fu_plugin_get_enabled (FuPlugin *self)
Richard Hughescff38bc2016-12-12 12:03:37 +0000357{
Richard Hughes12724852018-09-04 13:53:44 +0100358 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100359 return !fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED);
Richard Hughesbc93e4a2016-12-08 17:29:51 +0000360}
361
Richard Hughes57d18222017-01-10 16:02:59 +0000362/**
363 * fu_plugin_set_enabled:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100364 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000365 * @enabled: the enabled value
366 *
367 * Enables or disables a plugin. Plugins can self-disable at any point.
368 *
369 * Since: 0.8.0
370 **/
Richard Hughesd0905142016-03-13 09:46:49 +0000371void
Richard Hughes12724852018-09-04 13:53:44 +0100372fu_plugin_set_enabled (FuPlugin *self, gboolean enabled)
Richard Hughesd0905142016-03-13 09:46:49 +0000373{
Richard Hughes12724852018-09-04 13:53:44 +0100374 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100375 if (enabled) {
376 fwupd_plugin_remove_flag (FWUPD_PLUGIN (self),
377 FWUPD_PLUGIN_FLAG_DISABLED);
378 } else {
379 fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_DISABLED);
380 }
Richard Hughescff38bc2016-12-12 12:03:37 +0000381}
382
Mario Limonciello1a680f32019-11-25 19:44:53 -0600383/**
384 * fu_plugin_guess_name_from_fn:
385 * @filename: filename to guess
386 *
387 * Tries to guess the name of the plugin from a filename
388 *
389 * Returns: (transfer full): the guessed name of the plugin
390 *
391 * Since: 1.0.8
392 **/
Richard Hughes1e456bc2018-05-10 20:16:16 +0100393gchar *
394fu_plugin_guess_name_from_fn (const gchar *filename)
395{
396 const gchar *prefix = "libfu_plugin_";
397 gchar *name;
398 gchar *str = g_strstr_len (filename, -1, prefix);
399 if (str == NULL)
400 return NULL;
401 name = g_strdup (str + strlen (prefix));
402 g_strdelimit (name, ".", '\0');
403 return name;
404}
405
Mario Limonciello1a680f32019-11-25 19:44:53 -0600406/**
407 * fu_plugin_open:
408 * @self: A #FuPlugin
409 * @filename: The shared object filename to open
410 * @error: A #GError or NULL
411 *
412 * Opens the plugin module
413 *
414 * Returns: TRUE for success, FALSE for fail
415 *
416 * Since: 0.8.0
417 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000418gboolean
Richard Hughes12724852018-09-04 13:53:44 +0100419fu_plugin_open (FuPlugin *self, const gchar *filename, GError **error)
Richard Hughescff38bc2016-12-12 12:03:37 +0000420{
Richard Hughes12724852018-09-04 13:53:44 +0100421 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughescff38bc2016-12-12 12:03:37 +0000422 FuPluginInitFunc func = NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +0000423
Richard Hughes6a489a92020-12-22 10:32:06 +0000424 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
425 g_return_val_if_fail (filename != NULL, FALSE);
426 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
427
Richard Hughescff38bc2016-12-12 12:03:37 +0000428 priv->module = g_module_open (filename, 0);
429 if (priv->module == NULL) {
430 g_set_error (error,
431 G_IO_ERROR,
432 G_IO_ERROR_FAILED,
Mario Limonciellof5605532019-11-04 07:49:50 -0600433 "failed to open plugin %s: %s",
434 filename, g_module_error ());
Mario Limoncielloc3a81732020-10-20 09:16:18 -0500435 fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_FAILED_OPEN);
436 fu_plugin_add_flag (self, FWUPD_PLUGIN_FLAG_USER_WARNING);
Richard Hughescff38bc2016-12-12 12:03:37 +0000437 return FALSE;
438 }
439
440 /* set automatically */
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100441 if (fu_plugin_get_name (self) == NULL) {
442 g_autofree gchar *str = fu_plugin_guess_name_from_fn (filename);
443 fu_plugin_set_name (self, str);
444 }
Richard Hughesd0905142016-03-13 09:46:49 +0000445
446 /* optional */
Richard Hughescff38bc2016-12-12 12:03:37 +0000447 g_module_symbol (priv->module, "fu_plugin_init", (gpointer *) &func);
448 if (func != NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -0500449 g_debug ("init(%s)", filename);
Richard Hughes12724852018-09-04 13:53:44 +0100450 func (self);
Richard Hughesd0905142016-03-13 09:46:49 +0000451 }
452
Richard Hughescff38bc2016-12-12 12:03:37 +0000453 return TRUE;
454}
455
Richard Hughes203ed842020-11-02 14:25:13 +0000456/* order of usefulness to the user */
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100457static const gchar *
458fu_plugin_build_device_update_error (FuPlugin *self)
459{
460 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_NO_HARDWARE))
461 return "Not updatable as required hardware was not found";
462 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_LEGACY_BIOS))
463 return "Not updatable in legacy BIOS mode";
464 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_CAPSULES_UNSUPPORTED))
Mario Limonciello797da4f2021-01-12 12:38:51 -0600465 return "Not updatable as UEFI capsule updates not enabled in firmware setup";
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100466 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_UNLOCK_REQUIRED))
467 return "Not updatable as requires unlock";
468 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_EFIVAR_NOT_MOUNTED))
469 return "Not updatable as efivarfs was not found";
470 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_ESP_NOT_FOUND))
471 return "Not updatable as UEFI ESP partition not detected";
472 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
473 return "Not updatable as plugin was disabled";
474 return NULL;
475}
476
Richard Hughes68ab1e42021-01-13 14:01:17 +0000477static void
478fu_plugin_ensure_devices (FuPlugin *self)
479{
480 FuPluginPrivate *priv = GET_PRIVATE (self);
481 if (priv->devices != NULL)
482 return;
483 priv->devices = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
484}
485
Richard Hughes57d18222017-01-10 16:02:59 +0000486/**
487 * fu_plugin_device_add:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100488 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000489 * @device: A #FuDevice
490 *
491 * Asks the daemon to add a device to the exported list. If this device ID
492 * has already been added by a different plugin then this request will be
493 * ignored.
494 *
495 * Plugins should use fu_plugin_device_add_delay() if they are not capable of
496 * actually flashing an image to the hardware so that higher-priority plugins
497 * can add the device themselves.
498 *
499 * Since: 0.8.0
500 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000501void
Richard Hughes12724852018-09-04 13:53:44 +0100502fu_plugin_device_add (FuPlugin *self, FuDevice *device)
Richard Hughescff38bc2016-12-12 12:03:37 +0000503{
Richard Hughes68ab1e42021-01-13 14:01:17 +0000504 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes5e447292018-04-27 14:25:54 +0100505 GPtrArray *children;
Richard Hughesc125ec02018-09-05 19:35:17 +0100506 g_autoptr(GError) error = NULL;
Richard Hughes5e447292018-04-27 14:25:54 +0100507
Richard Hughes12724852018-09-04 13:53:44 +0100508 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughesccd78a92017-01-11 16:57:41 +0000509 g_return_if_fail (FU_IS_DEVICE (device));
510
Richard Hughesc125ec02018-09-05 19:35:17 +0100511 /* ensure the device ID is set from the physical and logical IDs */
512 if (!fu_device_ensure_id (device, &error)) {
513 g_warning ("ignoring add: %s", error->message);
514 return;
515 }
516
Richard Hughes68ab1e42021-01-13 14:01:17 +0000517 /* add to array */
518 fu_plugin_ensure_devices (self);
519 g_ptr_array_add (priv->devices, g_object_ref (device));
520
Richard Hughes7bcb8d42020-10-08 15:47:47 +0100521 /* proxy to device where required */
522 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_CLEAR_UPDATABLE)) {
523 g_debug ("plugin %s has _CLEAR_UPDATABLE, so removing from %s",
524 fu_plugin_get_name (self),
525 fu_device_get_id (device));
526 fu_device_remove_flag (device, FWUPD_DEVICE_FLAG_UPDATABLE);
527 }
528 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_USER_WARNING) &&
529 fu_device_get_update_error (device) == NULL) {
530 const gchar *tmp = fu_plugin_build_device_update_error (self);
531 g_debug ("setting %s update error to '%s' from %s",
532 fu_device_get_id (device), tmp, fu_plugin_get_name (self));
533 fu_device_set_update_error (device, tmp);
534 }
535
Richard Hughescff38bc2016-12-12 12:03:37 +0000536 g_debug ("emit added from %s: %s",
Richard Hughes12724852018-09-04 13:53:44 +0100537 fu_plugin_get_name (self),
Richard Hughescff38bc2016-12-12 12:03:37 +0000538 fu_device_get_id (device));
539 fu_device_set_created (device, (guint64) g_get_real_time () / G_USEC_PER_SEC);
Richard Hughes12724852018-09-04 13:53:44 +0100540 fu_device_set_plugin (device, fu_plugin_get_name (self));
541 g_signal_emit (self, signals[SIGNAL_DEVICE_ADDED], 0, device);
Richard Hughes5e447292018-04-27 14:25:54 +0100542
Richard Hughes128c0162018-08-10 11:00:29 +0100543 /* add children if they have not already been added */
Richard Hughes5e447292018-04-27 14:25:54 +0100544 children = fu_device_get_children (device);
545 for (guint i = 0; i < children->len; i++) {
546 FuDevice *child = g_ptr_array_index (children, i);
Richard Hughes128c0162018-08-10 11:00:29 +0100547 if (fu_device_get_created (child) == 0)
Richard Hughes12724852018-09-04 13:53:44 +0100548 fu_plugin_device_add (self, child);
Richard Hughes5e447292018-04-27 14:25:54 +0100549 }
Richard Hughescff38bc2016-12-12 12:03:37 +0000550}
551
Richard Hughese1fd34d2017-08-24 14:19:51 +0100552/**
Richard Hughes68ab1e42021-01-13 14:01:17 +0000553 * fu_plugin_get_devices:
554 * @self: A #FuPlugin
555 *
556 * Returns all devices added by the plugin using fu_plugin_device_add() and
557 * not yet removed with fu_plugin_device_remove().
558 *
559 * Returns: (transfer none) (element-type FuDevice): devices
560 *
561 * Since: 1.5.6
562 **/
563GPtrArray *
564fu_plugin_get_devices (FuPlugin *self)
565{
566 FuPluginPrivate *priv = GET_PRIVATE (self);
567 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
568 fu_plugin_ensure_devices (self);
569 return priv->devices;
570}
571
572/**
Richard Hughese1fd34d2017-08-24 14:19:51 +0100573 * fu_plugin_device_register:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100574 * @self: A #FuPlugin
Richard Hughese1fd34d2017-08-24 14:19:51 +0100575 * @device: A #FuDevice
576 *
577 * Registers the device with other plugins so they can set metadata.
578 *
579 * Plugins do not have to call this manually as this is done automatically
580 * when using fu_plugin_device_add(). They may wish to use this manually
Richard Hughes21eaeef2020-01-14 12:10:01 +0000581 * if for instance the coldplug should be ignored based on the metadata
Richard Hughese1fd34d2017-08-24 14:19:51 +0100582 * set from other plugins.
583 *
584 * Since: 0.9.7
585 **/
586void
Richard Hughes12724852018-09-04 13:53:44 +0100587fu_plugin_device_register (FuPlugin *self, FuDevice *device)
Richard Hughese1fd34d2017-08-24 14:19:51 +0100588{
Richard Hughesc125ec02018-09-05 19:35:17 +0100589 g_autoptr(GError) error = NULL;
590
Richard Hughes12724852018-09-04 13:53:44 +0100591 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughese1fd34d2017-08-24 14:19:51 +0100592 g_return_if_fail (FU_IS_DEVICE (device));
593
Richard Hughesc125ec02018-09-05 19:35:17 +0100594 /* ensure the device ID is set from the physical and logical IDs */
595 if (!fu_device_ensure_id (device, &error)) {
596 g_warning ("ignoring registration: %s", error->message);
597 return;
598 }
599
Richard Hughese1fd34d2017-08-24 14:19:51 +0100600 g_debug ("emit device-register from %s: %s",
Richard Hughes12724852018-09-04 13:53:44 +0100601 fu_plugin_get_name (self),
Richard Hughese1fd34d2017-08-24 14:19:51 +0100602 fu_device_get_id (device));
Richard Hughes12724852018-09-04 13:53:44 +0100603 g_signal_emit (self, signals[SIGNAL_DEVICE_REGISTER], 0, device);
Richard Hughese1fd34d2017-08-24 14:19:51 +0100604}
605
Richard Hughes57d18222017-01-10 16:02:59 +0000606/**
Richard Hughes4eada342017-10-03 21:20:32 +0100607 * fu_plugin_device_remove:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100608 * @self: A #FuPlugin
Richard Hughes57d18222017-01-10 16:02:59 +0000609 * @device: A #FuDevice
610 *
611 * Asks the daemon to remove a device from the exported list.
612 *
613 * Since: 0.8.0
614 **/
Richard Hughescff38bc2016-12-12 12:03:37 +0000615void
Richard Hughes12724852018-09-04 13:53:44 +0100616fu_plugin_device_remove (FuPlugin *self, FuDevice *device)
Richard Hughescff38bc2016-12-12 12:03:37 +0000617{
Richard Hughes68ab1e42021-01-13 14:01:17 +0000618 FuPluginPrivate *priv = GET_PRIVATE (self);
619
Richard Hughes12724852018-09-04 13:53:44 +0100620 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughesccd78a92017-01-11 16:57:41 +0000621 g_return_if_fail (FU_IS_DEVICE (device));
622
Richard Hughes68ab1e42021-01-13 14:01:17 +0000623 /* remove from array */
624 if (priv->devices != NULL)
625 g_ptr_array_remove (priv->devices, device);
626
Richard Hughescff38bc2016-12-12 12:03:37 +0000627 g_debug ("emit removed from %s: %s",
Richard Hughes12724852018-09-04 13:53:44 +0100628 fu_plugin_get_name (self),
Richard Hughescff38bc2016-12-12 12:03:37 +0000629 fu_device_get_id (device));
Richard Hughes12724852018-09-04 13:53:44 +0100630 g_signal_emit (self, signals[SIGNAL_DEVICE_REMOVED], 0, device);
Richard Hughescff38bc2016-12-12 12:03:37 +0000631}
632
Richard Hughes57d18222017-01-10 16:02:59 +0000633/**
Richard Hughes2de8f132018-01-17 09:12:02 +0000634 * fu_plugin_request_recoldplug:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100635 * @self: A #FuPlugin
Richard Hughes362d6d72017-01-07 21:42:14 +0000636 *
637 * Ask all the plugins to coldplug all devices, which will include the prepare()
638 * and cleanup() phases. Duplicate devices added will be ignored.
639 *
640 * Since: 0.8.0
641 **/
642void
Richard Hughes12724852018-09-04 13:53:44 +0100643fu_plugin_request_recoldplug (FuPlugin *self)
Richard Hughes362d6d72017-01-07 21:42:14 +0000644{
Richard Hughes12724852018-09-04 13:53:44 +0100645 g_return_if_fail (FU_IS_PLUGIN (self));
646 g_signal_emit (self, signals[SIGNAL_RECOLDPLUG], 0);
Richard Hughes362d6d72017-01-07 21:42:14 +0000647}
648
Richard Hughesb0829032017-01-10 09:27:08 +0000649/**
Richard Hughes399859e2020-05-11 19:44:03 +0100650 * fu_plugin_security_changed:
651 * @self: A #FuPlugin
652 *
653 * Informs the daemon that the HSI state may have changed.
654 *
655 * Since: 1.5.0
656 **/
657void
658fu_plugin_security_changed (FuPlugin *self)
659{
660 g_return_if_fail (FU_IS_PLUGIN (self));
661 g_signal_emit (self, signals[SIGNAL_SECURITY_CHANGED], 0);
662}
663
664/**
Richard Hughesb8f8db22017-04-25 15:56:00 +0100665 * fu_plugin_check_hwid:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100666 * @self: A #FuPlugin
Richard Hughes4eada342017-10-03 21:20:32 +0100667 * @hwid: A Hardware ID GUID, e.g. `6de5d951-d755-576b-bd09-c5cf66b27234`
Richard Hughesb8f8db22017-04-25 15:56:00 +0100668 *
Richard Hughesd7704d42017-08-08 20:29:09 +0100669 * Checks to see if a specific GUID exists. All hardware IDs on a
Richard Hughesb8f8db22017-04-25 15:56:00 +0100670 * specific system can be shown using the `fwupdmgr hwids` command.
671 *
Richard Hughes4eada342017-10-03 21:20:32 +0100672 * Returns: %TRUE if the HwId is found on the system.
673 *
Richard Hughesb8f8db22017-04-25 15:56:00 +0100674 * Since: 0.9.1
675 **/
676gboolean
Richard Hughes12724852018-09-04 13:53:44 +0100677fu_plugin_check_hwid (FuPlugin *self, const gchar *hwid)
Richard Hughesb8f8db22017-04-25 15:56:00 +0100678{
Richard Hughes12724852018-09-04 13:53:44 +0100679 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesb8f8db22017-04-25 15:56:00 +0100680 if (priv->hwids == NULL)
681 return FALSE;
Richard Hughesd7704d42017-08-08 20:29:09 +0100682 return fu_hwids_has_guid (priv->hwids, hwid);
683}
684
685/**
Patrick Rudolpha60b5472019-10-16 10:43:03 +0200686 * fu_plugin_get_hwid_replace_value:
687 * @self: A #FuPlugin
688 * @keys: A key, e.g. `HardwareID-3` or %FU_HWIDS_KEY_PRODUCT_SKU
689 * @error: A #GError or %NULL
690 *
691 * Gets the replacement value for a specific key. All hardware IDs on a
692 * specific system can be shown using the `fwupdmgr hwids` command.
693 *
694 * Returns: (transfer full): a string, or %NULL for error.
695 *
696 * Since: 1.3.3
697 **/
698gchar *
699fu_plugin_get_hwid_replace_value (FuPlugin *self, const gchar *keys, GError **error)
700{
701 FuPluginPrivate *priv = GET_PRIVATE (self);
702 if (priv->hwids == NULL)
703 return NULL;
704
705 return fu_hwids_get_replace_values (priv->hwids, keys, error);
706}
707
708/**
Richard Hughes69a5f352018-08-08 11:58:15 +0100709 * fu_plugin_get_hwids:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100710 * @self: A #FuPlugin
Richard Hughes69a5f352018-08-08 11:58:15 +0100711 *
712 * Returns all the HWIDs defined in the system. All hardware IDs on a
713 * specific system can be shown using the `fwupdmgr hwids` command.
714 *
Mario Limonciello1a680f32019-11-25 19:44:53 -0600715 * Returns: (transfer none) (element-type utf8): An array of GUIDs
Richard Hughes69a5f352018-08-08 11:58:15 +0100716 *
717 * Since: 1.1.1
718 **/
719GPtrArray *
Richard Hughes12724852018-09-04 13:53:44 +0100720fu_plugin_get_hwids (FuPlugin *self)
Richard Hughes69a5f352018-08-08 11:58:15 +0100721{
Richard Hughes12724852018-09-04 13:53:44 +0100722 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes69a5f352018-08-08 11:58:15 +0100723 if (priv->hwids == NULL)
724 return NULL;
725 return fu_hwids_get_guids (priv->hwids);
726}
727
728/**
Richard Hughes19841802019-09-10 16:48:00 +0100729 * fu_plugin_has_custom_flag:
730 * @self: A #FuPlugin
731 * @flag: A custom text flag, specific to the plugin, e.g. `uefi-force-enable`
732 *
733 * Returns if a per-plugin HwId custom flag exists, typically added from a DMI quirk.
734 *
735 * Returns: %TRUE if the quirk entry exists
736 *
737 * Since: 1.3.1
738 **/
739gboolean
740fu_plugin_has_custom_flag (FuPlugin *self, const gchar *flag)
741{
742 FuPluginPrivate *priv = GET_PRIVATE (self);
743 GPtrArray *hwids = fu_plugin_get_hwids (self);
744
745 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
746 g_return_val_if_fail (flag != NULL, FALSE);
747
748 /* never set up, e.g. in tests */
749 if (hwids == NULL)
750 return FALSE;
751
752 /* search each hwid */
753 for (guint i = 0; i < hwids->len; i++) {
754 const gchar *hwid = g_ptr_array_index (hwids, i);
755 const gchar *value;
756 g_autofree gchar *key = g_strdup_printf ("HwId=%s", hwid);
757
758 /* does prefixed quirk exist */
759 value = fu_quirks_lookup_by_id (priv->quirks, key, FU_QUIRKS_FLAGS);
760 if (value != NULL) {
761 g_auto(GStrv) quirks = g_strsplit (value, ",", -1);
762 if (g_strv_contains ((const gchar * const *) quirks, flag))
763 return TRUE;
764 }
765 }
766 return FALSE;
767}
768
769/**
Richard Hughes1354ea92017-09-19 15:58:31 +0100770 * fu_plugin_check_supported:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100771 * @self: A #FuPlugin
Richard Hughes4eada342017-10-03 21:20:32 +0100772 * @guid: A Hardware ID GUID, e.g. `6de5d951-d755-576b-bd09-c5cf66b27234`
Richard Hughes1354ea92017-09-19 15:58:31 +0100773 *
774 * Checks to see if a specific device GUID is supported, i.e. available in the
775 * AppStream metadata.
776 *
Richard Hughes4eada342017-10-03 21:20:32 +0100777 * Returns: %TRUE if the device is supported.
778 *
Richard Hughes1354ea92017-09-19 15:58:31 +0100779 * Since: 1.0.0
780 **/
Richard Hughesd8a8d5e2019-10-08 13:05:02 +0100781static gboolean
Richard Hughes12724852018-09-04 13:53:44 +0100782fu_plugin_check_supported (FuPlugin *self, const gchar *guid)
Richard Hughes1354ea92017-09-19 15:58:31 +0100783{
Richard Hughesaabdc372018-11-14 10:11:08 +0000784 gboolean retval = FALSE;
785 g_signal_emit (self, signals[SIGNAL_CHECK_SUPPORTED], 0, guid, &retval);
786 return retval;
Richard Hughes1354ea92017-09-19 15:58:31 +0100787}
788
789/**
Richard Hughesd7704d42017-08-08 20:29:09 +0100790 * fu_plugin_get_dmi_value:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100791 * @self: A #FuPlugin
Richard Hughes4eada342017-10-03 21:20:32 +0100792 * @dmi_id: A DMI ID, e.g. `BiosVersion`
Richard Hughesd7704d42017-08-08 20:29:09 +0100793 *
794 * Gets a hardware DMI value.
795 *
Richard Hughes4eada342017-10-03 21:20:32 +0100796 * Returns: The string, or %NULL
797 *
Richard Hughesd7704d42017-08-08 20:29:09 +0100798 * Since: 0.9.7
799 **/
800const gchar *
Richard Hughes12724852018-09-04 13:53:44 +0100801fu_plugin_get_dmi_value (FuPlugin *self, const gchar *dmi_id)
Richard Hughesd7704d42017-08-08 20:29:09 +0100802{
Richard Hughes12724852018-09-04 13:53:44 +0100803 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesd7704d42017-08-08 20:29:09 +0100804 if (priv->hwids == NULL)
Richard Hughes7ef96b82017-08-23 18:28:24 +0100805 return NULL;
Richard Hughesd7704d42017-08-08 20:29:09 +0100806 return fu_hwids_get_value (priv->hwids, dmi_id);
Richard Hughesb8f8db22017-04-25 15:56:00 +0100807}
808
Richard Hughes49e5e052017-09-03 12:15:41 +0100809/**
810 * fu_plugin_get_smbios_string:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100811 * @self: A #FuPlugin
Richard Hughes49e5e052017-09-03 12:15:41 +0100812 * @structure_type: A SMBIOS structure type, e.g. %FU_SMBIOS_STRUCTURE_TYPE_BIOS
813 * @offset: A SMBIOS offset
814 *
815 * Gets a hardware SMBIOS string.
816 *
817 * The @type and @offset can be referenced from the DMTF SMBIOS specification:
818 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.1.1.pdf
819 *
Richard Hughes4eada342017-10-03 21:20:32 +0100820 * Returns: A string, or %NULL
821 *
Richard Hughes49e5e052017-09-03 12:15:41 +0100822 * Since: 0.9.8
823 **/
824const gchar *
Richard Hughes12724852018-09-04 13:53:44 +0100825fu_plugin_get_smbios_string (FuPlugin *self, guint8 structure_type, guint8 offset)
Richard Hughes49e5e052017-09-03 12:15:41 +0100826{
Richard Hughes12724852018-09-04 13:53:44 +0100827 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes49e5e052017-09-03 12:15:41 +0100828 if (priv->smbios == NULL)
829 return NULL;
830 return fu_smbios_get_string (priv->smbios, structure_type, offset, NULL);
831}
832
833/**
834 * fu_plugin_get_smbios_data:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100835 * @self: A #FuPlugin
Richard Hughes49e5e052017-09-03 12:15:41 +0100836 * @structure_type: A SMBIOS structure type, e.g. %FU_SMBIOS_STRUCTURE_TYPE_BIOS
837 *
838 * Gets a hardware SMBIOS data.
839 *
Richard Hughesdfaca2d2019-08-01 08:08:03 +0100840 * Returns: (transfer full): A #GBytes, or %NULL
Richard Hughes4eada342017-10-03 21:20:32 +0100841 *
Richard Hughes49e5e052017-09-03 12:15:41 +0100842 * Since: 0.9.8
843 **/
844GBytes *
Richard Hughes12724852018-09-04 13:53:44 +0100845fu_plugin_get_smbios_data (FuPlugin *self, guint8 structure_type)
Richard Hughes49e5e052017-09-03 12:15:41 +0100846{
Richard Hughes12724852018-09-04 13:53:44 +0100847 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes49e5e052017-09-03 12:15:41 +0100848 if (priv->smbios == NULL)
849 return NULL;
850 return fu_smbios_get_data (priv->smbios, structure_type, NULL);
851}
852
Mario Limonciello1a680f32019-11-25 19:44:53 -0600853/**
854 * fu_plugin_set_hwids:
855 * @self: A #FuPlugin
856 * @hwids: A #FuHwids
857 *
858 * Sets the hwids for a plugin
859 *
860 * Since: 0.9.7
861 **/
Richard Hughesb8f8db22017-04-25 15:56:00 +0100862void
Richard Hughes12724852018-09-04 13:53:44 +0100863fu_plugin_set_hwids (FuPlugin *self, FuHwids *hwids)
Richard Hughesb8f8db22017-04-25 15:56:00 +0100864{
Richard Hughes12724852018-09-04 13:53:44 +0100865 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesd7704d42017-08-08 20:29:09 +0100866 g_set_object (&priv->hwids, hwids);
Richard Hughesb8f8db22017-04-25 15:56:00 +0100867}
868
Mario Limonciello1a680f32019-11-25 19:44:53 -0600869/**
870 * fu_plugin_set_udev_subsystems:
871 * @self: A #FuPlugin
Richard Hughesa0d81c72019-11-27 11:41:54 +0000872 * @udev_subsystems: (element-type utf8): A #GPtrArray
Mario Limonciello1a680f32019-11-25 19:44:53 -0600873 *
874 * Sets the udev subsystems used by a plugin
875 *
876 * Since: 1.1.2
877 **/
Richard Hughes49e5e052017-09-03 12:15:41 +0100878void
Richard Hughes12724852018-09-04 13:53:44 +0100879fu_plugin_set_udev_subsystems (FuPlugin *self, GPtrArray *udev_subsystems)
Richard Hughes9d6e0e72018-08-24 20:20:17 +0100880{
Richard Hughes12724852018-09-04 13:53:44 +0100881 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes9d6e0e72018-08-24 20:20:17 +0100882 if (priv->udev_subsystems != NULL)
883 g_ptr_array_unref (priv->udev_subsystems);
884 priv->udev_subsystems = g_ptr_array_ref (udev_subsystems);
885}
886
Mario Limonciello1a680f32019-11-25 19:44:53 -0600887/**
888 * fu_plugin_set_quirks:
889 * @self: A #FuPlugin
890 * @quirks: A #FuQuirks
891 *
892 * Sets the quirks for a plugin
893 *
894 * Since: 1.0.1
895 **/
Richard Hughes9d6e0e72018-08-24 20:20:17 +0100896void
Richard Hughes12724852018-09-04 13:53:44 +0100897fu_plugin_set_quirks (FuPlugin *self, FuQuirks *quirks)
Richard Hughes9c028f02017-10-28 21:14:28 +0100898{
Richard Hughes12724852018-09-04 13:53:44 +0100899 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes9c028f02017-10-28 21:14:28 +0100900 g_set_object (&priv->quirks, quirks);
901}
902
903/**
904 * fu_plugin_get_quirks:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100905 * @self: A #FuPlugin
Richard Hughes9c028f02017-10-28 21:14:28 +0100906 *
907 * Returns the hardware database object. This can be used to discover device
908 * quirks or other device-specific settings.
909 *
910 * Returns: (transfer none): a #FuQuirks, or %NULL if not set
911 *
912 * Since: 1.0.1
913 **/
914FuQuirks *
Richard Hughes12724852018-09-04 13:53:44 +0100915fu_plugin_get_quirks (FuPlugin *self)
Richard Hughes9c028f02017-10-28 21:14:28 +0100916{
Richard Hughes12724852018-09-04 13:53:44 +0100917 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes9c028f02017-10-28 21:14:28 +0100918 return priv->quirks;
919}
920
Mario Limonciello1a680f32019-11-25 19:44:53 -0600921/**
922 * fu_plugin_set_runtime_versions:
923 * @self: A #FuPlugin
924 * @runtime_versions: A #GHashTables
925 *
926 * Sets the runtime versions for a plugin
927 *
928 * Since: 1.0.7
929 **/
Richard Hughes0eb123b2018-04-19 12:00:04 +0100930void
Richard Hughes12724852018-09-04 13:53:44 +0100931fu_plugin_set_runtime_versions (FuPlugin *self, GHashTable *runtime_versions)
Richard Hughes0eb123b2018-04-19 12:00:04 +0100932{
Richard Hughes12724852018-09-04 13:53:44 +0100933 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes0eb123b2018-04-19 12:00:04 +0100934 priv->runtime_versions = g_hash_table_ref (runtime_versions);
935}
936
937/**
938 * fu_plugin_add_runtime_version:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100939 * @self: A #FuPlugin
Richard Hughes0eb123b2018-04-19 12:00:04 +0100940 * @component_id: An AppStream component id, e.g. "org.gnome.Software"
941 * @version: A version string, e.g. "1.2.3"
942 *
Richard Hughesdce91202019-04-08 12:47:45 +0100943 * Sets a runtime version of a specific dependency.
Richard Hughes0eb123b2018-04-19 12:00:04 +0100944 *
945 * Since: 1.0.7
946 **/
947void
Richard Hughes12724852018-09-04 13:53:44 +0100948fu_plugin_add_runtime_version (FuPlugin *self,
Richard Hughes0eb123b2018-04-19 12:00:04 +0100949 const gchar *component_id,
950 const gchar *version)
951{
Richard Hughes12724852018-09-04 13:53:44 +0100952 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesb01b4862018-04-20 16:39:48 +0100953 if (priv->runtime_versions == NULL)
954 return;
Richard Hughes0eb123b2018-04-19 12:00:04 +0100955 g_hash_table_insert (priv->runtime_versions,
956 g_strdup (component_id),
957 g_strdup (version));
958}
959
Mario Limonciello1a680f32019-11-25 19:44:53 -0600960/**
961 * fu_plugin_set_compile_versions:
962 * @self: A #FuPlugin
963 * @compile_versions: A #GHashTables
964 *
965 * Sets the compile time versions for a plugin
966 *
967 * Since: 1.0.7
968 **/
Richard Hughes34e0dab2018-04-20 16:43:00 +0100969void
Richard Hughes12724852018-09-04 13:53:44 +0100970fu_plugin_set_compile_versions (FuPlugin *self, GHashTable *compile_versions)
Richard Hughes34e0dab2018-04-20 16:43:00 +0100971{
Richard Hughes12724852018-09-04 13:53:44 +0100972 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes34e0dab2018-04-20 16:43:00 +0100973 priv->compile_versions = g_hash_table_ref (compile_versions);
974}
975
976/**
977 * fu_plugin_add_compile_version:
Richard Hughes2c0635a2018-09-04 14:52:46 +0100978 * @self: A #FuPlugin
Richard Hughes34e0dab2018-04-20 16:43:00 +0100979 * @component_id: An AppStream component id, e.g. "org.gnome.Software"
980 * @version: A version string, e.g. "1.2.3"
981 *
Richard Hughesdce91202019-04-08 12:47:45 +0100982 * Sets a compile-time version of a specific dependency.
Richard Hughes34e0dab2018-04-20 16:43:00 +0100983 *
984 * Since: 1.0.7
985 **/
986void
Richard Hughes12724852018-09-04 13:53:44 +0100987fu_plugin_add_compile_version (FuPlugin *self,
Richard Hughes34e0dab2018-04-20 16:43:00 +0100988 const gchar *component_id,
989 const gchar *version)
990{
Richard Hughes12724852018-09-04 13:53:44 +0100991 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes34e0dab2018-04-20 16:43:00 +0100992 if (priv->compile_versions == NULL)
993 return;
994 g_hash_table_insert (priv->compile_versions,
995 g_strdup (component_id),
996 g_strdup (version));
997}
998
Richard Hughes9c028f02017-10-28 21:14:28 +0100999/**
1000 * fu_plugin_lookup_quirk_by_id:
Richard Hughes2c0635a2018-09-04 14:52:46 +01001001 * @self: A #FuPlugin
Richard Hughes87fb9ff2018-06-28 12:55:59 +01001002 * @group: A string, e.g. "DfuFlags"
1003 * @key: An ID to match the entry, e.g. "Summary"
Richard Hughes9c028f02017-10-28 21:14:28 +01001004 *
1005 * Looks up an entry in the hardware database using a string value.
1006 *
1007 * Returns: (transfer none): values from the database, or %NULL if not found
1008 *
1009 * Since: 1.0.1
1010 **/
1011const gchar *
Richard Hughes12724852018-09-04 13:53:44 +01001012fu_plugin_lookup_quirk_by_id (FuPlugin *self, const gchar *group, const gchar *key)
Richard Hughes9c028f02017-10-28 21:14:28 +01001013{
Richard Hughes12724852018-09-04 13:53:44 +01001014 FuPluginPrivate *priv = GET_PRIVATE (self);
1015 g_return_val_if_fail (FU_IS_PLUGIN (self), NULL);
Richard Hughes9c028f02017-10-28 21:14:28 +01001016
Richard Hughes9c028f02017-10-28 21:14:28 +01001017 /* exact ID */
Richard Hughes87fb9ff2018-06-28 12:55:59 +01001018 return fu_quirks_lookup_by_id (priv->quirks, group, key);
Richard Hughes9c028f02017-10-28 21:14:28 +01001019}
1020
1021/**
Richard Hughes8fe7cdd2018-08-23 10:02:44 +01001022 * fu_plugin_lookup_quirk_by_id_as_uint64:
Richard Hughes2c0635a2018-09-04 14:52:46 +01001023 * @self: A #FuPlugin
Richard Hughes8fe7cdd2018-08-23 10:02:44 +01001024 * @group: A string, e.g. "DfuFlags"
1025 * @key: An ID to match the entry, e.g. "Size"
1026 *
1027 * Looks up an entry in the hardware database using a string key, returning
1028 * an integer value. Values are assumed base 10, unless prefixed with "0x"
1029 * where they are parsed as base 16.
1030 *
Mario Limonciello1a680f32019-11-25 19:44:53 -06001031 * Returns: guint64 id or 0 if not found
Richard Hughes8fe7cdd2018-08-23 10:02:44 +01001032 *
1033 * Since: 1.1.2
1034 **/
1035guint64
Richard Hughes12724852018-09-04 13:53:44 +01001036fu_plugin_lookup_quirk_by_id_as_uint64 (FuPlugin *self, const gchar *group, const gchar *key)
Richard Hughes8fe7cdd2018-08-23 10:02:44 +01001037{
Richard Hughes12724852018-09-04 13:53:44 +01001038 return fu_common_strtoull (fu_plugin_lookup_quirk_by_id (self, group, key));
Richard Hughes8fe7cdd2018-08-23 10:02:44 +01001039}
1040
Mario Limonciello1a680f32019-11-25 19:44:53 -06001041/**
1042 * fu_plugin_set_smbios:
1043 * @self: A #FuPlugin
1044 * @smbios: A #FuSmbios
1045 *
1046 * Sets the smbios for a plugin
1047 *
1048 * Since: 1.0.0
1049 **/
Richard Hughes1354ea92017-09-19 15:58:31 +01001050void
Richard Hughes12724852018-09-04 13:53:44 +01001051fu_plugin_set_smbios (FuPlugin *self, FuSmbios *smbios)
Richard Hughes49e5e052017-09-03 12:15:41 +01001052{
Richard Hughes12724852018-09-04 13:53:44 +01001053 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes49e5e052017-09-03 12:15:41 +01001054 g_set_object (&priv->smbios, smbios);
1055}
1056
Richard Hughesb8f8db22017-04-25 15:56:00 +01001057/**
Richard Hughesb0829032017-01-10 09:27:08 +00001058 * fu_plugin_set_coldplug_delay:
Richard Hughes2c0635a2018-09-04 14:52:46 +01001059 * @self: A #FuPlugin
Richard Hughesb0829032017-01-10 09:27:08 +00001060 * @duration: A delay in milliseconds
1061 *
Richard Hughes21eaeef2020-01-14 12:10:01 +00001062 * Set the minimum time that should be waited in-between the call to
Richard Hughesb0829032017-01-10 09:27:08 +00001063 * fu_plugin_coldplug_prepare() and fu_plugin_coldplug(). This is usually going
Richard Hughes203ed842020-11-02 14:25:13 +00001064 * to be the minimum hardware initialization time from a datasheet.
Richard Hughesb0829032017-01-10 09:27:08 +00001065 *
1066 * It is better to use this function rather than using a sleep() in the plugin
1067 * itself as then only one delay is done in the daemon rather than waiting for
1068 * each coldplug prepare in a serial way.
1069 *
1070 * Additionally, very long delays should be avoided as the daemon will be
1071 * blocked from processing requests whilst the coldplug delay is being
1072 * performed.
1073 *
1074 * Since: 0.8.0
1075 **/
1076void
Richard Hughes12724852018-09-04 13:53:44 +01001077fu_plugin_set_coldplug_delay (FuPlugin *self, guint duration)
Richard Hughesb0829032017-01-10 09:27:08 +00001078{
Richard Hughes12724852018-09-04 13:53:44 +01001079 g_return_if_fail (FU_IS_PLUGIN (self));
Richard Hughesb0829032017-01-10 09:27:08 +00001080 g_return_if_fail (duration > 0);
1081
1082 /* check sanity */
1083 if (duration > FU_PLUGIN_COLDPLUG_DELAY_MAXIMUM) {
1084 g_warning ("duration of %ums is crazy, truncating to %ums",
1085 duration,
1086 FU_PLUGIN_COLDPLUG_DELAY_MAXIMUM);
1087 duration = FU_PLUGIN_COLDPLUG_DELAY_MAXIMUM;
1088 }
1089
1090 /* emit */
Richard Hughes12724852018-09-04 13:53:44 +01001091 g_signal_emit (self, signals[SIGNAL_SET_COLDPLUG_DELAY], 0, duration);
Richard Hughesb0829032017-01-10 09:27:08 +00001092}
1093
Richard Hughes4b303802019-10-04 13:22:51 +01001094static gboolean
1095fu_plugin_device_attach (FuPlugin *self, FuDevice *device, GError **error)
1096{
1097 g_autoptr(FuDeviceLocker) locker = NULL;
Richard Hughes4b303802019-10-04 13:22:51 +01001098 locker = fu_device_locker_new (device, error);
1099 if (locker == NULL)
1100 return FALSE;
1101 return fu_device_attach (device, error);
1102}
1103
1104static gboolean
1105fu_plugin_device_detach (FuPlugin *self, FuDevice *device, GError **error)
1106{
1107 g_autoptr(FuDeviceLocker) locker = NULL;
Richard Hughes4b303802019-10-04 13:22:51 +01001108 locker = fu_device_locker_new (device, error);
1109 if (locker == NULL)
1110 return FALSE;
1111 return fu_device_detach (device, error);
1112}
1113
1114static gboolean
Richard Hughes4b303802019-10-04 13:22:51 +01001115fu_plugin_device_activate (FuPlugin *self, FuDevice *device, GError **error)
1116{
1117 g_autoptr(FuDeviceLocker) locker = NULL;
1118 locker = fu_device_locker_new (device, error);
1119 if (locker == NULL)
1120 return FALSE;
1121 return fu_device_activate (device, error);
1122}
1123
1124static gboolean
1125fu_plugin_device_write_firmware (FuPlugin *self, FuDevice *device,
1126 GBytes *fw, FwupdInstallFlags flags,
1127 GError **error)
1128{
1129 g_autoptr(FuDeviceLocker) locker = NULL;
1130 locker = fu_device_locker_new (device, error);
1131 if (locker == NULL)
1132 return FALSE;
Richard Hughes1a612582020-09-29 19:39:38 +01001133
1134 /* back the old firmware up to /var/lib/fwupd */
1135 if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_BACKUP_BEFORE_INSTALL)) {
1136 g_autoptr(GBytes) fw_old = NULL;
1137 g_autofree gchar *path = NULL;
1138 g_autofree gchar *fn = NULL;
1139 g_autofree gchar *localstatedir = NULL;
1140
1141 fw_old = fu_device_dump_firmware (device, error);
1142 if (fw_old == NULL) {
1143 g_prefix_error (error, "failed to backup old firmware: ");
1144 return FALSE;
1145 }
1146 localstatedir = fu_common_get_path (FU_PATH_KIND_LOCALSTATEDIR_PKG);
1147 fn = g_strdup_printf ("%s.bin", fu_device_get_version (device));
1148 path = g_build_filename (localstatedir,
1149 "backup",
1150 fu_device_get_id (device),
1151 fu_device_get_serial (device) != NULL ?
1152 fu_device_get_serial (device) :
1153 "default",
1154 fn, NULL);
1155 if (!fu_common_set_contents_bytes (path, fw_old, error))
1156 return FALSE;
1157 }
1158
Richard Hughes4b303802019-10-04 13:22:51 +01001159 return fu_device_write_firmware (device, fw, flags, error);
1160}
1161
Richard Hughes7f677212019-10-05 16:19:40 +01001162static gboolean
1163fu_plugin_device_read_firmware (FuPlugin *self, FuDevice *device, GError **error)
1164{
1165 g_autoptr(FuDeviceLocker) locker = NULL;
Richard Hughesf0eb0912019-10-10 11:37:22 +01001166 g_autoptr(FuFirmware) firmware = NULL;
Richard Hughes7f677212019-10-05 16:19:40 +01001167 g_autoptr(GBytes) fw = NULL;
1168 GChecksumType checksum_types[] = {
1169 G_CHECKSUM_SHA1,
1170 G_CHECKSUM_SHA256,
1171 0 };
1172 locker = fu_device_locker_new (device, error);
1173 if (locker == NULL)
1174 return FALSE;
1175 if (!fu_device_detach (device, error))
1176 return FALSE;
Richard Hughesf0eb0912019-10-10 11:37:22 +01001177 firmware = fu_device_read_firmware (device, error);
1178 if (firmware == NULL) {
1179 g_autoptr(GError) error_local = NULL;
1180 if (!fu_device_attach (device, &error_local))
1181 g_debug ("ignoring attach failure: %s", error_local->message);
1182 g_prefix_error (error, "failed to read firmware: ");
1183 return FALSE;
1184 }
1185 fw = fu_firmware_write (firmware, error);
Richard Hughes7f677212019-10-05 16:19:40 +01001186 if (fw == NULL) {
1187 g_autoptr(GError) error_local = NULL;
1188 if (!fu_device_attach (device, &error_local))
Richard Hughesf0eb0912019-10-10 11:37:22 +01001189 g_debug ("ignoring attach failure: %s", error_local->message);
1190 g_prefix_error (error, "failed to write firmware: ");
Richard Hughes7f677212019-10-05 16:19:40 +01001191 return FALSE;
1192 }
1193 for (guint i = 0; checksum_types[i] != 0; i++) {
1194 g_autofree gchar *hash = NULL;
1195 hash = g_compute_checksum_for_bytes (checksum_types[i], fw);
1196 fu_device_add_checksum (device, hash);
1197 }
1198 return fu_device_attach (device, error);
1199}
1200
Mario Limonciello1a680f32019-11-25 19:44:53 -06001201/**
1202 * fu_plugin_runner_startup:
1203 * @self: a #FuPlugin
1204 * @error: a #GError or NULL
1205 *
1206 * Runs the startup routine for the plugin
1207 *
1208 * Returns: #TRUE for success, #FALSE for failure
1209 *
1210 * Since: 0.8.0
1211 **/
Richard Hughesd0905142016-03-13 09:46:49 +00001212gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001213fu_plugin_runner_startup (FuPlugin *self, GError **error)
Richard Hughesd0905142016-03-13 09:46:49 +00001214{
Richard Hughes12724852018-09-04 13:53:44 +01001215 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes7b8b2022016-12-12 16:15:03 +00001216 FuPluginStartupFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001217 g_autoptr(GError) error_local = NULL;
Richard Hughesd0905142016-03-13 09:46:49 +00001218
1219 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001220 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughesd0905142016-03-13 09:46:49 +00001221 return TRUE;
1222
Richard Hughes639da472018-01-06 22:35:04 +00001223 /* no object loaded */
1224 if (priv->module == NULL)
1225 return TRUE;
1226
Richard Hughesd0905142016-03-13 09:46:49 +00001227 /* optional */
Richard Hughescff38bc2016-12-12 12:03:37 +00001228 g_module_symbol (priv->module, "fu_plugin_startup", (gpointer *) &func);
1229 if (func == NULL)
Richard Hughesd0905142016-03-13 09:46:49 +00001230 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001231 g_debug ("startup(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001232 if (!func (self, &error_local)) {
1233 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001234 g_critical ("unset plugin error in startup(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001235 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001236 g_set_error_literal (&error_local,
1237 FWUPD_ERROR,
1238 FWUPD_ERROR_INTERNAL,
1239 "unspecified error");
1240 }
1241 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1242 "failed to startup using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001243 fu_plugin_get_name (self));
Richard Hughescff38bc2016-12-12 12:03:37 +00001244 return FALSE;
1245 }
1246 return TRUE;
1247}
1248
1249static gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001250fu_plugin_runner_device_generic (FuPlugin *self, FuDevice *device,
Richard Hughes4b303802019-10-04 13:22:51 +01001251 const gchar *symbol_name,
1252 FuPluginDeviceFunc device_func,
1253 GError **error)
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001254{
Richard Hughes12724852018-09-04 13:53:44 +01001255 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001256 FuPluginDeviceFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001257 g_autoptr(GError) error_local = NULL;
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001258
1259 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001260 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001261 return TRUE;
1262
Richard Hughesd3d96cc2017-11-14 11:34:33 +00001263 /* no object loaded */
1264 if (priv->module == NULL)
1265 return TRUE;
1266
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001267 /* optional */
1268 g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
Richard Hughes4b303802019-10-04 13:22:51 +01001269 if (func == NULL) {
1270 if (device_func != NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001271 g_debug ("running superclassed %s(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001272 symbol_name + 10, fu_plugin_get_name (self));
Richard Hughes4b303802019-10-04 13:22:51 +01001273 return device_func (self, device, error);
1274 }
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001275 return TRUE;
Richard Hughes4b303802019-10-04 13:22:51 +01001276 }
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001277 g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001278 if (!func (self, device, &error_local)) {
1279 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001280 g_critical ("unset plugin error in %s(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001281 fu_plugin_get_name (self), symbol_name + 10);
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001282 g_set_error_literal (&error_local,
1283 FWUPD_ERROR,
1284 FWUPD_ERROR_INTERNAL,
1285 "unspecified error");
1286 }
1287 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1288 "failed to %s using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001289 symbol_name + 10, fu_plugin_get_name (self));
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001290 return FALSE;
1291 }
1292 return TRUE;
1293}
1294
Richard Hughesdbd8c762018-06-15 20:31:40 +01001295static gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001296fu_plugin_runner_flagged_device_generic (FuPlugin *self, FwupdInstallFlags flags,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001297 FuDevice *device,
1298 const gchar *symbol_name, GError **error)
1299{
Richard Hughes12724852018-09-04 13:53:44 +01001300 FuPluginPrivate *priv = GET_PRIVATE (self);
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001301 FuPluginFlaggedDeviceFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001302 g_autoptr(GError) error_local = NULL;
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001303
1304 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001305 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001306 return TRUE;
1307
1308 /* no object loaded */
1309 if (priv->module == NULL)
1310 return TRUE;
1311
1312 /* optional */
1313 g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
1314 if (func == NULL)
1315 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001316 g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001317 if (!func (self, flags, device, &error_local)) {
1318 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001319 g_critical ("unset plugin error in %s(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001320 fu_plugin_get_name (self), symbol_name + 10);
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001321 g_set_error_literal (&error_local,
1322 FWUPD_ERROR,
1323 FWUPD_ERROR_INTERNAL,
1324 "unspecified error");
1325 }
1326 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1327 "failed to %s using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001328 symbol_name + 10, fu_plugin_get_name (self));
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001329 return FALSE;
1330 }
1331 return TRUE;
1332
1333}
1334
1335static gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001336fu_plugin_runner_device_array_generic (FuPlugin *self, GPtrArray *devices,
Richard Hughesdbd8c762018-06-15 20:31:40 +01001337 const gchar *symbol_name, GError **error)
1338{
Richard Hughes12724852018-09-04 13:53:44 +01001339 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesdbd8c762018-06-15 20:31:40 +01001340 FuPluginDeviceArrayFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001341 g_autoptr(GError) error_local = NULL;
Richard Hughesdbd8c762018-06-15 20:31:40 +01001342
1343 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001344 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughesdbd8c762018-06-15 20:31:40 +01001345 return TRUE;
1346
1347 /* no object loaded */
1348 if (priv->module == NULL)
1349 return TRUE;
1350
1351 /* optional */
1352 g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
1353 if (func == NULL)
1354 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001355 g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001356 if (!func (self, devices, &error_local)) {
1357 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001358 g_critical ("unset plugin error in for %s(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001359 fu_plugin_get_name (self), symbol_name + 10);
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001360 g_set_error_literal (&error_local,
1361 FWUPD_ERROR,
1362 FWUPD_ERROR_INTERNAL,
1363 "unspecified error");
1364 }
1365 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1366 "failed to %s using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001367 symbol_name + 10, fu_plugin_get_name (self));
Richard Hughesdbd8c762018-06-15 20:31:40 +01001368 return FALSE;
1369 }
1370 return TRUE;
1371}
1372
Mario Limonciello1a680f32019-11-25 19:44:53 -06001373/**
1374 * fu_plugin_runner_coldplug:
1375 * @self: a #FuPlugin
1376 * @error: a #GError or NULL
1377 *
1378 * Runs the coldplug routine for the plugin
1379 *
1380 * Returns: #TRUE for success, #FALSE for failure
1381 *
1382 * Since: 0.8.0
1383 **/
Richard Hughesd0905142016-03-13 09:46:49 +00001384gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001385fu_plugin_runner_coldplug (FuPlugin *self, GError **error)
Richard Hughesd0905142016-03-13 09:46:49 +00001386{
Richard Hughes12724852018-09-04 13:53:44 +01001387 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes7b8b2022016-12-12 16:15:03 +00001388 FuPluginStartupFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001389 g_autoptr(GError) error_local = NULL;
Richard Hughesd0905142016-03-13 09:46:49 +00001390
1391 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001392 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughesd0905142016-03-13 09:46:49 +00001393 return TRUE;
1394
Richard Hughes639da472018-01-06 22:35:04 +00001395 /* no object loaded */
1396 if (priv->module == NULL)
1397 return TRUE;
1398
Richard Hughesd0905142016-03-13 09:46:49 +00001399 /* optional */
Richard Hughescff38bc2016-12-12 12:03:37 +00001400 g_module_symbol (priv->module, "fu_plugin_coldplug", (gpointer *) &func);
1401 if (func == NULL)
Richard Hughesd0905142016-03-13 09:46:49 +00001402 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001403 g_debug ("coldplug(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001404 if (!func (self, &error_local)) {
1405 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001406 g_critical ("unset plugin error in coldplug(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001407 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001408 g_set_error_literal (&error_local,
1409 FWUPD_ERROR,
1410 FWUPD_ERROR_INTERNAL,
1411 "unspecified error");
1412 }
1413 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001414 "failed to coldplug using %s: ", fu_plugin_get_name (self));
Richard Hughescff38bc2016-12-12 12:03:37 +00001415 return FALSE;
1416 }
1417 return TRUE;
1418}
1419
Mario Limonciello1a680f32019-11-25 19:44:53 -06001420/**
1421 * fu_plugin_runner_recoldplug:
1422 * @self: a #FuPlugin
1423 * @error: a #GError or NULL
1424 *
1425 * Runs the recoldplug routine for the plugin
1426 *
1427 * Returns: #TRUE for success, #FALSE for failure
1428 *
1429 * Since: 1.0.4
1430 **/
Richard Hughes7b8b2022016-12-12 16:15:03 +00001431gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001432fu_plugin_runner_recoldplug (FuPlugin *self, GError **error)
Richard Hughes2de8f132018-01-17 09:12:02 +00001433{
Richard Hughes12724852018-09-04 13:53:44 +01001434 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes2de8f132018-01-17 09:12:02 +00001435 FuPluginStartupFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001436 g_autoptr(GError) error_local = NULL;
Richard Hughes2de8f132018-01-17 09:12:02 +00001437
1438 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001439 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes2de8f132018-01-17 09:12:02 +00001440 return TRUE;
1441
1442 /* no object loaded */
1443 if (priv->module == NULL)
1444 return TRUE;
1445
1446 /* optional */
1447 g_module_symbol (priv->module, "fu_plugin_recoldplug", (gpointer *) &func);
1448 if (func == NULL)
1449 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001450 g_debug ("recoldplug(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001451 if (!func (self, &error_local)) {
1452 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001453 g_critical ("unset plugin error in recoldplug(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001454 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001455 g_set_error_literal (&error_local,
1456 FWUPD_ERROR,
1457 FWUPD_ERROR_INTERNAL,
1458 "unspecified error");
1459 }
1460 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1461 "failed to recoldplug using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001462 fu_plugin_get_name (self));
Richard Hughes2de8f132018-01-17 09:12:02 +00001463 return FALSE;
1464 }
1465 return TRUE;
1466}
1467
Mario Limonciello1a680f32019-11-25 19:44:53 -06001468/**
1469 * fu_plugin_runner_coldplug_prepare:
1470 * @self: a #FuPlugin
1471 * @error: a #GError or NULL
1472 *
1473 * Runs the coldplug_prepare routine for the plugin
1474 *
1475 * Returns: #TRUE for success, #FALSE for failure
1476 *
1477 * Since: 0.8.0
1478 **/
Richard Hughes2de8f132018-01-17 09:12:02 +00001479gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001480fu_plugin_runner_coldplug_prepare (FuPlugin *self, GError **error)
Richard Hughes46487c92017-01-07 21:26:34 +00001481{
Richard Hughes12724852018-09-04 13:53:44 +01001482 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes46487c92017-01-07 21:26:34 +00001483 FuPluginStartupFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001484 g_autoptr(GError) error_local = NULL;
Richard Hughes46487c92017-01-07 21:26:34 +00001485
1486 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001487 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes46487c92017-01-07 21:26:34 +00001488 return TRUE;
1489
Richard Hughes639da472018-01-06 22:35:04 +00001490 /* no object loaded */
1491 if (priv->module == NULL)
1492 return TRUE;
1493
Richard Hughes46487c92017-01-07 21:26:34 +00001494 /* optional */
1495 g_module_symbol (priv->module, "fu_plugin_coldplug_prepare", (gpointer *) &func);
1496 if (func == NULL)
1497 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001498 g_debug ("coldplug_prepare(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001499 if (!func (self, &error_local)) {
1500 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001501 g_critical ("unset plugin error in coldplug_prepare(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001502 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001503 g_set_error_literal (&error_local,
1504 FWUPD_ERROR,
1505 FWUPD_ERROR_INTERNAL,
1506 "unspecified error");
1507 }
1508 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1509 "failed to coldplug_prepare using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001510 fu_plugin_get_name (self));
Richard Hughes46487c92017-01-07 21:26:34 +00001511 return FALSE;
1512 }
1513 return TRUE;
1514}
1515
Mario Limonciello1a680f32019-11-25 19:44:53 -06001516/**
1517 * fu_plugin_runner_coldplug_cleanup:
1518 * @self: a #FuPlugin
1519 * @error: a #GError or NULL
1520 *
1521 * Runs the coldplug_cleanup routine for the plugin
1522 *
1523 * Returns: #TRUE for success, #FALSE for failure
1524 *
1525 * Since: 0.8.0
1526 **/
Richard Hughes46487c92017-01-07 21:26:34 +00001527gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001528fu_plugin_runner_coldplug_cleanup (FuPlugin *self, GError **error)
Richard Hughes46487c92017-01-07 21:26:34 +00001529{
Richard Hughes12724852018-09-04 13:53:44 +01001530 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes46487c92017-01-07 21:26:34 +00001531 FuPluginStartupFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001532 g_autoptr(GError) error_local = NULL;
Richard Hughes46487c92017-01-07 21:26:34 +00001533
1534 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001535 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes46487c92017-01-07 21:26:34 +00001536 return TRUE;
1537
Richard Hughes639da472018-01-06 22:35:04 +00001538 /* no object loaded */
1539 if (priv->module == NULL)
1540 return TRUE;
1541
Richard Hughes46487c92017-01-07 21:26:34 +00001542 /* optional */
1543 g_module_symbol (priv->module, "fu_plugin_coldplug_cleanup", (gpointer *) &func);
1544 if (func == NULL)
1545 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001546 g_debug ("coldplug_cleanup(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001547 if (!func (self, &error_local)) {
1548 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05001549 g_critical ("unset plugin error in coldplug_cleanup(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001550 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001551 g_set_error_literal (&error_local,
1552 FWUPD_ERROR,
1553 FWUPD_ERROR_INTERNAL,
1554 "unspecified error");
1555 }
1556 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1557 "failed to coldplug_cleanup using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001558 fu_plugin_get_name (self));
Richard Hughes46487c92017-01-07 21:26:34 +00001559 return FALSE;
1560 }
1561 return TRUE;
1562}
1563
Mario Limonciello1a680f32019-11-25 19:44:53 -06001564/**
1565 * fu_plugin_runner_composite_prepare:
1566 * @self: a #FuPlugin
Richard Hughesa0d81c72019-11-27 11:41:54 +00001567 * @devices: (element-type FuDevice): a #GPtrArray of devices
Mario Limonciello1a680f32019-11-25 19:44:53 -06001568 * @error: a #GError or NULL
1569 *
1570 * Runs the composite_prepare routine for the plugin
1571 *
1572 * Returns: #TRUE for success, #FALSE for failure
1573 *
1574 * Since: 1.0.9
1575 **/
Richard Hughes46487c92017-01-07 21:26:34 +00001576gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001577fu_plugin_runner_composite_prepare (FuPlugin *self, GPtrArray *devices, GError **error)
Richard Hughesdbd8c762018-06-15 20:31:40 +01001578{
Richard Hughes12724852018-09-04 13:53:44 +01001579 return fu_plugin_runner_device_array_generic (self, devices,
Richard Hughesdbd8c762018-06-15 20:31:40 +01001580 "fu_plugin_composite_prepare",
1581 error);
1582}
1583
Mario Limonciello1a680f32019-11-25 19:44:53 -06001584/**
1585 * fu_plugin_runner_composite_cleanup:
1586 * @self: a #FuPlugin
Richard Hughesa0d81c72019-11-27 11:41:54 +00001587 * @devices: (element-type FuDevice): a #GPtrArray of devices
Mario Limonciello1a680f32019-11-25 19:44:53 -06001588 * @error: a #GError or NULL
1589 *
1590 * Runs the composite_cleanup routine for the plugin
1591 *
1592 * Returns: #TRUE for success, #FALSE for failure
1593 *
1594 * Since: 1.0.9
1595 **/
Richard Hughesdbd8c762018-06-15 20:31:40 +01001596gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001597fu_plugin_runner_composite_cleanup (FuPlugin *self, GPtrArray *devices, GError **error)
Richard Hughesdbd8c762018-06-15 20:31:40 +01001598{
Richard Hughes12724852018-09-04 13:53:44 +01001599 return fu_plugin_runner_device_array_generic (self, devices,
Richard Hughesdbd8c762018-06-15 20:31:40 +01001600 "fu_plugin_composite_cleanup",
1601 error);
1602}
1603
Mario Limonciello1a680f32019-11-25 19:44:53 -06001604/**
1605 * fu_plugin_runner_update_prepare:
1606 * @self: a #FuPlugin
Richard Hughes2bbb7d22020-11-30 09:18:45 +00001607 * @flags: #FwupdInstallFlags
1608 * @device: a #FuDevice
Mario Limonciello1a680f32019-11-25 19:44:53 -06001609 * @error: a #GError or NULL
1610 *
1611 * Runs the update_prepare routine for the plugin
1612 *
1613 * Returns: #TRUE for success, #FALSE for failure
1614 *
1615 * Since: 1.1.2
1616 **/
Richard Hughesdbd8c762018-06-15 20:31:40 +01001617gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001618fu_plugin_runner_update_prepare (FuPlugin *self, FwupdInstallFlags flags, FuDevice *device,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001619 GError **error)
Richard Hughes7b8b2022016-12-12 16:15:03 +00001620{
Richard Hughes12724852018-09-04 13:53:44 +01001621 return fu_plugin_runner_flagged_device_generic (self, flags, device,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001622 "fu_plugin_update_prepare",
1623 error);
Richard Hughes7b8b2022016-12-12 16:15:03 +00001624}
1625
Mario Limonciello1a680f32019-11-25 19:44:53 -06001626/**
1627 * fu_plugin_runner_update_cleanup:
1628 * @self: a #FuPlugin
Richard Hughes2bbb7d22020-11-30 09:18:45 +00001629 * @flags: #FwupdInstallFlags
1630 * @device: a #FuDevice
Mario Limonciello1a680f32019-11-25 19:44:53 -06001631 * @error: a #GError or NULL
1632 *
1633 * Runs the update_cleanup routine for the plugin
1634 *
1635 * Returns: #TRUE for success, #FALSE for failure
1636 *
1637 * Since: 1.1.2
1638 **/
Richard Hughes7b8b2022016-12-12 16:15:03 +00001639gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001640fu_plugin_runner_update_cleanup (FuPlugin *self, FwupdInstallFlags flags, FuDevice *device,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001641 GError **error)
Richard Hughes7b8b2022016-12-12 16:15:03 +00001642{
Richard Hughes12724852018-09-04 13:53:44 +01001643 return fu_plugin_runner_flagged_device_generic (self, flags, device,
Mario Limoncielloe3b1a3f2018-08-21 13:01:45 -05001644 "fu_plugin_update_cleanup",
1645 error);
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001646}
Richard Hughes7b8b2022016-12-12 16:15:03 +00001647
Mario Limonciello1a680f32019-11-25 19:44:53 -06001648/**
1649 * fu_plugin_runner_update_attach:
1650 * @self: a #FuPlugin
1651 * @device: a #FuDevice
1652 * @error: a #GError or NULL
1653 *
1654 * Runs the update_attach routine for the plugin
1655 *
1656 * Returns: #TRUE for success, #FALSE for failure
1657 *
1658 * Since: 1.1.2
1659 **/
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001660gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001661fu_plugin_runner_update_attach (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001662{
Richard Hughes12724852018-09-04 13:53:44 +01001663 return fu_plugin_runner_device_generic (self, device,
Richard Hughes4b303802019-10-04 13:22:51 +01001664 "fu_plugin_update_attach",
1665 fu_plugin_device_attach,
1666 error);
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001667}
Richard Hughes7b8b2022016-12-12 16:15:03 +00001668
Mario Limonciello1a680f32019-11-25 19:44:53 -06001669/**
1670 * fu_plugin_runner_update_detach:
1671 * @self: a #FuPlugin
1672 * @device: A #FuDevice
1673 * @error: a #GError or NULL
1674 *
1675 * Runs the update_detach routine for the plugin
1676 *
1677 * Returns: #TRUE for success, #FALSE for failure
1678 *
1679 * Since: 1.1.2
1680 **/
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001681gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001682fu_plugin_runner_update_detach (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001683{
Richard Hughes12724852018-09-04 13:53:44 +01001684 return fu_plugin_runner_device_generic (self, device,
Richard Hughes4b303802019-10-04 13:22:51 +01001685 "fu_plugin_update_detach",
1686 fu_plugin_device_detach,
1687 error);
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001688}
1689
Mario Limonciello1a680f32019-11-25 19:44:53 -06001690/**
1691 * fu_plugin_runner_update_reload:
1692 * @self: a #FuPlugin
Richard Hughes2bbb7d22020-11-30 09:18:45 +00001693 * @device: A #FuDevice
Mario Limonciello1a680f32019-11-25 19:44:53 -06001694 * @error: a #GError or NULL
1695 *
1696 * Runs reload routine for a device
1697 *
1698 * Returns: #TRUE for success, #FALSE for failure
1699 *
1700 * Since: 1.1.2
1701 **/
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001702gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001703fu_plugin_runner_update_reload (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughes0d7fdb32017-11-11 20:23:14 +00001704{
Richard Hughes42f33df2019-10-05 20:52:33 +01001705 g_autoptr(FuDeviceLocker) locker = NULL;
1706
1707 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001708 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes42f33df2019-10-05 20:52:33 +01001709 return TRUE;
1710
1711 /* no object loaded */
1712 locker = fu_device_locker_new (device, error);
1713 if (locker == NULL)
1714 return FALSE;
1715 return fu_device_reload (device, error);
Richard Hughes7b8b2022016-12-12 16:15:03 +00001716}
1717
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001718/**
Richard Hughes196c6c62020-05-11 19:42:47 +01001719 * fu_plugin_runner_add_security_attrs:
1720 * @self: a #FuPlugin
Richard Hughes3ecd22c2020-05-19 20:13:47 +01001721 * @attrs: a #FuSecurityAttrs
Richard Hughes196c6c62020-05-11 19:42:47 +01001722 *
Richard Hughes3ecd22c2020-05-19 20:13:47 +01001723 * Runs the `add_security_attrs()` routine for the plugin
Richard Hughes196c6c62020-05-11 19:42:47 +01001724 *
1725 * Since: 1.5.0
1726 **/
Richard Hughesf58ac732020-05-12 15:23:44 +01001727void
1728fu_plugin_runner_add_security_attrs (FuPlugin *self, FuSecurityAttrs *attrs)
Richard Hughes196c6c62020-05-11 19:42:47 +01001729{
Richard Hughesf58ac732020-05-12 15:23:44 +01001730 FuPluginPrivate *priv = GET_PRIVATE (self);
1731 FuPluginSecurityAttrsFunc func = NULL;
1732 const gchar *symbol_name = "fu_plugin_add_security_attrs";
1733
1734 /* no object loaded */
1735 if (priv->module == NULL)
1736 return;
1737
1738 /* optional, but gets called even for disabled plugins */
1739 g_module_symbol (priv->module, symbol_name, (gpointer *) &func);
1740 if (func == NULL)
1741 return;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001742 g_debug ("%s(%s)", symbol_name + 10, fu_plugin_get_name (self));
Richard Hughesf58ac732020-05-12 15:23:44 +01001743 func (self, attrs);
Richard Hughes196c6c62020-05-11 19:42:47 +01001744}
1745
1746/**
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001747 * fu_plugin_add_udev_subsystem:
Richard Hughes2c0635a2018-09-04 14:52:46 +01001748 * @self: a #FuPlugin
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001749 * @subsystem: a subsystem name, e.g. `pciport`
1750 *
1751 * Registers the udev subsystem to be watched by the daemon.
1752 *
1753 * Plugins can use this method only in fu_plugin_init()
Mario Limonciello1a680f32019-11-25 19:44:53 -06001754 *
1755 * Since: 1.1.2
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001756 **/
1757void
Richard Hughes12724852018-09-04 13:53:44 +01001758fu_plugin_add_udev_subsystem (FuPlugin *self, const gchar *subsystem)
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001759{
Richard Hughes12724852018-09-04 13:53:44 +01001760 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesea327fc2020-06-22 15:23:29 +01001761 if (priv->udev_subsystems == NULL)
1762 priv->udev_subsystems = g_ptr_array_new_with_free_func (g_free);
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001763 for (guint i = 0; i < priv->udev_subsystems->len; i++) {
1764 const gchar *subsystem_tmp = g_ptr_array_index (priv->udev_subsystems, i);
1765 if (g_strcmp0 (subsystem_tmp, subsystem) == 0)
1766 return;
1767 }
1768 g_debug ("added udev subsystem watch of %s", subsystem);
1769 g_ptr_array_add (priv->udev_subsystems, g_strdup (subsystem));
1770}
1771
Richard Hughes989acf12019-10-05 20:16:47 +01001772/**
1773 * fu_plugin_set_device_gtype:
1774 * @self: a #FuPlugin
1775 * @device_gtype: a #GType `FU_TYPE_DEVICE`
1776 *
1777 * Sets the device #GType which is used when creating devices.
1778 *
Richard Hughes525f71f2021-02-09 14:52:47 +00001779 * If this method is used then fu_plugin_backend_device_added() is not called, and
Richard Hughes989acf12019-10-05 20:16:47 +01001780 * instead the object is created in the daemon for the plugin.
1781 *
1782 * Plugins can use this method only in fu_plugin_init()
1783 *
1784 * Since: 1.3.3
1785 **/
1786void
1787fu_plugin_set_device_gtype (FuPlugin *self, GType device_gtype)
1788{
1789 FuPluginPrivate *priv = GET_PRIVATE (self);
1790 priv->device_gtype = device_gtype;
1791}
1792
Richard Hughes9f71fe32021-01-03 20:35:36 +00001793static gchar *
1794fu_common_string_uncamelcase (const gchar *str)
1795{
1796 GString *tmp = g_string_new (NULL);
1797 for (guint i = 0; str[i] != '\0'; i++) {
1798 if (g_ascii_islower (str[i]) ||
1799 g_ascii_isdigit (str[i])) {
1800 g_string_append_c (tmp, str[i]);
1801 continue;
1802 }
1803 if (i > 0)
1804 g_string_append_c (tmp, '-');
1805 g_string_append_c (tmp, g_ascii_tolower (str[i]));
1806 }
1807 return g_string_free (tmp, FALSE);
1808}
1809
Mario Limonciello1a680f32019-11-25 19:44:53 -06001810/**
1811 * fu_plugin_add_firmware_gtype:
1812 * @self: a #FuPlugin
Richard Hughes9f71fe32021-01-03 20:35:36 +00001813 * @id: (nullable): An optional string describing the type, e.g. "ihex"
1814 * @gtype: a #GType e.g. `FU_TYPE_FOO_FIRMWARE`
Mario Limonciello1a680f32019-11-25 19:44:53 -06001815 *
Richard Hughes9f71fe32021-01-03 20:35:36 +00001816 * Adds a firmware #GType which is used when creating devices. If @id is not
1817 * specified then it is guessed using the #GType name.
1818 *
Mario Limonciello1a680f32019-11-25 19:44:53 -06001819 * Plugins can use this method only in fu_plugin_init()
1820 *
1821 * Since: 1.3.3
1822 **/
Richard Hughes95c98a92019-10-22 16:03:15 +01001823void
1824fu_plugin_add_firmware_gtype (FuPlugin *self, const gchar *id, GType gtype)
1825{
Richard Hughes9f71fe32021-01-03 20:35:36 +00001826 g_autofree gchar *id_safe = NULL;
1827 if (id != NULL) {
1828 id_safe = g_strdup (id);
1829 } else {
Richard Hughesebb10a52021-01-05 13:34:39 +00001830 g_autoptr(GString) str = g_string_new (g_type_name (gtype));
Richard Hughes9f71fe32021-01-03 20:35:36 +00001831 if (g_str_has_prefix (str->str, "Fu"))
1832 g_string_erase (str, 0, 2);
1833 fu_common_string_replace (str, "Firmware", "");
1834 id_safe = fu_common_string_uncamelcase (str->str);
1835 }
1836 g_signal_emit (self, signals[SIGNAL_ADD_FIRMWARE_GTYPE], 0, id_safe, gtype);
Richard Hughes95c98a92019-10-22 16:03:15 +01001837}
1838
Richard Hughes989acf12019-10-05 20:16:47 +01001839static gboolean
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001840fu_plugin_check_supported_device (FuPlugin *self, FuDevice *device)
1841{
1842 GPtrArray *instance_ids = fu_device_get_instance_ids (device);
1843 for (guint i = 0; i < instance_ids->len; i++) {
1844 const gchar *instance_id = g_ptr_array_index (instance_ids, i);
1845 g_autofree gchar *guid = fwupd_guid_hash_string (instance_id);
1846 if (fu_plugin_check_supported (self, guid))
1847 return TRUE;
1848 }
1849 return FALSE;
1850}
1851
1852static gboolean
Richard Hughes525f71f2021-02-09 14:52:47 +00001853fu_plugin_backend_device_added (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughes989acf12019-10-05 20:16:47 +01001854{
1855 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001856 GType device_gtype = fu_device_get_specialized_gtype (FU_DEVICE (device));
Richard Hughes989acf12019-10-05 20:16:47 +01001857 g_autoptr(FuDevice) dev = NULL;
1858 g_autoptr(FuDeviceLocker) locker = NULL;
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001859
1860 /* fall back to plugin default */
1861 if (device_gtype == G_TYPE_INVALID)
1862 device_gtype = priv->device_gtype;
1863
1864 /* create new device and incorporate existing properties */
1865 dev = g_object_new (device_gtype, NULL);
1866 fu_device_incorporate (dev, FU_DEVICE (device));
Richard Hughes0f66a022020-02-19 18:54:38 +00001867 if (!fu_plugin_runner_device_created (self, dev, error))
1868 return FALSE;
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001869
1870 /* there are a lot of different devices that match, but not all respond
1871 * well to opening -- so limit some ones with issued updates */
Richard Hughescf100292021-01-04 10:36:37 +00001872 if (fu_device_has_internal_flag (dev, FU_DEVICE_INTERNAL_FLAG_ONLY_SUPPORTED)) {
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001873 if (!fu_device_probe (dev, error))
1874 return FALSE;
1875 fu_device_convert_instance_ids (dev);
1876 if (!fu_plugin_check_supported_device (self, dev)) {
1877 g_autofree gchar *guids = fu_device_get_guids_as_str (dev);
1878 g_debug ("%s has no updates, so ignoring device", guids);
1879 return TRUE;
1880 }
1881 }
1882
1883 /* open and add */
1884 locker = fu_device_locker_new (dev, error);
1885 if (locker == NULL)
1886 return FALSE;
1887 fu_plugin_device_add (self, dev);
Richard Hughes6a078702020-05-09 20:36:33 +01001888 fu_plugin_runner_device_added (self, dev);
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001889 return TRUE;
1890}
1891
Mario Limonciello1a680f32019-11-25 19:44:53 -06001892/**
1893 * fu_plugin_runner_usb_device_added:
1894 * @self: a #FuPlugin
1895 * @device: a #FuUsbDevice
1896 * @error: a #GError or NULL
1897 *
Richard Hughes525f71f2021-02-09 14:52:47 +00001898 * Call the backend_device_added routine for the plugin
Mario Limonciello1a680f32019-11-25 19:44:53 -06001899 *
1900 * Returns: #TRUE for success, #FALSE for failure
1901 *
1902 * Since: 1.0.2
1903 **/
Richard Hughes104f6512017-11-24 11:44:57 +00001904gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001905fu_plugin_runner_usb_device_added (FuPlugin *self, FuUsbDevice *device, GError **error)
Richard Hughes104f6512017-11-24 11:44:57 +00001906{
Richard Hughes525f71f2021-02-09 14:52:47 +00001907 return fu_plugin_runner_backend_device_added (self, FU_DEVICE (device), error);
Richard Hughes104f6512017-11-24 11:44:57 +00001908}
1909
Mario Limonciello1a680f32019-11-25 19:44:53 -06001910/**
1911 * fu_plugin_runner_udev_device_added:
1912 * @self: a #FuPlugin
1913 * @device: a #FuUdevDevice
1914 * @error: a #GError or NULL
1915 *
Richard Hughes525f71f2021-02-09 14:52:47 +00001916 * Call the backend_device_added routine for the plugin
Mario Limonciello1a680f32019-11-25 19:44:53 -06001917 *
1918 * Returns: #TRUE for success, #FALSE for failure
1919 *
1920 * Since: 1.0.2
1921 **/
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001922gboolean
Richard Hughes12724852018-09-04 13:53:44 +01001923fu_plugin_runner_udev_device_added (FuPlugin *self, FuUdevDevice *device, GError **error)
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001924{
Richard Hughes525f71f2021-02-09 14:52:47 +00001925 return fu_plugin_runner_backend_device_added (self, FU_DEVICE (device), error);
1926}
1927
1928/**
1929 * fu_plugin_runner_backend_device_added:
1930 * @self: a #FuPlugin
1931 * @device: a #FuDevice
1932 * @error: a #GError or NULL
1933 *
1934 * Call the backend_device_added routine for the plugin
1935 *
1936 * Returns: #TRUE for success, #FALSE for failure
1937 *
1938 * Since: 1.5.6
1939 **/
1940gboolean
1941fu_plugin_runner_backend_device_added (FuPlugin *self, FuDevice *device, GError **error)
1942{
Richard Hughes12724852018-09-04 13:53:44 +01001943 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes525f71f2021-02-09 14:52:47 +00001944 FuPluginDeviceFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001945 g_autoptr(GError) error_local = NULL;
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001946
Richard Hughes6a489a92020-12-22 10:32:06 +00001947 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
Richard Hughes525f71f2021-02-09 14:52:47 +00001948 g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
Richard Hughes6a489a92020-12-22 10:32:06 +00001949 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1950
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001951 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001952 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001953 return TRUE;
1954
1955 /* no object loaded */
1956 if (priv->module == NULL)
1957 return TRUE;
1958
1959 /* optional */
Richard Hughes525f71f2021-02-09 14:52:47 +00001960 g_module_symbol (priv->module, "fu_plugin_backend_device_added", (gpointer *) &func);
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001961 if (func == NULL) {
1962 if (priv->device_gtype != G_TYPE_INVALID ||
Richard Hughes525f71f2021-02-09 14:52:47 +00001963 fu_device_get_specialized_gtype (device) != G_TYPE_INVALID) {
1964 return fu_plugin_backend_device_added (self, device, error);
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001965 }
Richard Hughesa21e0252020-12-01 12:21:33 +00001966 g_set_error_literal (error,
1967 FWUPD_ERROR,
1968 FWUPD_ERROR_INTERNAL,
1969 "No device GType set");
1970 return FALSE;
Richard Hughesd8a8d5e2019-10-08 13:05:02 +01001971 }
Richard Hughes525f71f2021-02-09 14:52:47 +00001972 g_debug ("backend_device_added(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001973 if (!func (self, device, &error_local)) {
1974 if (error_local == NULL) {
Richard Hughes525f71f2021-02-09 14:52:47 +00001975 g_critical ("unset plugin error in backend_device_added(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001976 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001977 g_set_error_literal (&error_local,
1978 FWUPD_ERROR,
1979 FWUPD_ERROR_INTERNAL,
1980 "unspecified error");
1981 }
1982 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
1983 "failed to add device using on %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01001984 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00001985 return FALSE;
Richard Hughes9d6e0e72018-08-24 20:20:17 +01001986 }
1987 return TRUE;
1988}
1989
Mario Limonciello1a680f32019-11-25 19:44:53 -06001990/**
1991 * fu_plugin_runner_udev_device_changed:
1992 * @self: a #FuPlugin
1993 * @device: a #FuUdevDevice
1994 * @error: a #GError or NULL
1995 *
Richard Hughes525f71f2021-02-09 14:52:47 +00001996 * Call the backend_device_changed routine for the plugin
Mario Limonciello1a680f32019-11-25 19:44:53 -06001997 *
1998 * Returns: #TRUE for success, #FALSE for failure
1999 *
2000 * Since: 1.0.2
2001 **/
Richard Hughes5e952ce2019-08-26 11:09:46 +01002002gboolean
2003fu_plugin_runner_udev_device_changed (FuPlugin *self, FuUdevDevice *device, GError **error)
2004{
Richard Hughes525f71f2021-02-09 14:52:47 +00002005 return fu_plugin_runner_backend_device_changed (self, FU_DEVICE (device), error);
2006}
2007
2008/**
2009 * fu_plugin_runner_backend_device_changed:
2010 * @self: a #FuPlugin
2011 * @device: a #FuDevice
2012 * @error: a #GError or NULL
2013 *
2014 * Call the backend_device_changed routine for the plugin
2015 *
2016 * Returns: #TRUE for success, #FALSE for failure
2017 *
2018 * Since: 1.5.6
2019 **/
2020gboolean
2021fu_plugin_runner_backend_device_changed (FuPlugin *self, FuDevice *device, GError **error)
2022{
Richard Hughes5e952ce2019-08-26 11:09:46 +01002023 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes525f71f2021-02-09 14:52:47 +00002024 FuPluginDeviceFunc func = NULL;
Richard Hughes5e952ce2019-08-26 11:09:46 +01002025 g_autoptr(GError) error_local = NULL;
2026
Richard Hughes6a489a92020-12-22 10:32:06 +00002027 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
Richard Hughes525f71f2021-02-09 14:52:47 +00002028 g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
Richard Hughes6a489a92020-12-22 10:32:06 +00002029 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2030
Richard Hughes5e952ce2019-08-26 11:09:46 +01002031 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002032 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes5e952ce2019-08-26 11:09:46 +01002033 return TRUE;
2034
2035 /* no object loaded */
2036 if (priv->module == NULL)
2037 return TRUE;
2038
2039 /* optional */
Richard Hughes525f71f2021-02-09 14:52:47 +00002040 g_module_symbol (priv->module, "fu_plugin_backend_device_changed", (gpointer *) &func);
Mario Limonciello6d235142020-09-10 21:35:17 -05002041 if (func == NULL)
Richard Hughes5e952ce2019-08-26 11:09:46 +01002042 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002043 g_debug ("udev_device_changed(%s)", fu_plugin_get_name (self));
Richard Hughes5e952ce2019-08-26 11:09:46 +01002044 if (!func (self, device, &error_local)) {
2045 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05002046 g_critical ("unset plugin error in udev_device_changed(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002047 fu_plugin_get_name (self));
Richard Hughes5e952ce2019-08-26 11:09:46 +01002048 g_set_error_literal (&error_local,
2049 FWUPD_ERROR,
2050 FWUPD_ERROR_INTERNAL,
2051 "unspecified error");
2052 }
2053 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
2054 "failed to change device on %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002055 fu_plugin_get_name (self));
Richard Hughes5e952ce2019-08-26 11:09:46 +01002056 return FALSE;
2057 }
2058 return TRUE;
2059}
2060
Mario Limonciello1a680f32019-11-25 19:44:53 -06002061/**
Richard Hughes6a078702020-05-09 20:36:33 +01002062 * fu_plugin_runner_device_added:
2063 * @self: a #FuPlugin
2064 * @device: a #FuDevice
2065 *
2066 * Call the device_added routine for the plugin
2067 *
2068 * Since: 1.5.0
2069 **/
2070void
2071fu_plugin_runner_device_added (FuPlugin *self, FuDevice *device)
2072{
2073 FuPluginPrivate *priv = GET_PRIVATE (self);
2074 FuPluginDeviceRegisterFunc func = NULL;
2075
2076 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002077 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes6a078702020-05-09 20:36:33 +01002078 return;
2079 if (priv->module == NULL)
2080 return;
2081
2082 /* optional */
2083 g_module_symbol (priv->module, "fu_plugin_device_added", (gpointer *) &func);
2084 if (func == NULL)
2085 return;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002086 g_debug ("fu_plugin_device_added(%s)", fu_plugin_get_name (self));
Richard Hughes6a078702020-05-09 20:36:33 +01002087 func (self, device);
2088}
2089
2090/**
Mario Limonciello1a680f32019-11-25 19:44:53 -06002091 * fu_plugin_runner_device_removed:
2092 * @self: a #FuPlugin
2093 * @device: a #FuDevice
2094 *
2095 * Call the device_removed routine for the plugin
2096 *
2097 * Since: 1.1.2
2098 **/
Richard Hughese1fd34d2017-08-24 14:19:51 +01002099void
Richard Hughes12724852018-09-04 13:53:44 +01002100fu_plugin_runner_device_removed (FuPlugin *self, FuDevice *device)
Mario Limoncielloe260ead2018-09-01 09:19:24 -05002101{
2102 g_autoptr(GError) error_local= NULL;
2103
Richard Hughes12724852018-09-04 13:53:44 +01002104 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes525f71f2021-02-09 14:52:47 +00002105 "fu_plugin_backend_device_removed",
Richard Hughes4b303802019-10-04 13:22:51 +01002106 NULL,
Mario Limoncielloe260ead2018-09-01 09:19:24 -05002107 &error_local))
2108 g_warning ("%s", error_local->message);
2109}
2110
Mario Limonciello1a680f32019-11-25 19:44:53 -06002111/**
2112 * fu_plugin_runner_device_register:
2113 * @self: a #FuPlugin
2114 * @device: a #FuDevice
2115 *
2116 * Call the device_registered routine for the plugin
2117 *
2118 * Since: 0.9.7
2119 **/
Mario Limoncielloe260ead2018-09-01 09:19:24 -05002120void
Richard Hughes12724852018-09-04 13:53:44 +01002121fu_plugin_runner_device_register (FuPlugin *self, FuDevice *device)
Richard Hughese1fd34d2017-08-24 14:19:51 +01002122{
Richard Hughes12724852018-09-04 13:53:44 +01002123 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughese1fd34d2017-08-24 14:19:51 +01002124 FuPluginDeviceRegisterFunc func = NULL;
2125
2126 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002127 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughese1fd34d2017-08-24 14:19:51 +01002128 return;
Richard Hughes34834102017-11-21 21:55:00 +00002129 if (priv->module == NULL)
2130 return;
Richard Hughese1fd34d2017-08-24 14:19:51 +01002131
2132 /* optional */
2133 g_module_symbol (priv->module, "fu_plugin_device_registered", (gpointer *) &func);
2134 if (func != NULL) {
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002135 g_debug ("fu_plugin_device_registered(%s)", fu_plugin_get_name (self));
Richard Hughes12724852018-09-04 13:53:44 +01002136 func (self, device);
Richard Hughese1fd34d2017-08-24 14:19:51 +01002137 }
2138}
2139
Mario Limonciello1a680f32019-11-25 19:44:53 -06002140/**
Richard Hughes0f66a022020-02-19 18:54:38 +00002141 * fu_plugin_runner_device_created:
2142 * @self: a #FuPlugin
2143 * @device: a #FuDevice
2144 * @error: a #GError or NULL
2145 *
2146 * Call the device_created routine for the plugin
2147 *
2148 * Returns: #TRUE for success, #FALSE for failure
2149 *
Mario Limonciello96117d12020-02-28 10:17:56 -06002150 * Since: 1.4.0
Richard Hughes0f66a022020-02-19 18:54:38 +00002151 **/
2152gboolean
2153fu_plugin_runner_device_created (FuPlugin *self, FuDevice *device, GError **error)
2154{
2155 FuPluginPrivate *priv = GET_PRIVATE (self);
2156 FuPluginDeviceFunc func = NULL;
2157
Richard Hughes6a489a92020-12-22 10:32:06 +00002158 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
2159 g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
2160 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2161
Richard Hughes0f66a022020-02-19 18:54:38 +00002162 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002163 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughes0f66a022020-02-19 18:54:38 +00002164 return TRUE;
2165 if (priv->module == NULL)
2166 return TRUE;
2167
2168 /* optional */
2169 g_module_symbol (priv->module, "fu_plugin_device_created", (gpointer *) &func);
2170 if (func == NULL)
2171 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002172 g_debug ("fu_plugin_device_created(%s)", fu_plugin_get_name (self));
Richard Hughes0f66a022020-02-19 18:54:38 +00002173 return func (self, device, error);
2174}
2175
2176/**
Mario Limonciello1a680f32019-11-25 19:44:53 -06002177 * fu_plugin_runner_verify:
2178 * @self: a #FuPlugin
2179 * @device: a #FuDevice
2180 * @flags: #FuPluginVerifyFlags
2181 * @error: A #GError or NULL
2182 *
2183 * Call into the plugin's verify routine
2184 *
2185 * Returns: #TRUE for success, #FALSE for failure
2186 *
2187 * Since: 0.8.0
2188 **/
Richard Hughescff38bc2016-12-12 12:03:37 +00002189gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002190fu_plugin_runner_verify (FuPlugin *self,
Richard Hughescff38bc2016-12-12 12:03:37 +00002191 FuDevice *device,
2192 FuPluginVerifyFlags flags,
2193 GError **error)
2194{
Richard Hughes12724852018-09-04 13:53:44 +01002195 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes7b8b2022016-12-12 16:15:03 +00002196 FuPluginVerifyFunc func = NULL;
Richard Hughesababbb72017-06-15 20:18:36 +01002197 GPtrArray *checksums;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002198 g_autoptr(GError) error_local = NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +00002199
Richard Hughes6a489a92020-12-22 10:32:06 +00002200 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
2201 g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
2202 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2203
Richard Hughescff38bc2016-12-12 12:03:37 +00002204 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002205 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughescff38bc2016-12-12 12:03:37 +00002206 return TRUE;
2207
Richard Hughes639da472018-01-06 22:35:04 +00002208 /* no object loaded */
2209 if (priv->module == NULL)
2210 return TRUE;
2211
Richard Hughescff38bc2016-12-12 12:03:37 +00002212 /* optional */
2213 g_module_symbol (priv->module, "fu_plugin_verify", (gpointer *) &func);
Richard Hughes7f677212019-10-05 16:19:40 +01002214 if (func == NULL) {
Richard Hughes7f677212019-10-05 16:19:40 +01002215 return fu_plugin_device_read_firmware (self, device, error);
2216 }
Richard Hughes1812fc72018-12-14 11:37:54 +00002217
2218 /* clear any existing verification checksums */
2219 checksums = fu_device_get_checksums (device);
2220 g_ptr_array_set_size (checksums, 0);
2221
Richard Hughesc9223be2019-03-18 08:46:42 +00002222 /* run additional detach */
2223 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes42f33df2019-10-05 20:52:33 +01002224 "fu_plugin_update_detach",
Richard Hughes4b303802019-10-04 13:22:51 +01002225 fu_plugin_device_detach,
Richard Hughesc9223be2019-03-18 08:46:42 +00002226 error))
2227 return FALSE;
2228
Richard Hughes1812fc72018-12-14 11:37:54 +00002229 /* run vfunc */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002230 g_debug ("verify(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002231 if (!func (self, device, flags, &error_local)) {
Richard Hughesc9223be2019-03-18 08:46:42 +00002232 g_autoptr(GError) error_attach = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002233 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05002234 g_critical ("unset plugin error in verify(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002235 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002236 g_set_error_literal (&error_local,
2237 FWUPD_ERROR,
2238 FWUPD_ERROR_INTERNAL,
2239 "unspecified error");
2240 }
2241 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
2242 "failed to verify using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002243 fu_plugin_get_name (self));
Richard Hughesc9223be2019-03-18 08:46:42 +00002244 /* make the device "work" again, but don't prefix the error */
2245 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes42f33df2019-10-05 20:52:33 +01002246 "fu_plugin_update_attach",
Richard Hughes4b303802019-10-04 13:22:51 +01002247 fu_plugin_device_attach,
Richard Hughesc9223be2019-03-18 08:46:42 +00002248 &error_attach)) {
2249 g_warning ("failed to attach whilst aborting verify(): %s",
2250 error_attach->message);
2251 }
Richard Hughesd0905142016-03-13 09:46:49 +00002252 return FALSE;
2253 }
Richard Hughesc9223be2019-03-18 08:46:42 +00002254
2255 /* run optional attach */
2256 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes42f33df2019-10-05 20:52:33 +01002257 "fu_plugin_update_attach",
Richard Hughes4b303802019-10-04 13:22:51 +01002258 fu_plugin_device_attach,
Richard Hughesc9223be2019-03-18 08:46:42 +00002259 error))
2260 return FALSE;
2261
2262 /* success */
Richard Hughesd0905142016-03-13 09:46:49 +00002263 return TRUE;
2264}
2265
Mario Limonciello1a680f32019-11-25 19:44:53 -06002266/**
2267 * fu_plugin_runner_activate:
2268 * @self: a #FuPlugin
2269 * @device: a #FuDevice
2270 * @error: A #GError or NULL
2271 *
2272 * Call into the plugin's activate routine
2273 *
2274 * Returns: #TRUE for success, #FALSE for failure
2275 *
2276 * Since: 1.2.6
2277 **/
Richard Hughesd0905142016-03-13 09:46:49 +00002278gboolean
Mario Limonciello96a0dd52019-02-25 13:50:03 -06002279fu_plugin_runner_activate (FuPlugin *self, FuDevice *device, GError **error)
2280{
2281 guint64 flags;
2282
Richard Hughes6a489a92020-12-22 10:32:06 +00002283 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
2284 g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
2285 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2286
Mario Limonciello96a0dd52019-02-25 13:50:03 -06002287 /* final check */
2288 flags = fu_device_get_flags (device);
2289 if ((flags & FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION) == 0) {
2290 g_set_error (error,
2291 FWUPD_ERROR,
2292 FWUPD_ERROR_NOT_SUPPORTED,
2293 "Device %s does not need activation",
2294 fu_device_get_id (device));
2295 return FALSE;
2296 }
2297
2298 /* run vfunc */
2299 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes4b303802019-10-04 13:22:51 +01002300 "fu_plugin_activate",
2301 fu_plugin_device_activate,
2302 error))
Mario Limonciello96a0dd52019-02-25 13:50:03 -06002303 return FALSE;
2304
2305 /* update with correct flags */
2306 fu_device_remove_flag (device, FWUPD_DEVICE_FLAG_NEEDS_ACTIVATION);
2307 fu_device_set_modified (device, (guint64) g_get_real_time () / G_USEC_PER_SEC);
2308 return TRUE;
2309}
2310
Mario Limonciello1a680f32019-11-25 19:44:53 -06002311/**
2312 * fu_plugin_runner_unlock:
2313 * @self: a #FuPlugin
2314 * @device: a #FuDevice
2315 * @error: A #GError or NULL
2316 *
2317 * Call into the plugin's unlock routine
2318 *
2319 * Returns: #TRUE for success, #FALSE for failure
2320 *
2321 * Since: 0.8.0
2322 **/
Mario Limonciello96a0dd52019-02-25 13:50:03 -06002323gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002324fu_plugin_runner_unlock (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughesd0905142016-03-13 09:46:49 +00002325{
Richard Hughescff38bc2016-12-12 12:03:37 +00002326 guint64 flags;
Richard Hughescff38bc2016-12-12 12:03:37 +00002327
Richard Hughes6a489a92020-12-22 10:32:06 +00002328 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
2329 g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
2330 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2331
Richard Hughescff38bc2016-12-12 12:03:37 +00002332 /* final check */
2333 flags = fu_device_get_flags (device);
2334 if ((flags & FWUPD_DEVICE_FLAG_LOCKED) == 0) {
2335 g_set_error (error,
2336 FWUPD_ERROR,
2337 FWUPD_ERROR_NOT_SUPPORTED,
2338 "Device %s is not locked",
2339 fu_device_get_id (device));
2340 return FALSE;
2341 }
2342
Richard Hughes9c4b5312017-11-14 11:34:53 +00002343 /* run vfunc */
Richard Hughes12724852018-09-04 13:53:44 +01002344 if (!fu_plugin_runner_device_generic (self, device,
Richard Hughes4b303802019-10-04 13:22:51 +01002345 "fu_plugin_unlock",
2346 NULL,
2347 error))
Richard Hughes9c4b5312017-11-14 11:34:53 +00002348 return FALSE;
Richard Hughescff38bc2016-12-12 12:03:37 +00002349
2350 /* update with correct flags */
2351 flags = fu_device_get_flags (device);
2352 fu_device_set_flags (device, flags &= ~FWUPD_DEVICE_FLAG_LOCKED);
2353 fu_device_set_modified (device, (guint64) g_get_real_time () / G_USEC_PER_SEC);
2354 return TRUE;
2355}
2356
Mario Limonciello1a680f32019-11-25 19:44:53 -06002357/**
2358 * fu_plugin_runner_update:
2359 * @self: a #FuPlugin
2360 * @device: a #FuDevice
2361 * @blob_fw: A #GBytes
2362 * @flags: A #FwupdInstallFlags
2363 * @error: A #GError or NULL
2364 *
2365 * Call into the plugin's update routine
2366 *
2367 * Returns: #TRUE for success, #FALSE for failure
2368 *
2369 * Since: 0.8.0
2370 **/
Richard Hughescff38bc2016-12-12 12:03:37 +00002371gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002372fu_plugin_runner_update (FuPlugin *self,
Richard Hughesa785a1c2017-08-25 16:00:58 +01002373 FuDevice *device,
Richard Hughesa785a1c2017-08-25 16:00:58 +01002374 GBytes *blob_fw,
2375 FwupdInstallFlags flags,
2376 GError **error)
Richard Hughescff38bc2016-12-12 12:03:37 +00002377{
Richard Hughes12724852018-09-04 13:53:44 +01002378 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesa785a1c2017-08-25 16:00:58 +01002379 FuPluginUpdateFunc update_func;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002380 g_autoptr(GError) error_local = NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +00002381
Richard Hughes6a489a92020-12-22 10:32:06 +00002382 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
2383 g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
2384 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2385
Richard Hughescff38bc2016-12-12 12:03:37 +00002386 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002387 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED)) {
Richard Hughes41c15482018-02-01 22:07:21 +00002388 g_debug ("plugin not enabled, skipping");
Richard Hughesd0905142016-03-13 09:46:49 +00002389 return TRUE;
Richard Hughes41c15482018-02-01 22:07:21 +00002390 }
Richard Hughesd0905142016-03-13 09:46:49 +00002391
Richard Hughes639da472018-01-06 22:35:04 +00002392 /* no object loaded */
Richard Hughes41c15482018-02-01 22:07:21 +00002393 if (priv->module == NULL) {
2394 g_debug ("module not enabled, skipping");
Richard Hughes639da472018-01-06 22:35:04 +00002395 return TRUE;
Richard Hughes41c15482018-02-01 22:07:21 +00002396 }
Richard Hughes639da472018-01-06 22:35:04 +00002397
Richard Hughesd0905142016-03-13 09:46:49 +00002398 /* optional */
Richard Hughesa785a1c2017-08-25 16:00:58 +01002399 g_module_symbol (priv->module, "fu_plugin_update", (gpointer *) &update_func);
2400 if (update_func == NULL) {
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002401 g_debug ("superclassed write_firmware(%s)", fu_plugin_get_name (self));
Richard Hughes4b303802019-10-04 13:22:51 +01002402 return fu_plugin_device_write_firmware (self, device, blob_fw, flags, error);
Richard Hughesa785a1c2017-08-25 16:00:58 +01002403 }
Richard Hughesd0905142016-03-13 09:46:49 +00002404
Richard Hughescff38bc2016-12-12 12:03:37 +00002405 /* online */
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002406 if (!update_func (self, device, blob_fw, flags, &error_local)) {
2407 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05002408 g_critical ("unset plugin error in update(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002409 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002410 g_set_error_literal (&error_local,
Richard Hughes3c8ada32018-10-12 10:08:58 +01002411 FWUPD_ERROR,
2412 FWUPD_ERROR_INTERNAL,
2413 "unspecified error");
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002414 return FALSE;
Richard Hughes3c8ada32018-10-12 10:08:58 +01002415 }
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002416 fu_device_set_update_error (device, error_local->message);
2417 g_propagate_error (error, g_steal_pointer (&error_local));
Richard Hughescff38bc2016-12-12 12:03:37 +00002418 return FALSE;
2419 }
2420
Richard Hughesf556d372017-06-15 19:49:18 +01002421 /* no longer valid */
Richard Hughesf8039642019-01-16 12:22:22 +00002422 if (!fu_device_has_flag (device, FWUPD_DEVICE_FLAG_NEEDS_REBOOT) &&
2423 !fu_device_has_flag (device, FWUPD_DEVICE_FLAG_NEEDS_SHUTDOWN)) {
Richard Hughes08435162018-12-12 10:34:16 +00002424 GPtrArray *checksums = fu_device_get_checksums (device);
2425 g_ptr_array_set_size (checksums, 0);
2426 }
Richard Hughesf556d372017-06-15 19:49:18 +01002427
Richard Hughes019a1bc2019-11-26 10:19:33 +00002428 /* success */
Richard Hughesd0905142016-03-13 09:46:49 +00002429 return TRUE;
2430}
Richard Hughescff38bc2016-12-12 12:03:37 +00002431
Mario Limonciello1a680f32019-11-25 19:44:53 -06002432/**
2433 * fu_plugin_runner_clear_results:
2434 * @self: a #FuPlugin
2435 * @device: a #FuDevice
2436 * @error: A #GError or NULL
2437 *
2438 * Call into the plugin's clear results routine
2439 *
2440 * Returns: #TRUE for success, #FALSE for failure
2441 *
2442 * Since: 0.8.0
2443 **/
Richard Hughescff38bc2016-12-12 12:03:37 +00002444gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002445fu_plugin_runner_clear_results (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughescff38bc2016-12-12 12:03:37 +00002446{
Richard Hughes12724852018-09-04 13:53:44 +01002447 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes7b8b2022016-12-12 16:15:03 +00002448 FuPluginDeviceFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002449 g_autoptr(GError) error_local = NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +00002450
Richard Hughes6a489a92020-12-22 10:32:06 +00002451 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
2452 g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
2453 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2454
Richard Hughescff38bc2016-12-12 12:03:37 +00002455 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002456 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughescff38bc2016-12-12 12:03:37 +00002457 return TRUE;
2458
Richard Hughes639da472018-01-06 22:35:04 +00002459 /* no object loaded */
2460 if (priv->module == NULL)
2461 return TRUE;
2462
Richard Hughes65e44ca2018-01-30 17:26:30 +00002463 /* optional */
Richard Hughescd644902019-11-01 12:35:17 +00002464 g_module_symbol (priv->module, "fu_plugin_clear_results", (gpointer *) &func);
Richard Hughes65e44ca2018-01-30 17:26:30 +00002465 if (func == NULL)
Richard Hughescff38bc2016-12-12 12:03:37 +00002466 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002467 g_debug ("clear_result(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002468 if (!func (self, device, &error_local)) {
2469 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05002470 g_critical ("unset plugin error in clear_result(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002471 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002472 g_set_error_literal (&error_local,
2473 FWUPD_ERROR,
2474 FWUPD_ERROR_INTERNAL,
2475 "unspecified error");
2476 }
2477 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
2478 "failed to clear_result using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002479 fu_plugin_get_name (self));
Richard Hughescff38bc2016-12-12 12:03:37 +00002480 return FALSE;
2481 }
Richard Hughes65e44ca2018-01-30 17:26:30 +00002482 return TRUE;
Richard Hughescff38bc2016-12-12 12:03:37 +00002483}
2484
Mario Limonciello1a680f32019-11-25 19:44:53 -06002485/**
2486 * fu_plugin_runner_get_results:
2487 * @self: a #FuPlugin
2488 * @device: a #FuDevice
2489 * @error: A #GError or NULL
2490 *
2491 * Call into the plugin's get results routine
2492 *
2493 * Returns: #TRUE for success, #FALSE for failure
2494 *
2495 * Since: 0.8.0
2496 **/
Richard Hughescff38bc2016-12-12 12:03:37 +00002497gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002498fu_plugin_runner_get_results (FuPlugin *self, FuDevice *device, GError **error)
Richard Hughescff38bc2016-12-12 12:03:37 +00002499{
Richard Hughes12724852018-09-04 13:53:44 +01002500 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughes7b8b2022016-12-12 16:15:03 +00002501 FuPluginDeviceFunc func = NULL;
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002502 g_autoptr(GError) error_local = NULL;
Richard Hughescff38bc2016-12-12 12:03:37 +00002503
Richard Hughes6a489a92020-12-22 10:32:06 +00002504 g_return_val_if_fail (FU_IS_PLUGIN (self), FALSE);
2505 g_return_val_if_fail (FU_IS_DEVICE (device), FALSE);
2506 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
2507
Richard Hughescff38bc2016-12-12 12:03:37 +00002508 /* not enabled */
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002509 if (fu_plugin_has_flag (self, FWUPD_PLUGIN_FLAG_DISABLED))
Richard Hughescff38bc2016-12-12 12:03:37 +00002510 return TRUE;
2511
Richard Hughes639da472018-01-06 22:35:04 +00002512 /* no object loaded */
2513 if (priv->module == NULL)
2514 return TRUE;
2515
Richard Hughes65e44ca2018-01-30 17:26:30 +00002516 /* optional */
Richard Hughescff38bc2016-12-12 12:03:37 +00002517 g_module_symbol (priv->module, "fu_plugin_get_results", (gpointer *) &func);
Richard Hughes65e44ca2018-01-30 17:26:30 +00002518 if (func == NULL)
Richard Hughescff38bc2016-12-12 12:03:37 +00002519 return TRUE;
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002520 g_debug ("get_results(%s)", fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002521 if (!func (self, device, &error_local)) {
2522 if (error_local == NULL) {
Mario Limonciello67a8b892020-09-28 13:44:39 -05002523 g_critical ("unset plugin error in get_results(%s)",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002524 fu_plugin_get_name (self));
Richard Hughescd2fb3e2018-11-29 19:58:09 +00002525 g_set_error_literal (&error_local,
2526 FWUPD_ERROR,
2527 FWUPD_ERROR_INTERNAL,
2528 "unspecified error");
2529 }
2530 g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
2531 "failed to get_results using %s: ",
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002532 fu_plugin_get_name (self));
Richard Hughescff38bc2016-12-12 12:03:37 +00002533 return FALSE;
2534 }
Richard Hughescff38bc2016-12-12 12:03:37 +00002535 return TRUE;
2536}
2537
Richard Hughes08a37992017-09-12 12:57:43 +01002538/**
2539 * fu_plugin_get_order:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002540 * @self: a #FuPlugin
Richard Hughes08a37992017-09-12 12:57:43 +01002541 *
2542 * Gets the plugin order, where higher numbers are run after lower
2543 * numbers.
2544 *
2545 * Returns: the integer value
Mario Limonciello1a680f32019-11-25 19:44:53 -06002546 *
2547 * Since: 1.0.0
Richard Hughes08a37992017-09-12 12:57:43 +01002548 **/
2549guint
Richard Hughes12724852018-09-04 13:53:44 +01002550fu_plugin_get_order (FuPlugin *self)
Richard Hughes08a37992017-09-12 12:57:43 +01002551{
Richard Hughes12724852018-09-04 13:53:44 +01002552 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes08a37992017-09-12 12:57:43 +01002553 return priv->order;
2554}
2555
2556/**
2557 * fu_plugin_set_order:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002558 * @self: a #FuPlugin
Richard Hughes08a37992017-09-12 12:57:43 +01002559 * @order: a integer value
2560 *
2561 * Sets the plugin order, where higher numbers are run after lower
2562 * numbers.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002563 *
2564 * Since: 1.0.0
Richard Hughes08a37992017-09-12 12:57:43 +01002565 **/
2566void
Richard Hughes12724852018-09-04 13:53:44 +01002567fu_plugin_set_order (FuPlugin *self, guint order)
Richard Hughes08a37992017-09-12 12:57:43 +01002568{
Richard Hughes12724852018-09-04 13:53:44 +01002569 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes08a37992017-09-12 12:57:43 +01002570 priv->order = order;
2571}
2572
2573/**
Richard Hughes81c427c2018-08-06 15:20:17 +01002574 * fu_plugin_get_priority:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002575 * @self: a #FuPlugin
Richard Hughes81c427c2018-08-06 15:20:17 +01002576 *
2577 * Gets the plugin priority, where higher numbers are better.
2578 *
2579 * Returns: the integer value
Mario Limonciello1a680f32019-11-25 19:44:53 -06002580 *
2581 * Since: 1.1.1
Richard Hughes81c427c2018-08-06 15:20:17 +01002582 **/
2583guint
Richard Hughes12724852018-09-04 13:53:44 +01002584fu_plugin_get_priority (FuPlugin *self)
Richard Hughes81c427c2018-08-06 15:20:17 +01002585{
Richard Hughes12724852018-09-04 13:53:44 +01002586 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes81c427c2018-08-06 15:20:17 +01002587 return priv->priority;
2588}
2589
2590/**
2591 * fu_plugin_set_priority:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002592 * @self: a #FuPlugin
Richard Hughes81c427c2018-08-06 15:20:17 +01002593 * @priority: a integer value
2594 *
2595 * Sets the plugin priority, where higher numbers are better.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002596 *
2597 * Since: 1.0.0
Richard Hughes81c427c2018-08-06 15:20:17 +01002598 **/
2599void
Richard Hughes12724852018-09-04 13:53:44 +01002600fu_plugin_set_priority (FuPlugin *self, guint priority)
Richard Hughes81c427c2018-08-06 15:20:17 +01002601{
Richard Hughes12724852018-09-04 13:53:44 +01002602 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes81c427c2018-08-06 15:20:17 +01002603 priv->priority = priority;
2604}
2605
2606/**
Richard Hughes08a37992017-09-12 12:57:43 +01002607 * fu_plugin_add_rule:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002608 * @self: a #FuPlugin
Richard Hughes08a37992017-09-12 12:57:43 +01002609 * @rule: a #FuPluginRule, e.g. %FU_PLUGIN_RULE_CONFLICTS
Richard Hughes4eada342017-10-03 21:20:32 +01002610 * @name: a plugin name, e.g. `upower`
Richard Hughes08a37992017-09-12 12:57:43 +01002611 *
2612 * If the plugin name is found, the rule will be used to sort the plugin list,
2613 * for example the plugin specified by @name will be ordered after this plugin
2614 * when %FU_PLUGIN_RULE_RUN_AFTER is used.
2615 *
2616 * NOTE: The depsolver is iterative and may not solve overly-complicated rules;
2617 * If depsolving fails then fwupd will not start.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002618 *
2619 * Since: 1.0.0
Richard Hughes08a37992017-09-12 12:57:43 +01002620 **/
2621void
Richard Hughes12724852018-09-04 13:53:44 +01002622fu_plugin_add_rule (FuPlugin *self, FuPluginRule rule, const gchar *name)
Richard Hughes08a37992017-09-12 12:57:43 +01002623{
Richard Hughes12724852018-09-04 13:53:44 +01002624 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes11c59412020-06-22 15:29:48 +01002625 if (priv->rules[rule] == NULL)
2626 priv->rules[rule] = g_ptr_array_new_with_free_func (g_free);
Richard Hughes08a37992017-09-12 12:57:43 +01002627 g_ptr_array_add (priv->rules[rule], g_strdup (name));
Richard Hughes75b965d2018-11-15 13:51:21 +00002628 g_signal_emit (self, signals[SIGNAL_RULES_CHANGED], 0);
Richard Hughes08a37992017-09-12 12:57:43 +01002629}
2630
2631/**
2632 * fu_plugin_get_rules:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002633 * @self: a #FuPlugin
Richard Hughes08a37992017-09-12 12:57:43 +01002634 * @rule: a #FuPluginRule, e.g. %FU_PLUGIN_RULE_CONFLICTS
2635 *
2636 * Gets the plugin IDs that should be run after this plugin.
2637 *
Richard Hughes11c59412020-06-22 15:29:48 +01002638 * Returns: (element-type utf8) (transfer none) (nullable): the list of plugin names, e.g. ['appstream']
Mario Limonciello1a680f32019-11-25 19:44:53 -06002639 *
2640 * Since: 1.0.0
Richard Hughes08a37992017-09-12 12:57:43 +01002641 **/
2642GPtrArray *
Richard Hughes12724852018-09-04 13:53:44 +01002643fu_plugin_get_rules (FuPlugin *self, FuPluginRule rule)
Richard Hughes08a37992017-09-12 12:57:43 +01002644{
Richard Hughes12724852018-09-04 13:53:44 +01002645 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughesdad35972019-12-06 11:00:25 +00002646 g_return_val_if_fail (rule < FU_PLUGIN_RULE_LAST, NULL);
Richard Hughes08a37992017-09-12 12:57:43 +01002647 return priv->rules[rule];
2648}
2649
Richard Hughes80b79bb2018-01-11 21:11:06 +00002650/**
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002651 * fu_plugin_has_rule:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002652 * @self: a #FuPlugin
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002653 * @rule: a #FuPluginRule, e.g. %FU_PLUGIN_RULE_CONFLICTS
2654 * @name: a plugin name, e.g. `upower`
2655 *
Richard Hughes87fb9ff2018-06-28 12:55:59 +01002656 * Gets the plugin IDs that should be run after this plugin.
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002657 *
2658 * Returns: %TRUE if the name exists for the specific rule
Mario Limonciello1a680f32019-11-25 19:44:53 -06002659 *
2660 * Since: 1.0.0
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002661 **/
2662gboolean
Richard Hughes12724852018-09-04 13:53:44 +01002663fu_plugin_has_rule (FuPlugin *self, FuPluginRule rule, const gchar *name)
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002664{
Richard Hughes12724852018-09-04 13:53:44 +01002665 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes11c59412020-06-22 15:29:48 +01002666 if (priv->rules[rule] == NULL)
2667 return FALSE;
Richard Hughes5f3a56b2018-06-28 12:13:59 +01002668 for (guint i = 0; i < priv->rules[rule]->len; i++) {
2669 const gchar *tmp = g_ptr_array_index (priv->rules[rule], i);
2670 if (g_strcmp0 (tmp, name) == 0)
2671 return TRUE;
2672 }
2673 return FALSE;
2674}
2675
2676/**
Richard Hughes80b79bb2018-01-11 21:11:06 +00002677 * fu_plugin_add_report_metadata:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002678 * @self: a #FuPlugin
Richard Hughes80b79bb2018-01-11 21:11:06 +00002679 * @key: a string, e.g. `FwupdateVersion`
2680 * @value: a string, e.g. `10`
2681 *
2682 * Sets any additional metadata to be included in the firmware report to aid
2683 * debugging problems.
2684 *
2685 * Any data included here will be sent to the metadata server after user
2686 * confirmation.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002687 *
2688 * Since: 1.0.4
Richard Hughes80b79bb2018-01-11 21:11:06 +00002689 **/
2690void
Richard Hughes12724852018-09-04 13:53:44 +01002691fu_plugin_add_report_metadata (FuPlugin *self, const gchar *key, const gchar *value)
Richard Hughes80b79bb2018-01-11 21:11:06 +00002692{
Richard Hughes12724852018-09-04 13:53:44 +01002693 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes1d900f72020-06-22 15:17:39 +01002694 if (priv->report_metadata == NULL) {
2695 priv->report_metadata = g_hash_table_new_full (g_str_hash,
2696 g_str_equal,
2697 g_free,
2698 g_free);
2699 }
Richard Hughes80b79bb2018-01-11 21:11:06 +00002700 g_hash_table_insert (priv->report_metadata, g_strdup (key), g_strdup (value));
2701}
2702
2703/**
2704 * fu_plugin_get_report_metadata:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002705 * @self: a #FuPlugin
Richard Hughes80b79bb2018-01-11 21:11:06 +00002706 *
2707 * Returns the list of additional metadata to be added when filing a report.
2708 *
Richard Hughes1d900f72020-06-22 15:17:39 +01002709 * Returns: (transfer none) (nullable): the map of report metadata
Mario Limonciello1a680f32019-11-25 19:44:53 -06002710 *
2711 * Since: 1.0.4
Richard Hughes80b79bb2018-01-11 21:11:06 +00002712 **/
2713GHashTable *
Richard Hughes12724852018-09-04 13:53:44 +01002714fu_plugin_get_report_metadata (FuPlugin *self)
Richard Hughes80b79bb2018-01-11 21:11:06 +00002715{
Richard Hughes12724852018-09-04 13:53:44 +01002716 FuPluginPrivate *priv = fu_plugin_get_instance_private (self);
Richard Hughes80b79bb2018-01-11 21:11:06 +00002717 return priv->report_metadata;
2718}
2719
Mario Limonciello963dc422018-02-27 14:26:58 -06002720/**
2721 * fu_plugin_get_config_value:
Richard Hughes2c0635a2018-09-04 14:52:46 +01002722 * @self: a #FuPlugin
Mario Limonciello963dc422018-02-27 14:26:58 -06002723 * @key: A settings key
2724 *
2725 * Return the value of a key if it's been configured
2726 *
2727 * Since: 1.0.6
2728 **/
2729gchar *
Richard Hughes12724852018-09-04 13:53:44 +01002730fu_plugin_get_config_value (FuPlugin *self, const gchar *key)
Mario Limonciello963dc422018-02-27 14:26:58 -06002731{
Richard Hughes4be17d12018-05-30 20:36:29 +01002732 g_autofree gchar *conf_dir = NULL;
Mario Limonciello963dc422018-02-27 14:26:58 -06002733 g_autofree gchar *conf_file = NULL;
2734 g_autofree gchar *conf_path = NULL;
2735 g_autoptr(GKeyFile) keyfile = NULL;
2736 const gchar *plugin_name;
2737
Richard Hughes4be17d12018-05-30 20:36:29 +01002738 conf_dir = fu_common_get_path (FU_PATH_KIND_SYSCONFDIR_PKG);
Richard Hughes12724852018-09-04 13:53:44 +01002739 plugin_name = fu_plugin_get_name (self);
Mario Limonciello963dc422018-02-27 14:26:58 -06002740 conf_file = g_strdup_printf ("%s.conf", plugin_name);
Richard Hughes4be17d12018-05-30 20:36:29 +01002741 conf_path = g_build_filename (conf_dir, conf_file, NULL);
Mario Limonciello963dc422018-02-27 14:26:58 -06002742 if (!g_file_test (conf_path, G_FILE_TEST_IS_REGULAR))
2743 return NULL;
2744 keyfile = g_key_file_new ();
2745 if (!g_key_file_load_from_file (keyfile, conf_path,
2746 G_KEY_FILE_NONE, NULL))
2747 return NULL;
2748 return g_key_file_get_string (keyfile, plugin_name, key, NULL);
2749}
2750
Richard Hughes8c71a3f2018-05-22 19:19:52 +01002751/**
Richard Hughes334ba792020-02-19 20:44:56 +00002752 * fu_plugin_get_config_value_boolean:
2753 * @self: a #FuPlugin
2754 * @key: A settings key
2755 *
2756 * Return the boolean value of a key if it's been configured
2757 *
2758 * Returns: %TRUE if the value is `true` (case insensitive), %FALSE otherwise
2759 *
Mario Limonciello96117d12020-02-28 10:17:56 -06002760 * Since: 1.4.0
Richard Hughes334ba792020-02-19 20:44:56 +00002761 **/
2762gboolean
2763fu_plugin_get_config_value_boolean (FuPlugin *self, const gchar *key)
2764{
2765 g_autofree gchar *tmp = fu_plugin_get_config_value (self, key);
2766 if (tmp == NULL)
2767 return FALSE;
Richard Hughes5337a432020-02-21 12:04:32 +00002768 return g_ascii_strcasecmp (tmp, "true") == 0;
Richard Hughes334ba792020-02-19 20:44:56 +00002769}
2770
2771/**
Richard Hughes8c71a3f2018-05-22 19:19:52 +01002772 * fu_plugin_name_compare:
2773 * @plugin1: first #FuPlugin to compare.
2774 * @plugin2: second #FuPlugin to compare.
2775 *
2776 * Compares two plugins by their names.
2777 *
2778 * Returns: 1, 0 or -1 if @plugin1 is greater, equal, or less than @plugin2.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002779 *
2780 * Since: 1.0.8
Richard Hughes8c71a3f2018-05-22 19:19:52 +01002781 **/
2782gint
2783fu_plugin_name_compare (FuPlugin *plugin1, FuPlugin *plugin2)
2784{
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002785 return g_strcmp0 (fu_plugin_get_name (plugin1), fu_plugin_get_name (plugin2));
Richard Hughes8c71a3f2018-05-22 19:19:52 +01002786}
2787
2788/**
2789 * fu_plugin_order_compare:
2790 * @plugin1: first #FuPlugin to compare.
2791 * @plugin2: second #FuPlugin to compare.
2792 *
2793 * Compares two plugins by their depsolved order.
2794 *
2795 * Returns: 1, 0 or -1 if @plugin1 is greater, equal, or less than @plugin2.
Mario Limonciello1a680f32019-11-25 19:44:53 -06002796 *
2797 * Since: 1.0.8
Richard Hughes8c71a3f2018-05-22 19:19:52 +01002798 **/
2799gint
2800fu_plugin_order_compare (FuPlugin *plugin1, FuPlugin *plugin2)
2801{
2802 FuPluginPrivate *priv1 = fu_plugin_get_instance_private (plugin1);
2803 FuPluginPrivate *priv2 = fu_plugin_get_instance_private (plugin2);
2804 if (priv1->order < priv2->order)
2805 return -1;
2806 if (priv1->order > priv2->order)
2807 return 1;
2808 return 0;
2809}
2810
Richard Hughescff38bc2016-12-12 12:03:37 +00002811static void
2812fu_plugin_class_init (FuPluginClass *klass)
2813{
2814 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2815 object_class->finalize = fu_plugin_finalize;
2816 signals[SIGNAL_DEVICE_ADDED] =
2817 g_signal_new ("device-added",
2818 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2819 G_STRUCT_OFFSET (FuPluginClass, device_added),
2820 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2821 G_TYPE_NONE, 1, FU_TYPE_DEVICE);
2822 signals[SIGNAL_DEVICE_REMOVED] =
2823 g_signal_new ("device-removed",
2824 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2825 G_STRUCT_OFFSET (FuPluginClass, device_removed),
2826 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2827 G_TYPE_NONE, 1, FU_TYPE_DEVICE);
Richard Hughese1fd34d2017-08-24 14:19:51 +01002828 signals[SIGNAL_DEVICE_REGISTER] =
2829 g_signal_new ("device-register",
2830 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2831 G_STRUCT_OFFSET (FuPluginClass, device_register),
2832 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2833 G_TYPE_NONE, 1, FU_TYPE_DEVICE);
Richard Hughes362d6d72017-01-07 21:42:14 +00002834 signals[SIGNAL_RECOLDPLUG] =
2835 g_signal_new ("recoldplug",
2836 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2837 G_STRUCT_OFFSET (FuPluginClass, recoldplug),
2838 NULL, NULL, g_cclosure_marshal_VOID__VOID,
2839 G_TYPE_NONE, 0);
Richard Hughes399859e2020-05-11 19:44:03 +01002840 signals[SIGNAL_SECURITY_CHANGED] =
2841 g_signal_new ("security-changed",
2842 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2843 G_STRUCT_OFFSET (FuPluginClass, security_changed),
2844 NULL, NULL, g_cclosure_marshal_VOID__VOID,
2845 G_TYPE_NONE, 0);
Richard Hughesb0829032017-01-10 09:27:08 +00002846 signals[SIGNAL_SET_COLDPLUG_DELAY] =
2847 g_signal_new ("set-coldplug-delay",
2848 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2849 G_STRUCT_OFFSET (FuPluginClass, set_coldplug_delay),
2850 NULL, NULL, g_cclosure_marshal_VOID__UINT,
2851 G_TYPE_NONE, 1, G_TYPE_UINT);
Richard Hughesaabdc372018-11-14 10:11:08 +00002852 signals[SIGNAL_CHECK_SUPPORTED] =
2853 g_signal_new ("check-supported",
2854 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2855 G_STRUCT_OFFSET (FuPluginClass, check_supported),
2856 NULL, NULL, g_cclosure_marshal_generic,
2857 G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
Richard Hughes75b965d2018-11-15 13:51:21 +00002858 signals[SIGNAL_RULES_CHANGED] =
2859 g_signal_new ("rules-changed",
2860 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2861 G_STRUCT_OFFSET (FuPluginClass, rules_changed),
2862 NULL, NULL, g_cclosure_marshal_VOID__VOID,
2863 G_TYPE_NONE, 0);
Richard Hughes95c98a92019-10-22 16:03:15 +01002864 signals[SIGNAL_ADD_FIRMWARE_GTYPE] =
2865 g_signal_new ("add-firmware-gtype",
2866 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2867 G_STRUCT_OFFSET (FuPluginClass, add_firmware_gtype),
2868 NULL, NULL, g_cclosure_marshal_generic,
2869 G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_GTYPE);
Richard Hughescff38bc2016-12-12 12:03:37 +00002870}
2871
2872static void
Richard Hughes12724852018-09-04 13:53:44 +01002873fu_plugin_init (FuPlugin *self)
Richard Hughescff38bc2016-12-12 12:03:37 +00002874{
Richard Hughes12724852018-09-04 13:53:44 +01002875 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughesfaf2afe2021-01-13 14:00:20 +00002876 g_rw_lock_init (&priv->cache_mutex);
Richard Hughescff38bc2016-12-12 12:03:37 +00002877}
2878
2879static void
2880fu_plugin_finalize (GObject *object)
2881{
Richard Hughes12724852018-09-04 13:53:44 +01002882 FuPlugin *self = FU_PLUGIN (object);
2883 FuPluginPrivate *priv = GET_PRIVATE (self);
Richard Hughescff38bc2016-12-12 12:03:37 +00002884 FuPluginInitFunc func = NULL;
2885
Richard Hughesfaf2afe2021-01-13 14:00:20 +00002886 g_rw_lock_clear (&priv->cache_mutex);
Richard Hughesaae22e42020-06-22 21:32:59 +01002887
Richard Hughescff38bc2016-12-12 12:03:37 +00002888 /* optional */
2889 if (priv->module != NULL) {
2890 g_module_symbol (priv->module, "fu_plugin_destroy", (gpointer *) &func);
2891 if (func != NULL) {
Richard Hughes7bcb8d42020-10-08 15:47:47 +01002892 g_debug ("destroy(%s)", fu_plugin_get_name (self));
Richard Hughes12724852018-09-04 13:53:44 +01002893 func (self);
Richard Hughescff38bc2016-12-12 12:03:37 +00002894 }
2895 }
2896
Richard Hughes11c59412020-06-22 15:29:48 +01002897 for (guint i = 0; i < FU_PLUGIN_RULE_LAST; i++) {
2898 if (priv->rules[i] != NULL)
2899 g_ptr_array_unref (priv->rules[i]);
2900 }
Richard Hughes68ab1e42021-01-13 14:01:17 +00002901 if (priv->devices != NULL)
2902 g_ptr_array_unref (priv->devices);
Richard Hughesb8f8db22017-04-25 15:56:00 +01002903 if (priv->hwids != NULL)
Richard Hughesd7704d42017-08-08 20:29:09 +01002904 g_object_unref (priv->hwids);
Richard Hughes9c028f02017-10-28 21:14:28 +01002905 if (priv->quirks != NULL)
2906 g_object_unref (priv->quirks);
Richard Hughes9d6e0e72018-08-24 20:20:17 +01002907 if (priv->udev_subsystems != NULL)
2908 g_ptr_array_unref (priv->udev_subsystems);
Richard Hughes49e5e052017-09-03 12:15:41 +01002909 if (priv->smbios != NULL)
2910 g_object_unref (priv->smbios);
Richard Hughes275d3b42018-04-20 16:40:37 +01002911 if (priv->runtime_versions != NULL)
2912 g_hash_table_unref (priv->runtime_versions);
Richard Hughes34e0dab2018-04-20 16:43:00 +01002913 if (priv->compile_versions != NULL)
2914 g_hash_table_unref (priv->compile_versions);
Richard Hughes1d900f72020-06-22 15:17:39 +01002915 if (priv->report_metadata != NULL)
2916 g_hash_table_unref (priv->report_metadata);
Richard Hughesfaf2afe2021-01-13 14:00:20 +00002917 if (priv->cache != NULL)
2918 g_hash_table_unref (priv->cache);
Richard Hughes84999302019-05-02 10:18:32 +01002919 g_free (priv->build_hash);
Richard Hughescff38bc2016-12-12 12:03:37 +00002920 g_free (priv->data);
Mario Limonciello3f9a1c12018-06-06 14:06:40 -05002921 /* Must happen as the last step to avoid prematurely
2922 * freeing memory held by the plugin */
Richard Hughes862ec5c2020-05-22 14:38:02 +01002923#ifdef RUNNING_ON_VALGRIND
2924 if (priv->module != NULL && RUNNING_ON_VALGRIND == 0)
2925#else
Mario Limonciello3f9a1c12018-06-06 14:06:40 -05002926 if (priv->module != NULL)
Mario Limonciello3f9a1c12018-06-06 14:06:40 -05002927#endif
Richard Hughes862ec5c2020-05-22 14:38:02 +01002928 g_module_close (priv->module);
Richard Hughescff38bc2016-12-12 12:03:37 +00002929
2930 G_OBJECT_CLASS (fu_plugin_parent_class)->finalize (object);
2931}
2932
Mario Limonciello1a680f32019-11-25 19:44:53 -06002933/**
2934 * fu_plugin_new:
2935 *
2936 * Creates a new #FuPlugin
2937 *
2938 * Since: 0.8.0
2939 **/
Richard Hughescff38bc2016-12-12 12:03:37 +00002940FuPlugin *
2941fu_plugin_new (void)
2942{
Richard Hughes12724852018-09-04 13:53:44 +01002943 return FU_PLUGIN (g_object_new (FU_TYPE_PLUGIN, NULL));
Richard Hughescff38bc2016-12-12 12:03:37 +00002944}