diff --git a/plugins/dfu/dfu-device.c b/plugins/dfu/dfu-device.c index 2138f5a46..792f12f43 100644 --- a/plugins/dfu/dfu-device.c +++ b/plugins/dfu/dfu-device.c @@ -44,6 +44,7 @@ * * `legacy-protocol`: Use a legacy protocol version * * `detach-for-attach`: Requires a DFU_REQUEST_DETACH to attach * * `absent-sector-size`: In absence of sector size, assume byte + * * `manifest-poll`: Requires polling via GetStatus in dfuManifest state * * Default value: `none` * diff --git a/plugins/dfu/dfu-target.c b/plugins/dfu/dfu-target.c index ac5e9f683..e9d13d856 100644 --- a/plugins/dfu/dfu-target.c +++ b/plugins/dfu/dfu-target.c @@ -30,6 +30,8 @@ #include "fwupd-error.h" +#define DFU_TARGET_MANIFEST_MAX_POLLING_TRIES 200 + static void dfu_target_finalize (GObject *object); typedef struct { @@ -472,6 +474,46 @@ dfu_target_status_to_error_msg (DfuStatus status) return NULL; } +static gboolean +dfu_target_manifest_wait (DfuTarget *target, GError **error) +{ + DfuTargetPrivate *priv = GET_PRIVATE (target); + guint polling_count = 0; + + /* get the status */ + if (!dfu_device_refresh (priv->device, error)) + return FALSE; + + /* wait for DFU_STATE_DFU_MANIFEST to not be set */ + while (dfu_device_get_state (priv->device) == DFU_STATE_DFU_MANIFEST_SYNC || + dfu_device_get_state (priv->device) == DFU_STATE_DFU_MANIFEST) { + g_debug ("waiting for DFU_STATE_DFU_MANIFEST to clear"); + + if (polling_count++ > DFU_TARGET_MANIFEST_MAX_POLLING_TRIES) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + "reach to max polling tries"); + return FALSE; + } + + g_usleep ((dfu_device_get_download_timeout (priv->device) + 1000) * 1000); + if (!dfu_device_refresh (priv->device, error)) + return FALSE; + } + + /* in an error state */ + if (dfu_device_get_state (priv->device) == DFU_STATE_DFU_ERROR) { + g_set_error_literal (error, + FWUPD_ERROR, + FWUPD_ERROR_INTERNAL, + dfu_target_status_to_error_msg (dfu_device_get_status (priv->device))); + return FALSE; + } + + return TRUE; +} + gboolean dfu_target_check_status (DfuTarget *target, GError **error) { @@ -1285,6 +1327,11 @@ dfu_target_download (DfuTarget *target, DfuImage *image, return FALSE; } + if (fu_device_has_custom_flag (FU_DEVICE (dfu_target_get_device (target)), "manifest-poll") && + dfu_device_has_attribute (priv->device, DFU_DEVICE_ATTRIBUTE_MANIFEST_TOL)) + if (!dfu_target_manifest_wait (target, error)) + return FALSE; + /* success */ return TRUE; } diff --git a/plugins/dfu/dfu.quirk b/plugins/dfu/dfu.quirk index bbf172a72..5639c7cd0 100644 --- a/plugins/dfu/dfu.quirk +++ b/plugins/dfu/dfu.quirk @@ -329,3 +329,43 @@ Flags = absent-sector-size Plugin = dfu DfuForceVersion = 011a DfuForceTimeout = 5000 + +# Poly Studio +[DeviceInstanceId=USB\VID_095D&PID_9217] +Plugin = dfu +Flags = manifest-poll +[DeviceInstanceId=USB\VID_095D&PID_9218] +Plugin = dfu +Flags = manifest-poll + +# Poly Eagle Eye Cube +[DeviceInstanceId=USB\VID_095D&PID_9212] +Plugin = dfu +Flags = manifest-poll +[DeviceInstanceId=USB\VID_095D&PID_9213] +Plugin = dfu +Flags = manifest-poll + +# Poly P30 +[DeviceInstanceId=USB\VID_095D&PID_9290] +Plugin = dfu +Flags = manifest-poll +[DeviceInstanceId=USB\VID_095D&PID_9291] +Plugin = dfu +Flags = manifest-poll + +# Poly ULCC +[DeviceInstanceId=USB\VID_095D&PID_9160] +Plugin = dfu +Flags = manifest-poll +[DeviceInstanceId=USB\VID_095D&PID_927B] +Plugin = dfu +Flags = manifest-poll + +# Poly Eagle Eye Mini +[DeviceInstanceId=USB\VID_095D&PID_3001] +Plugin = dfu +Flags = manifest-poll +[DeviceInstanceId=USB\VID_095D&PID_3002] +Plugin = dfu +Flags = manifest-poll