diff --git a/plugins/dell/dell.quirk b/plugins/dell/dell.quirk index 7ec9f1f92..a76f4da2e 100644 --- a/plugins/dell/dell.quirk +++ b/plugins/dell/dell.quirk @@ -1,3 +1,7 @@ +# Realtek NIC in Dell docks +[DeviceInstanceId=USB\VID_0BDA&PID_8153] +Plugin = dell + [SmbiosManufacturer=Dell Inc.] UefiVersionFormat = quad diff --git a/plugins/dell/fu-plugin-dell.c b/plugins/dell/fu-plugin-dell.c index 3b5c86cc1..4903777a1 100644 --- a/plugins/dell/fu-plugin-dell.c +++ b/plugins/dell/fu-plugin-dell.c @@ -254,20 +254,6 @@ fu_plugin_dell_get_version_format (FuPlugin *plugin) return AS_VERSION_PARSE_FLAG_USE_TRIPLET; } -static gchar * -fu_plugin_get_dock_key (FuPlugin *plugin, - GUsbDevice *device, const gchar *guid) -{ - FuPluginData *data = fu_plugin_get_data (plugin); - const gchar* platform_id; - - if (data->smi_obj->fake_smbios) - platform_id = "fake"; - else - platform_id = g_usb_device_get_platform_id (device); - return g_strdup_printf ("%s_%s", platform_id, guid); -} - static gboolean fu_plugin_dell_capsule_supported (FuPlugin *plugin) { @@ -277,13 +263,12 @@ fu_plugin_dell_capsule_supported (FuPlugin *plugin) } static gboolean -fu_plugin_dock_node (FuPlugin *plugin, GUsbDevice *device, +fu_plugin_dock_node (FuPlugin *plugin, const gchar *platform, guint8 type, const gchar *component_guid, const gchar *component_desc, const gchar *version) { const gchar *dock_type; g_autofree gchar *dock_id = NULL; - g_autofree gchar *dock_key = NULL; g_autofree gchar *dock_name = NULL; g_autoptr(FuDevice) dev = NULL; @@ -293,13 +278,8 @@ fu_plugin_dock_node (FuPlugin *plugin, GUsbDevice *device, return FALSE; } - dock_key = fu_plugin_get_dock_key (plugin, device, component_guid); - if (fu_plugin_cache_lookup (plugin, dock_key) != NULL) { - g_debug ("%s is already registered.", dock_key); - return FALSE; - } - dev = fu_device_new (); + fu_device_set_platform_id (dev, platform); dock_id = g_strdup_printf ("DELL-%s" G_GUINT64_FORMAT, component_guid); if (component_desc != NULL) { dock_name = g_strdup_printf ("Dell %s %s", dock_type, @@ -332,15 +312,13 @@ fu_plugin_dock_node (FuPlugin *plugin, GUsbDevice *device, } fu_plugin_device_register (plugin, dev); - fu_plugin_cache_add (plugin, dock_key, dev); return TRUE; } - -void -fu_plugin_dell_device_added_cb (GUsbContext *ctx, - GUsbDevice *device, - FuPlugin *plugin) +gboolean +fu_plugin_usb_device_added (FuPlugin *plugin, + GUsbDevice *device, + GError **error) { FuPluginData *data = fu_plugin_get_data (plugin); AsVersionParseFlag parse_flags; @@ -349,6 +327,7 @@ fu_plugin_dell_device_added_cb (GUsbContext *ctx, const gchar *query_str; const gchar *component_guid = NULL; const gchar *component_name = NULL; + const gchar *platform; DOCK_UNION buf; DOCK_INFO *dock_info; gboolean old_ec = FALSE; @@ -359,25 +338,32 @@ fu_plugin_dell_device_added_cb (GUsbContext *ctx, if (!data->smi_obj->fake_smbios) { vid = g_usb_device_get_vid (device); pid = g_usb_device_get_pid (device); + platform = g_usb_device_get_platform_id (device); } else { vid = data->fake_vid; pid = data->fake_pid; + platform = "fake"; } /* we're going to match on the Realtek NIC in the dock */ - if (vid != DOCK_NIC_VID || pid != DOCK_NIC_PID) - return; + if (vid != DOCK_NIC_VID || pid != DOCK_NIC_PID) { + g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, + "wrong VID/PID %04x:%04x", vid, pid); + return FALSE; + } buf.buf = NULL; if (!fu_dell_query_dock (data->smi_obj, &buf)) { - g_debug ("No dock detected."); - return; + g_set_error_literal (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, + "no dock detected"); + return FALSE; } if (buf.record->dock_info_header.dir_version != 1) { - g_debug ("Dock info header version unknown: %d", - buf.record->dock_info_header.dir_version); - return; + g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, + "dock info header version unknown %d", + buf.record->dock_info_header.dir_version); + return FALSE; } dock_info = &buf.record->dock_info; @@ -403,15 +389,16 @@ fu_plugin_dell_device_added_cb (GUsbContext *ctx, query_str = g_strrstr (dock_info->components[i].description, "Query "); if (query_str == NULL) { - g_debug ("Invalid dock component request"); - return; + g_set_error_literal (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, + "invalid dock component request"); + return FALSE; } if (!fu_plugin_dell_match_dock_component (query_str + 6, &component_guid, &component_name)) { - g_debug ("Unable to match dock component %s", - query_str); - return; + g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, + "invalid dock component request %s", query_str); + return FALSE; } /* dock EC hasn't been updated for first time */ @@ -430,13 +417,14 @@ fu_plugin_dell_device_added_cb (GUsbContext *ctx, fw_str = as_utils_version_from_uint32 (dock_info->components[i].fw_version, parse_flags); if (!fu_plugin_dock_node (plugin, - device, - buf.record->dock_info_header.dock_type, - component_guid, - component_name, - fw_str)) { - g_debug ("Failed to create %s", component_name); - return; + platform, + buf.record->dock_info_header.dock_type, + component_guid, + component_name, + fw_str)) { + g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL, + "failed to create %s", component_name); + return FALSE; } } @@ -445,61 +433,21 @@ fu_plugin_dell_device_added_cb (GUsbContext *ctx, flash_ver_str = as_utils_version_from_uint32 (dock_info->flash_pkg_version, parse_flags); if (!fu_plugin_dock_node (plugin, - device, + platform, buf.record->dock_info_header.dock_type, DOCK_FLASH_GUID, NULL, flash_ver_str)) { - g_debug ("Failed to create top dock node"); - return; + g_set_error_literal (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL, + "failed to create top dock node"); + + return FALSE; } #if defined (HAVE_SYNAPTICS) fu_plugin_request_recoldplug (plugin); #endif -} - -void -fu_plugin_dell_device_removed_cb (GUsbContext *ctx, - GUsbDevice *device, - FuPlugin *plugin) -{ - FuPluginData *data = fu_plugin_get_data (plugin); - const gchar *guids[] = { WD15_EC_GUID, TB16_EC_GUID, TB16_PC2_GUID, - TB16_PC1_GUID, WD15_PC1_GUID, - LEGACY_CBL_GUID, UNIV_CBL_GUID, - TBT_CBL_GUID, DOCK_FLASH_GUID}; - guint16 pid; - guint16 vid; - FuDevice *dev = NULL; - - if (!data->smi_obj->fake_smbios) { - vid = g_usb_device_get_vid (device); - pid = g_usb_device_get_pid (device); - } else { - vid = data->fake_vid; - pid = data->fake_pid; - } - - /* we're going to match on the Realtek NIC in the dock */ - if (vid != DOCK_NIC_VID || pid != DOCK_NIC_PID) - return; - - /* remove any components already in database? */ - for (guint i = 0; i < G_N_ELEMENTS (guids); i++) { - g_autofree gchar *dock_key = NULL; - dock_key = fu_plugin_get_dock_key (plugin, device, - guids[i]); - dev = fu_plugin_cache_lookup (plugin, dock_key); - if (dev != NULL) { - fu_plugin_device_remove (plugin, - dev); - fu_plugin_cache_remove (plugin, dock_key); - } - } -#if defined (HAVE_SYNAPTICS) - fu_plugin_request_recoldplug (plugin); -#endif + return TRUE; } gboolean @@ -914,6 +862,7 @@ fu_plugin_init (FuPlugin *plugin) data->smi_obj->fake_smbios = FALSE; if (g_getenv ("FWUPD_DELL_FAKE_SMBIOS") != NULL) data->smi_obj->fake_smbios = TRUE; + fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_REQUIRES_QUIRK, FU_QUIRKS_PLUGIN); } void @@ -929,7 +878,6 @@ gboolean fu_plugin_startup (FuPlugin *plugin, GError **error) { FuPluginData *data = fu_plugin_get_data (plugin); - GUsbContext *usb_ctx = fu_plugin_get_usb_context (plugin); g_autofree gchar *sysfsfwdir = NULL; g_autofree gchar *esrtdir = NULL; @@ -969,15 +917,6 @@ fu_plugin_startup (FuPlugin *plugin, GError **error) g_debug ("UEFI capsule firmware updating not supported"); } - if (usb_ctx != NULL) { - g_signal_connect (usb_ctx, "device-added", - G_CALLBACK (fu_plugin_dell_device_added_cb), - plugin); - g_signal_connect (usb_ctx, "device-removed", - G_CALLBACK (fu_plugin_dell_device_removed_cb), - plugin); - } - return TRUE; } diff --git a/plugins/dell/fu-plugin-dell.h b/plugins/dell/fu-plugin-dell.h index 7608e741c..8bae502f6 100644 --- a/plugins/dell/fu-plugin-dell.h +++ b/plugins/dell/fu-plugin-dell.h @@ -27,16 +27,6 @@ fu_plugin_dell_inject_fake_data (FuPlugin *plugin, gboolean fu_plugin_dell_detect_tpm (FuPlugin *plugin, GError **error); -void -fu_plugin_dell_device_added_cb (GUsbContext *ctx, - GUsbDevice *device, - FuPlugin *plugin); - -void -fu_plugin_dell_device_removed_cb (GUsbContext *ctx, - GUsbDevice *device, - FuPlugin *plugin); - /* These are nodes that will indicate information about * the TPM status */ diff --git a/plugins/dell/fu-self-test.c b/plugins/dell/fu-self-test.c index f6db42896..2425e732e 100644 --- a/plugins/dell/fu-self-test.c +++ b/plugins/dell/fu-self-test.c @@ -14,6 +14,7 @@ #include "fu-device-private.h" #include "fu-plugin-private.h" #include "fu-plugin-dell.h" +#include "fu-plugin-vfuncs.h" static FuDevice * _find_device_by_id (GPtrArray *devices, const gchar *device_id) @@ -288,7 +289,9 @@ fu_plugin_dell_dock_func (void) fu_plugin_dell_inject_fake_data (plugin_dell, (guint32 *) &out, 0x1234, 0x4321, NULL, FALSE); - fu_plugin_dell_device_added_cb (NULL, NULL, plugin_dell); + ret = fu_plugin_usb_device_added (plugin_dell, NULL, &error); + g_assert_false (ret); + g_clear_error (&error); g_assert_cmpint (devices->len, ==, 0); /* inject a USB dongle matching correct VID/PID */ @@ -298,7 +301,9 @@ fu_plugin_dell_dock_func (void) (guint32 *) &out, DOCK_NIC_VID, DOCK_NIC_PID, NULL, FALSE); - fu_plugin_dell_device_added_cb (NULL, NULL, plugin_dell); + ret = fu_plugin_usb_device_added (plugin_dell, NULL, &error); + g_assert_false (ret); + g_clear_error (&error); g_assert_cmpint (devices->len, ==, 0); /* inject valid TB16 dock w/ invalid flash pkg version */ @@ -330,12 +335,11 @@ fu_plugin_dell_dock_func (void) (guint32 *) &out, DOCK_NIC_VID, DOCK_NIC_PID, buf.buf, FALSE); - fu_plugin_dell_device_added_cb (NULL, NULL, plugin_dell); + ret = fu_plugin_usb_device_added (plugin_dell, NULL, NULL); + g_assert (ret); g_assert_cmpint (devices->len, ==, 4); g_ptr_array_set_size (devices, 0); g_free (buf.record); - fu_plugin_dell_device_removed_cb (NULL, NULL, - plugin_dell); /* inject valid TB16 dock w/ older system EC */ buf.record = g_malloc0 (sizeof(DOCK_INFO_RECORD)); @@ -366,13 +370,11 @@ fu_plugin_dell_dock_func (void) (guint32 *) &out, DOCK_NIC_VID, DOCK_NIC_PID, buf.buf, FALSE); - fu_plugin_dell_device_added_cb (NULL, NULL, plugin_dell); + ret = fu_plugin_usb_device_added (plugin_dell, NULL, NULL); + g_assert (ret); g_assert_cmpint (devices->len, ==, 3); g_ptr_array_set_size (devices, 0); g_free (buf.record); - fu_plugin_dell_device_removed_cb (NULL, NULL, - plugin_dell); - /* inject valid WD15 dock w/ invalid flash pkg version */ buf.record = g_malloc0 (sizeof(DOCK_INFO_RECORD)); @@ -400,13 +402,12 @@ fu_plugin_dell_dock_func (void) (guint32 *) &out, DOCK_NIC_VID, DOCK_NIC_PID, buf.buf, FALSE); - fu_plugin_dell_device_added_cb (NULL, NULL, plugin_dell); + ret = fu_plugin_usb_device_added (plugin_dell, NULL, &error); + g_assert (ret); + g_assert_no_error (error); g_assert_cmpint (devices->len, ==, 3); g_ptr_array_set_size (devices, 0); g_free (buf.record); - fu_plugin_dell_device_removed_cb (NULL, NULL, - plugin_dell); - /* inject valid WD15 dock w/ older system EC */ buf.record = g_malloc0 (sizeof(DOCK_INFO_RECORD)); @@ -434,12 +435,12 @@ fu_plugin_dell_dock_func (void) (guint32 *) &out, DOCK_NIC_VID, DOCK_NIC_PID, buf.buf, FALSE); - fu_plugin_dell_device_added_cb (NULL, NULL, plugin_dell); + ret = fu_plugin_usb_device_added (plugin_dell, NULL, &error); + g_assert (ret); + g_assert_no_error (error); g_assert_cmpint (devices->len, ==, 2); g_ptr_array_set_size (devices, 0); g_free (buf.record); - fu_plugin_dell_device_removed_cb (NULL, NULL, - plugin_dell); /* inject an invalid future dock */ buf.record = g_malloc0 (sizeof(DOCK_INFO_RECORD)); @@ -461,7 +462,8 @@ fu_plugin_dell_dock_func (void) (guint32 *) &out, DOCK_NIC_VID, DOCK_NIC_PID, buf.buf, FALSE); - fu_plugin_dell_device_added_cb (NULL, NULL, plugin_dell); + ret = fu_plugin_usb_device_added (plugin_dell, NULL, &error); + g_assert_false (ret); g_assert_cmpint (devices->len, ==, 0); g_free (buf.record); }