Commit cff38bcb authored by Richard Hughes's avatar Richard Hughes
Browse files

Convert the providers to plugins to simplify code and for future features

This is a large commit that removes all the providers and turns them into
plugins. I think having both providers _and_ plugins was super confusing.

Plugins are loaded at runtime so you could in theory develop a new plugin
without putting it in the fwupd source tree, although there are no installed
headers or PC files as I'm not sure it's a good idea at this stage.

This commit moves all the per-provider docs, tests, notes, debug dumps and test
data to plugin-specific directories -- these also allows the plugin author to
"own" more of the source tree so we don't enforce fu- prefixes and the style
guide everywhere.

This allows us to run the same action on all the plugins in the future, so we
could have a prepare(FuPlugin, FuDevice) and cleanup(FuPlugin, FuDevice) run
on *all* plugins, so doing an update using one plugin would allow us to work
around hardware quirks in other plugins.

If I've broken your out-of-tree provider it's trivial to port to the new API
with sed and a fixed up build file. If you need help please let me know.
parent b4a24f60
......@@ -5,75 +5,11 @@ This project aims to make updating firmware on Linux automatic, safe and reliabl
Additional information is available at the website: http://www.fwupd.org
DFU Support
-----------
DFU support is supported directly by this project with the embedded libdfu
library.
ColorHug Support
----------------
For colorhug support you need to install colord 1.2.12 or later.
* source: https://github.com/hughsie/colord
* rpms: http://people.freedesktop.org/~hughsient/fedora/
* debs (Debian): https://tracker.debian.org/pkg/fwupd
* debs (Ubuntu): https://launchpad.net/ubuntu/+source/fwupd
If you don't want or need this functionality you can use the
`--disable-colorhug` option.
UEFI Support
------------
For UEFI capsule support, you need to install fwupdate 0.5 or later.
* source: https://github.com/rhinstaller/fwupdate
* rpms: https://pjones.fedorapeople.org/fwupdate/
* debs (Debian): https://tracker.debian.org/pkg/fwupdate
* debs (Ubuntu): https://launchpad.net/ubuntu/+source/fwupdate
If you don't want or need this functionality you can use the
`--disable-uefi` option.
UEFI Unlock Support
Adding a new plugin
-------------------
On some Dell systems it's possible to turn on and off UEFI capsule
support from within the BIOS. This functionality can also be adjusted
from within the OS by fwupd. This requires using fwupdate 5 or later
and compiling it with libsmbios support.
When fwupd and fwupdate have been compiled with this support you will
be able to enable UEFI support on the device by using the `unlock` command.
Dell Support
----------------
This allows installing Dell capsules that are not part of the ESRT table.
Information on special features enabled by this provider are available here:
https://github.com/hughsie/fwupd/blob/master/docs/dell-provider.md
For Dell support you will need libsmbios_c version 2.3.0 or later and
efivar.
* source: http://linux.dell.com/cgi-bin/cgit.cgi/libsmbios.git/
* rpms: https://apps.fedoraproject.org/packages/libsmbios
* debs (Debian): http://tracker.debian.org/pkg/libsmbios
* debs (Ubuntu): http://launchpad.net/ubuntu/+source/libsmbios
If you don't want or need this functionality you can use the
`--disable-dell` option.
Raspberry Pi support
--------------------
A provider is available that can flash the boot firmware on the Raspberry Pi.
Adding a new provider
---------------------
An extensible architecture allows for providing new Provider types (for reading
and writing different firmware) as well as for plugins that can extend existing
firmware providers to quirk their behavior.
An extensible architecture allows for providing new plugin types (for reading
and writing different firmware) as well as ways quirk their behavior.
If you have a firmware specification and would like to see support
in this project, please file an issue and share the spec. Patches are also
......
......@@ -9,7 +9,7 @@ m4_define([fwupd_version],
AC_INIT([fwupd],[fwupd_version],[https://github.com/hughsie/fwupd])
AC_CONFIG_SRCDIR(src)
AM_INIT_AUTOMAKE([1.9 no-dist-gzip dist-xz tar-ustar foreign])
AM_INIT_AUTOMAKE([1.9 no-dist-gzip dist-xz tar-ustar foreign subdir-objects])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_LIBTOOL
......@@ -317,7 +317,6 @@ libfwupd/Makefile
data/Makefile
data/pki/Makefile
data/tests/Makefile
data/tests/rpiupdate/Makefile
data/tests/colorhug/Makefile
docs/Makefile
docs/libdfu/Makefile
......@@ -328,8 +327,17 @@ policy/Makefile
po/Makefile.in
src/Makefile
plugins/Makefile
plugins/test/Makefile
plugins/colorhug/Makefile
plugins/dell/Makefile
plugins/dfu/Makefile
plugins/ebitdo/Makefile
plugins/raspberrypi/Makefile
plugins/raspberrypi/rpiupdate/Makefile
plugins/steelseries/Makefile
plugins/test/Makefile
plugins/udev/Makefile
plugins/uefi/Makefile
plugins/usb/Makefile
])
AC_OUTPUT
......
......@@ -153,9 +153,17 @@ make check VERBOSE=1
%dir %{_localstatedir}/cache/app-info/icons
%dir %{_localstatedir}/cache/app-info/xmls
/usr/lib/udev/rules.d/*.rules
%dir %{_libdir}/fwupd-plugins-1
%{_libdir}/fwupd-plugins-1/libfu_plugin_steelseries.so
%{_libdir}/fwupd-plugins-1/libfu_plugin_test.so
%dir %{_libdir}/fwupd-plugins-2
%{_libdir}/fwupd-plugins-2/libfu_plugin_colorhug.so
%{_libdir}/fwupd-plugins-2/libfu_plugin_dell.so
%{_libdir}/fwupd-plugins-2/libfu_plugin_dfu.so
%{_libdir}/fwupd-plugins-2/libfu_plugin_ebitdo.so
%{_libdir}/fwupd-plugins-2/libfu_plugin_raspberrypi.so
%{_libdir}/fwupd-plugins-2/libfu_plugin_steelseries.so
%{_libdir}/fwupd-plugins-2/libfu_plugin_test.so
%{_libdir}/fwupd-plugins-2/libfu_plugin_udev.so
%{_libdir}/fwupd-plugins-2/libfu_plugin_uefi.so
%{_libdir}/fwupd-plugins-2/libfu_plugin_usb.so
%ghost %{_localstatedir}/lib/fwupd/gnupg
%files devel
......
<?xml version="1.0" encoding="UTF-8"?>
<components version="0.9" origin="fwupd">
<!-- SteelSeries legacy hardware -->
<component type="firmware">
<name>SteelSeries Firmware</name>
<summary>Firmware for Rival SteelSeries mice</summary>
<id>com.steelseries.rival-legacy.firmware</id>
<provides>
<!-- 1038:1702 = Rival 100 -->
<firmware type="flashed">be9dac3a-180b-5aee-9e39-da122d4300ff</firmware>
</provides>
<metadata>
<value key="fwupd::plugin">steelseries</value>
</metadata>
</component>
<!-- some UEFI hardware needs to be enabled before the ESRT is available -->
<component type="firmware">
<id>UEFI-dummy-dev0</id>
......
SUBDIRS = \
colorhug \
rpiupdate
SUBDIRS = colorhug
test_files = \
rpiboot/start.elf \
pki/GPG-KEY-Linux-Vendor-Firmware-Service
test_files = pki/GPG-KEY-Linux-Vendor-Firmware-Service
EXTRA_DIST = $(test_files)
......
......@@ -4,7 +4,6 @@ SUBDIRS = \
man
EXTRA_DIST = \
dell-provider.md \
version.xml.in \
dfu-metadata-store.md
......
SUBDIRS = test steelseries
SUBDIRS = dfu ebitdo raspberrypi steelseries test udev usb
if HAVE_DELL
SUBDIRS += dell
endif
if HAVE_COLORHUG
SUBDIRS += colorhug
endif
if HAVE_UEFI
SUBDIRS += uefi
endif
-include $(top_srcdir)/git.mk
AM_CPPFLAGS = \
$(APPSTREAM_GLIB_CFLAGS) \
$(GUSB_CFLAGS) \
$(GLIB_CFLAGS) \
$(COLORHUG_CFLAGS) \
-I$(top_srcdir) \
-I$(top_srcdir)/libfwupd \
-I$(top_srcdir)/src
plugindir = $(libdir)/fwupd-plugins-2
plugin_LTLIBRARIES = libfu_plugin_colorhug.la
libfu_plugin_colorhug_la_SOURCES = \
fu-plugin-colorhug.c
libfu_plugin_colorhug_la_LIBADD = $(GUSB_LIBS) $(COLORHUG_LIBS)
libfu_plugin_colorhug_la_LDFLAGS = -module -avoid-version
libfu_plugin_colorhug_la_CFLAGS = $(WARN_CFLAGS) \
-DG_LOG_DOMAIN=\"FuPluginColorHug\"
EXTRA_DIST = README.md
-include $(top_srcdir)/git.mk
ColorHug Support
================
Introduction
------------
The ColorHug is an affordable open source display colorimeter built by
Hughski Limited. The USB device allows you to calibrate your screen for
accurate color matching.
ColorHug versions 1 and 2 support a custom HID-based flashing protocol, but
version 3 (ColorHug+) has now switched to DFU.
Build Requirements
------------------
For colorhug support you need to install colord 1.2.12 or later.
* source: https://github.com/hughsie/colord
* rpms: http://people.freedesktop.org/~hughsient/fedora/
* debs (Debian): https://tracker.debian.org/pkg/fwupd
* debs (Ubuntu): https://launchpad.net/ubuntu/+source/fwupd
If you don't want or need this functionality you can use the
`--disable-colorhug` option.
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
*
* Copyright (C) 2015 Richard Hughes <richard@hughsie.com>
* Copyright (C) 2015-2016 Richard Hughes <richard@hughsie.com>
*
* Licensed under the GNU General Public License Version 2
*
......@@ -21,49 +21,32 @@
#include "config.h"
#include <fwupd.h>
#include <colord.h>
#include <colorhug.h>
#include <gio/gio.h>
#include <gio/gunixinputstream.h>
#include <glib-object.h>
#include <gusb.h>
#include "fu-device.h"
#include "fu-provider-chug.h"
#include "fu-plugin.h"
#include "fu-plugin-vfuncs.h"
static void fu_provider_chug_finalize (GObject *object);
#define FU_PLUGIN_CHUG_POLL_REOPEN 5 /* seconds */
#define FU_PLUGIN_CHUG_FIRMWARE_MAX (64 * 1024) /* bytes */
#define FU_PROVIDER_CHUG_POLL_REOPEN 5 /* seconds */
#define FU_PROVIDER_CHUG_FIRMWARE_MAX (64 * 1024) /* bytes */
typedef struct {
GHashTable *devices; /* DeviceKey:FuProviderChugItem */
GUsbContext *usb_ctx;
struct FuPluginData {
GHashTable *devices; /* DeviceKey:FuPluginItem */
ChDeviceQueue *device_queue;
} FuProviderChugPrivate;
};
typedef struct {
FuDevice *device;
FuProviderChug *provider_chug;
FuPlugin *plugin;
GUsbDevice *usb_device;
gboolean got_version;
gboolean is_bootloader;
guint timeout_open_id;
GBytes *fw_bin;
} FuProviderChugItem;
G_DEFINE_TYPE_WITH_PRIVATE (FuProviderChug, fu_provider_chug, FU_TYPE_PROVIDER)
#define GET_PRIVATE(o) (fu_provider_chug_get_instance_private (o))
static const gchar *
fu_provider_chug_get_name (FuProvider *provider)
{
return "ColorHug";
}
} FuPluginItem;
static gchar *
fu_provider_chug_get_device_key (GUsbDevice *device)
fu_plugin_get_device_key (GUsbDevice *device)
{
return g_strdup_printf ("%s_%s",
g_usb_device_get_platform_id (device),
......@@ -71,10 +54,10 @@ fu_provider_chug_get_device_key (GUsbDevice *device)
}
static void
fu_provider_chug_device_free (FuProviderChugItem *item)
fu_plugin_device_free (FuPluginItem *item)
{
g_object_unref (item->device);
g_object_unref (item->provider_chug);
g_object_unref (item->plugin);
g_object_unref (item->usb_device);
if (item->fw_bin != NULL)
g_bytes_unref (item->fw_bin);
......@@ -83,14 +66,14 @@ fu_provider_chug_device_free (FuProviderChugItem *item)
}
static gboolean
fu_provider_chug_wait_for_connect (FuProviderChug *provider_chug,
FuProviderChugItem *item,
fu_plugin_wait_for_connect (FuPlugin *plugin,
FuPluginItem *item,
GError **error)
{
FuProviderChugPrivate *priv = GET_PRIVATE (item->provider_chug);
GUsbContext *usb_ctx = fu_plugin_get_usb_context (plugin);
g_autoptr(GUsbDevice) device = NULL;
device = g_usb_context_wait_for_replug (priv->usb_ctx,
device = g_usb_context_wait_for_replug (usb_ctx,
item->usb_device,
CH_DEVICE_USB_TIMEOUT,
error);
......@@ -104,7 +87,7 @@ fu_provider_chug_wait_for_connect (FuProviderChug *provider_chug,
static gboolean
fu_provider_chug_open (FuProviderChugItem *item, GError **error)
fu_plugin_open (FuPluginItem *item, GError **error)
{
g_autoptr(GError) error_local = NULL;
if (!ch_device_open (item->usb_device, &error_local)) {
......@@ -120,9 +103,9 @@ fu_provider_chug_open (FuProviderChugItem *item, GError **error)
}
static void
fu_provider_chug_get_firmware_version (FuProviderChugItem *item)
fu_plugin_get_firmware_version (FuPluginItem *item)
{
FuProviderChugPrivate *priv = GET_PRIVATE (item->provider_chug);
FuPluginData *data = fu_plugin_get_data (item->plugin);
guint16 major;
guint16 micro;
guint16 minor;
......@@ -156,9 +139,9 @@ fu_provider_chug_get_firmware_version (FuProviderChugItem *item)
g_debug ("Failed to claim interface, polling: %s", error->message);
return;
}
ch_device_queue_get_firmware_ver (priv->device_queue, item->usb_device,
ch_device_queue_get_firmware_ver (data->device_queue, item->usb_device,
&major, &minor, &micro);
if (!ch_device_queue_process (priv->device_queue,
if (!ch_device_queue_process (data->device_queue,
CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE,
NULL, &error)) {
g_warning ("Failed to get serial: %s", error->message);
......@@ -178,23 +161,22 @@ out:
g_debug ("Failed to close: %s", error->message);
}
static gboolean
fu_provider_chug_verify (FuProvider *provider,
FuDevice *device,
FuProviderVerifyFlags flags,
GError **error)
gboolean
fu_plugin_verify (FuPlugin *plugin,
FuDevice *device,
FuPluginVerifyFlags flags,
GError **error)
{
FuProviderChug *provider_chug = FU_PROVIDER_CHUG (provider);
FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug);
FuProviderChugItem *item;
FuPluginData *data = fu_plugin_get_data (plugin);
FuPluginItem *item;
GChecksumType checksum_type;
gsize len;
g_autoptr(GError) error_local = NULL;
g_autofree gchar *hash = NULL;
g_autofree guint8 *data = NULL;
g_autofree guint8 *data2 = NULL;
/* find item */
item = g_hash_table_lookup (priv->devices, fu_device_get_id (device));
item = g_hash_table_lookup (data->devices, fu_device_get_id (device));
if (item == NULL) {
g_set_error (error,
FWUPD_ERROR,
......@@ -205,15 +187,15 @@ fu_provider_chug_verify (FuProvider *provider,
}
/* open */
if (!fu_provider_chug_open (item, error))
if (!fu_plugin_open (item, error))
return FALSE;
/* get the firmware from the device */
g_debug ("ColorHug: Verifying firmware");
ch_device_queue_read_firmware (priv->device_queue, item->usb_device,
&data, &len);
fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_VERIFY);
if (!ch_device_queue_process (priv->device_queue,
ch_device_queue_read_firmware (data->device_queue, item->usb_device,
&data2, &len);
fu_plugin_set_status (plugin, FWUPD_STATUS_DEVICE_VERIFY);
if (!ch_device_queue_process (data->device_queue,
CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE,
NULL, &error_local)) {
g_set_error (error,
......@@ -226,8 +208,8 @@ fu_provider_chug_verify (FuProvider *provider,
}
/* get the checksum */
checksum_type = fu_provider_get_checksum_type (flags);
hash = g_compute_checksum_for_data (checksum_type, (guchar *) data, len);
checksum_type = fu_plugin_get_checksum_type (flags);
hash = g_compute_checksum_for_data (checksum_type, (guchar *) data2, len);
fu_device_set_checksum (device, hash);
fu_device_set_checksum_kind (device, checksum_type);
......@@ -238,20 +220,19 @@ fu_provider_chug_verify (FuProvider *provider,
return TRUE;
}
static gboolean
fu_provider_chug_update (FuProvider *provider,
gboolean
fu_plugin_update_online (FuPlugin *plugin,
FuDevice *device,
GBytes *blob_fw,
FwupdInstallFlags flags,
GError **error)
{
FuProviderChug *provider_chug = FU_PROVIDER_CHUG (provider);
FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug);
FuProviderChugItem *item;
FuPluginData *data = fu_plugin_get_data (plugin);
FuPluginItem *item;
g_autoptr(GError) error_local = NULL;
/* find item */
item = g_hash_table_lookup (priv->devices,
item = g_hash_table_lookup (data->devices,
fu_device_get_id (device));
if (item == NULL) {
g_set_error (error,
......@@ -281,11 +262,11 @@ fu_provider_chug_update (FuProvider *provider,
/* switch to bootloader mode */
if (!item->is_bootloader) {
g_debug ("ColorHug: Switching to bootloader mode");
if (!fu_provider_chug_open (item, error))
if (!fu_plugin_open (item, error))
return FALSE;
ch_device_queue_reset (priv->device_queue, item->usb_device);
fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_RESTART);
if (!ch_device_queue_process (priv->device_queue,
ch_device_queue_reset (data->device_queue, item->usb_device);
fu_plugin_set_status (plugin, FWUPD_STATUS_DEVICE_RESTART);
if (!ch_device_queue_process (data->device_queue,
CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE,
NULL, &error_local)) {
g_set_error (error,
......@@ -302,21 +283,21 @@ fu_provider_chug_update (FuProvider *provider,
/* wait for reconnection */
g_debug ("ColorHug: Waiting for bootloader");
if (!fu_provider_chug_wait_for_connect (provider_chug, item, error))
if (!fu_plugin_wait_for_connect (plugin, item, error))
return FALSE;
}
/* open the device, which is now in bootloader mode */
if (!fu_provider_chug_open (item, error))
if (!fu_plugin_open (item, error))
return FALSE;
/* write firmware */
g_debug ("ColorHug: Writing firmware");
ch_device_queue_write_firmware (priv->device_queue, item->usb_device,
ch_device_queue_write_firmware (data->device_queue, item->usb_device,
g_bytes_get_data (item->fw_bin, NULL),
g_bytes_get_size (item->fw_bin));
fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_WRITE);
if (!ch_device_queue_process (priv->device_queue,
fu_plugin_set_status (plugin, FWUPD_STATUS_DEVICE_WRITE);
if (!ch_device_queue_process (data->device_queue,
CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE,
NULL, &error_local)) {
g_set_error (error,
......@@ -330,11 +311,11 @@ fu_provider_chug_update (FuProvider *provider,
/* verify firmware */
g_debug ("ColorHug: Veifying firmware");
ch_device_queue_verify_firmware (priv->device_queue, item->usb_device,
ch_device_queue_verify_firmware (data->device_queue, item->usb_device,
g_bytes_get_data (item->fw_bin, NULL),
g_bytes_get_size (item->fw_bin));
fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_VERIFY);
if (!ch_device_queue_process (priv->device_queue,
fu_plugin_set_status (plugin, FWUPD_STATUS_DEVICE_VERIFY);
if (!ch_device_queue_process (data->device_queue,
CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE,
NULL, &error_local)) {
g_set_error (error,
......@@ -348,9 +329,9 @@ fu_provider_chug_update (FuProvider *provider,
/* boot into the new firmware */
g_debug ("ColorHug: Booting new firmware");
ch_device_queue_boot_flash (priv->device_queue, item->usb_device);
fu_provider_set_status (provider, FWUPD_STATUS_DEVICE_RESTART);
if (!ch_device_queue_process (priv->device_queue,
ch_device_queue_boot_flash (data->device_queue, item->usb_device);
fu_plugin_set_status (plugin, FWUPD_STATUS_DEVICE_RESTART);
if (!ch_device_queue_process (data->device_queue,
CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE,
NULL, &error_local)) {
g_set_error (error,
......@@ -366,15 +347,15 @@ fu_provider_chug_update (FuProvider *provider,
g_usb_device_close (item->usb_device, NULL);
/* wait for firmware mode */
if (!fu_provider_chug_wait_for_connect (provider_chug, item, error))
if (!fu_plugin_wait_for_connect (plugin, item, error))
return FALSE;
if (!fu_provider_chug_open (item, error))
if (!fu_plugin_open (item, error))
return FALSE;
/* set flash success */
g_debug ("ColorHug: Setting flash success");
ch_device_queue_set_flash_success (priv->device_queue, item->usb_device, 1);
if (!ch_device_queue_process (priv->device_queue,
ch_device_queue_set_flash_success (data->device_queue, item->usb_device, 1);
if (!ch_device_queue_process (data->device_queue,
CH_DEVICE_QUEUE_PROCESS_FLAGS_NONE,
NULL, &error_local)) {
g_set_error (error,
......@@ -400,7 +381,7 @@ fu_provider_chug_update (FuProvider *provider,
/* get the new firmware version */
g_debug ("ColorHug: Getting new firmware version");
item->got_version = FALSE;
fu_provider_chug_get_firmware_version (item);
fu_plugin_get_firmware_version (item);
if (item->got_version)
g_debug ("ColorHug: DONE!");
......@@ -409,13 +390,13 @@ fu_provider_chug_update (FuProvider *provider,
}
static gboolean
fu_provider_chug_open_cb (gpointer user_data)
fu_plugin_open_cb (gpointer user_data)
{
FuProviderChugItem *item = (FuProviderChugItem *) user_data;
FuPluginItem *item = (FuPluginItem *) user_data;
g_debug ("attempt to open %s",
g_usb_device_get_platform_id (item->usb_device));
fu_provider_chug_get_firmware_version (item);
fu_plugin_get_firmware_version (item);
/* success! */
if (item->got_version) {
......@@ -428,12 +409,12 @@ fu_provider_chug_open_cb (gpointer user_data)
}
static void
fu_provider_chug_device_added_cb (GUsbContext *ctx,
fu_plugin_device_added_cb (GUsbContext *ctx,
GUsbDevice *device,
FuProviderChug *provider_chug)
FuPlugin *plugin)
{
FuProviderChugPrivate *priv = GET_PRIVATE (provider_chug);
FuProviderChugItem *item;
FuPluginData *data = fu_plugin_get_data (plugin);
FuPluginItem *item;
ChDeviceMode mode;
g_autofree gchar *device_key = NULL;
......@@ -448,11 +429,11 @@ fu_provider_chug_device_added_cb (GUsbContext *ctx,
return;
/* is already in database */
device_key = fu_provider_chug_get_device_key (device);
item = g_hash_table_lookup (priv->devices, device_key);
device_key = fu_plugin_get_device_key (device);
item = g_hash_table_lookup (data->devices, device_key);
if (item == NULL) {
item = g_new0 (FuProviderChugItem, 1);
item->provider_chug = g_object_ref (provider_chug);
item = g_new0 (FuPluginItem, 1);
item->plugin = g_object_ref (plugin);
item->usb_device = g_object_ref (device);
item->device = fu_device_new ();
fu_device_set_id (item->device, device_key);
......@@ -464,14 +445,14 @@ fu_provider_chug_device_added_cb (GUsbContext *ctx,
/* try to get the serial number -- if opening failed then
* poll until the device is not busy */
fu_provider_chug_get_firmware_version (item);
fu_plugin_get_firmware_version (item);
if (!item->got_version && item->timeout_open_id == 0) {
item->timeout_open_id = g_timeout_add_seconds (FU_PROVIDER_CHUG_POLL_REOPEN,
fu_provider_chug_open_cb, item);
item->timeout_open_id = g_timeout_add_seconds (FU_PLUGIN_CHUG_POLL_REOPEN,
fu_plugin_open_cb, item);
}