diff --git a/libfwupdplugin/fu-device.c b/libfwupdplugin/fu-device.c index e4d6fb913..13c0b4d1c 100644 --- a/libfwupdplugin/fu-device.c +++ b/libfwupdplugin/fu-device.c @@ -81,6 +81,7 @@ typedef struct { gchar *custom_flags; gulong notify_flags_handler_id; GHashTable *instance_hash; + GPtrArray *backend_tags; /* of utf-8 */ } FuDevicePrivate; typedef struct { @@ -103,6 +104,7 @@ enum { PROP_CONTEXT, PROP_PROXY, PROP_PARENT, + PROP_BACKEND_TAGS, PROP_LAST }; @@ -137,6 +139,9 @@ fu_device_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec case PROP_PARENT: g_value_set_object(value, fu_device_get_parent(self)); break; + case PROP_BACKEND_TAGS: + g_value_set_boxed(value, priv->backend_tags); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; @@ -1244,6 +1249,74 @@ fu_device_get_children(FuDevice *self) return fwupd_device_get_children(FWUPD_DEVICE(self)); } +/** + * fu_device_get_backend_tags: + * @self: a #FuDevice + * @backend_tag: a tag, for example `bootloader` or `runtime-reload` + * + * Gets any backend tags. + * + * Returns: (transfer none) (element-type utf-8): string tags + * + * Since: 1.8.5 + **/ +GPtrArray * +fu_device_get_backend_tags(FuDevice *self) +{ + FuDevicePrivate *priv = GET_PRIVATE(self); + g_return_val_if_fail(FU_IS_DEVICE(self), NULL); + return priv->backend_tags; +} + +/** + * fu_device_add_backend_tag: + * @self: a #FuDevice + * @backend_tag: a tag, for example `bootloader` or `runtime-reload` + * + * Adds a backend tag, which allows the backend to identify the specific device for a specific + * phase. For instance, there might be a pre-update runtime, a bootloader and a post-update runtime + * and allowing tags to be saved to the backend object allows us to identify each version of + * the same physical device. + * + * Since: 1.8.5 + **/ +void +fu_device_add_backend_tag(FuDevice *self, const gchar *backend_tag) +{ + FuDevicePrivate *priv = GET_PRIVATE(self); + g_return_if_fail(FU_IS_DEVICE(self)); + g_return_if_fail(backend_tag != NULL); + if (fu_device_has_backend_tag(self, backend_tag)) + return; + g_ptr_array_add(priv->backend_tags, g_strdup(backend_tag)); + g_object_notify(G_OBJECT(self), "backend-tags"); +} + +/** + * fu_device_has_backend_tag: + * @self: a #FuDevice + * @backend_tag: a tag, for example `bootloader` or `runtime-reload` + * + * Finds if the backend tag already exists. + * + * Returns: %TRUE if the backend tag exists + * + * Since: 1.8.5 + **/ +gboolean +fu_device_has_backend_tag(FuDevice *self, const gchar *backend_tag) +{ + FuDevicePrivate *priv = GET_PRIVATE(self); + g_return_val_if_fail(FU_IS_DEVICE(self), FALSE); + g_return_val_if_fail(backend_tag != NULL, FALSE); + for (guint i = 0; i < priv->backend_tags->len; i++) { + const gchar *backend_tag_tmp = g_ptr_array_index(priv->backend_tags, i); + if (g_strcmp0(backend_tag_tmp, backend_tag) == 0) + return TRUE; + } + return FALSE; +} + /** * fu_device_add_child: * @self: a #FuDevice @@ -5584,6 +5657,20 @@ fu_device_class_init(FuDeviceClass *klass) FU_TYPE_DEVICE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_NAME); g_object_class_install_property(object_class, PROP_PARENT, pspec); + + /** + * FuDevice:backend-tags: + * + * The device tags used for backend identification. + * + * Since: 1.5.8 + */ + pspec = g_param_spec_boxed("backend-tags", + NULL, + NULL, + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | G_PARAM_STATIC_NAME); + g_object_class_install_property(object_class, PROP_BACKEND_TAGS, pspec); } static void @@ -5595,6 +5682,7 @@ fu_device_init(FuDevice *self) priv->possible_plugins = g_ptr_array_new_with_free_func(g_free); priv->retry_recs = g_ptr_array_new_with_free_func(g_free); priv->instance_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + priv->backend_tags = g_ptr_array_new_with_free_func(g_free); priv->acquiesce_delay = 50; /* ms */ g_rw_lock_init(&priv->parent_guids_mutex); g_rw_lock_init(&priv->metadata_mutex); @@ -5632,6 +5720,7 @@ fu_device_finalize(GObject *object) g_ptr_array_unref(priv->parent_guids); g_ptr_array_unref(priv->possible_plugins); g_ptr_array_unref(priv->retry_recs); + g_ptr_array_unref(priv->backend_tags); g_free(priv->alternate_id); g_free(priv->equivalent_id); g_free(priv->physical_id); diff --git a/libfwupdplugin/fu-device.h b/libfwupdplugin/fu-device.h index 753af3869..b0cae55e5 100644 --- a/libfwupdplugin/fu-device.h +++ b/libfwupdplugin/fu-device.h @@ -540,6 +540,12 @@ fu_device_set_version_lowest(FuDevice *self, const gchar *version); void fu_device_set_version_bootloader(FuDevice *self, const gchar *version); void +fu_device_add_backend_tag(FuDevice *self, const gchar *backend_tag); +gboolean +fu_device_has_backend_tag(FuDevice *self, const gchar *backend_tag); +GPtrArray * +fu_device_get_backend_tags(FuDevice *self); +void fu_device_inhibit(FuDevice *self, const gchar *inhibit_id, const gchar *reason); void fu_device_uninhibit(FuDevice *self, const gchar *inhibit_id); diff --git a/libfwupdplugin/fu-plugin.c b/libfwupdplugin/fu-plugin.c index 61cefdd25..9744af9d6 100644 --- a/libfwupdplugin/fu-plugin.c +++ b/libfwupdplugin/fu-plugin.c @@ -1226,6 +1226,7 @@ fu_plugin_runner_prepare(FuPlugin *self, GError **error) { FuPluginVfuncs *vfuncs = fu_plugin_get_vfuncs(self); + fu_device_add_backend_tag(device, "prepare"); return fu_plugin_runner_flagged_device_generic(self, device, progress, @@ -1257,6 +1258,7 @@ fu_plugin_runner_cleanup(FuPlugin *self, GError **error) { FuPluginVfuncs *vfuncs = fu_plugin_get_vfuncs(self); + fu_device_add_backend_tag(device, "cleanup"); return fu_plugin_runner_flagged_device_generic(self, device, progress, @@ -1283,6 +1285,7 @@ gboolean fu_plugin_runner_attach(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error) { FuPluginVfuncs *vfuncs = fu_plugin_get_vfuncs(self); + fu_device_add_backend_tag(device, "attach"); return fu_plugin_runner_device_generic_progress( self, device, @@ -1309,6 +1312,7 @@ gboolean fu_plugin_runner_detach(FuPlugin *self, FuDevice *device, FuProgress *progress, GError **error) { FuPluginVfuncs *vfuncs = fu_plugin_get_vfuncs(self); + fu_device_add_backend_tag(device, "detach"); return fu_plugin_runner_device_generic_progress( self, device, @@ -1344,6 +1348,7 @@ fu_plugin_runner_reload(FuPlugin *self, FuDevice *device, GError **error) locker = fu_device_locker_new(proxy, error); if (locker == NULL) return FALSE; + fu_device_add_backend_tag(device, "reload"); return fu_device_reload(device, error); } @@ -1917,6 +1922,7 @@ fu_plugin_runner_activate(FuPlugin *self, FuDevice *device, FuProgress *progress } /* run vfunc */ + fu_device_add_backend_tag(device, "activate"); if (!fu_plugin_runner_device_generic_progress( self, device, @@ -1966,6 +1972,7 @@ fu_plugin_runner_unlock(FuPlugin *self, FuDevice *device, GError **error) } /* run vfunc */ + fu_device_add_backend_tag(device, "unlock"); if (!fu_plugin_runner_device_generic(self, device, "fu_plugin_unlock", @@ -2015,6 +2022,7 @@ fu_plugin_runner_write_firmware(FuPlugin *self, g_debug("plugin not enabled, skipping"); return TRUE; } + fu_device_add_backend_tag(device, "write-firmware"); /* optional */ if (vfuncs->write_firmware == NULL) { diff --git a/libfwupdplugin/fu-self-test.c b/libfwupdplugin/fu-self-test.c index 3d052e034..2dbc9c94f 100644 --- a/libfwupdplugin/fu-self-test.c +++ b/libfwupdplugin/fu-self-test.c @@ -1103,6 +1103,13 @@ fu_device_func(void) fu_device_add_possible_plugin(device, "test"); possible_plugins = fu_device_get_possible_plugins(device); g_assert_cmpint(possible_plugins->len, ==, 1); + + g_assert_cmpint(fu_device_get_backend_tags(device)->len, ==, 0); + fu_device_add_backend_tag(device, "foo"); + fu_device_add_backend_tag(device, "bar"); + g_assert_cmpint(fu_device_get_backend_tags(device)->len, ==, 2); + g_assert_true(fu_device_has_backend_tag(device, "foo")); + g_assert_false(fu_device_has_backend_tag(device, "bazbazbazbazbaz")); } static void diff --git a/libfwupdplugin/fwupdplugin.map b/libfwupdplugin/fwupdplugin.map index 6875d4c81..79ae1e9d6 100644 --- a/libfwupdplugin/fwupdplugin.map +++ b/libfwupdplugin/fwupdplugin.map @@ -1102,6 +1102,9 @@ LIBFWUPDPLUGIN_1.8.5 { fu_backend_save; fu_context_add_flag; fu_context_has_flag; + fu_device_add_backend_tag; + fu_device_get_backend_tags; + fu_device_has_backend_tag; fu_device_set_quirk_kv; fu_intel_thunderbolt_firmware_get_type; fu_intel_thunderbolt_firmware_new;