/** * fu_provider_clear_results: **/ gboolean fu_provider_clear_results (FuProvider *provider, FuDevice *device, GError **error) { FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider); g_autoptr(GError) error_local = NULL; g_autoptr(FuDevice) device_pending = NULL; g_autoptr(FuPending) pending = NULL; /* handled by the provider */ if (klass->clear_results != NULL) return klass->clear_results (provider, device, error); /* handled using the database */ pending = fu_pending_new (); device_pending = fu_pending_get_device (pending, fu_device_get_id (device), &error_local); if (device_pending == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "Failed to find %s in pending database: %s", fu_device_get_id (device), error_local->message); return FALSE; } /* remove from pending database */ return fu_pending_remove_device (pending, device, error); }
/** * fu_provider_unlock: **/ gboolean fu_provider_unlock (FuProvider *provider, FuDevice *device, GError **error) { guint64 flags; FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider); /* final check */ flags = fu_device_get_flags (device); if ((flags & FU_DEVICE_FLAG_LOCKED) == 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "Device %s is not locked", fu_device_get_id (device)); return FALSE; } /* run provider method */ if (klass->unlock != NULL) { if (!klass->unlock (provider, device, error)) return FALSE; } /* update with correct flags */ flags = fu_device_get_flags (device); fu_device_set_flags (device, flags &= ~FU_DEVICE_FLAG_LOCKED); fu_device_set_modified (device, g_get_real_time () / G_USEC_PER_SEC); return TRUE; }
/** * fu_provider_device_add: **/ const gchar * fu_provider_get_name (FuProvider *provider) { FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider); if (klass->get_name != NULL) return klass->get_name (provider); return NULL; }
/** * fu_provider_coldplug: **/ gboolean fu_provider_coldplug (FuProvider *provider, GError **error) { FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider); if (klass->coldplug != NULL) return klass->coldplug (provider, error); return TRUE; }
/** * fu_provider_verify: **/ gboolean fu_provider_verify (FuProvider *provider, FuDevice *device, FuProviderVerifyFlags flags, GError **error) { FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider); if (klass->verify != NULL) return klass->verify (provider, device, flags, error); return TRUE; }
/** * fu_provider_get_results: **/ gboolean fu_provider_get_results (FuProvider *provider, FuDevice *device, GError **error) { FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider); FwupdUpdateState update_state; const gchar *tmp; g_autoptr(GError) error_local = NULL; g_autoptr(FwupdResult) res_pending = NULL; g_autoptr(FuPending) pending = NULL; /* handled by the provider */ if (klass->get_results != NULL) return klass->get_results (provider, device, error); /* handled using the database */ pending = fu_pending_new (); res_pending = fu_pending_get_device (pending, fu_device_get_id (device), &error_local); if (res_pending == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, "Failed to find %s in pending database: %s", fu_device_get_id (device), error_local->message); return FALSE; } /* copy the important parts from the pending device to the real one */ update_state = fwupd_result_get_update_state (res_pending); if (update_state == FWUPD_UPDATE_STATE_UNKNOWN || update_state == FWUPD_UPDATE_STATE_PENDING) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, "Device %s has not been updated offline yet", fu_device_get_id (device)); return FALSE; } /* copy */ fu_device_set_update_state (device, update_state); tmp = fwupd_result_get_update_error (res_pending); if (tmp != NULL) fu_device_set_update_error (device, tmp); tmp = fwupd_result_get_device_version (res_pending); if (tmp != NULL) fu_device_set_version (device, tmp); tmp = fwupd_result_get_update_version (res_pending); if (tmp != NULL) fu_device_set_update_version (device, tmp); return TRUE; }
/** * fu_provider_get_results: **/ gboolean fu_provider_get_results (FuProvider *provider, FuDevice *device, GError **error) { FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider); const gchar *tmp; guint i; g_autoptr(GError) error_local = NULL; g_autoptr(FuDevice) device_pending = NULL; g_autoptr(FuPending) pending = NULL; const gchar *copy_keys[] = { FU_DEVICE_KEY_PENDING_STATE, FU_DEVICE_KEY_PENDING_ERROR, FU_DEVICE_KEY_VERSION, FU_DEVICE_KEY_UPDATE_VERSION, NULL }; /* handled by the provider */ if (klass->get_results != NULL) return klass->get_results (provider, device, error); /* handled using the database */ pending = fu_pending_new (); device_pending = fu_pending_get_device (pending, fu_device_get_id (device), &error_local); if (device_pending == NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, "Failed to find %s in pending database: %s", fu_device_get_id (device), error_local->message); return FALSE; } /* copy the important parts from the pending device to the real one */ tmp = fu_device_get_metadata (device_pending, FU_DEVICE_KEY_PENDING_STATE); if (tmp == NULL || g_strcmp0 (tmp, "scheduled") == 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, "Device %s has not been updated offline yet", fu_device_get_id (device)); return FALSE; } for (i = 0; copy_keys[i] != NULL; i++) { tmp = fu_device_get_metadata (device_pending, copy_keys[i]); if (tmp != NULL) fu_device_set_metadata (device, copy_keys[i], tmp); } return TRUE; }
/** * fu_provider_update: **/ gboolean fu_provider_update (FuProvider *provider, FuDevice *device, GBytes *blob_cab, GBytes *blob_fw, FuProviderFlags flags, GError **error) { FuProviderClass *klass = FU_PROVIDER_GET_CLASS (provider); g_autoptr(FuPending) pending = NULL; g_autoptr(FuDevice) device_pending = NULL; GError *error_update = NULL; /* schedule for next reboot, or handle in the provider */ if (flags & FU_PROVIDER_UPDATE_FLAG_OFFLINE) { if (klass->update_offline == NULL) return fu_provider_schedule_update (provider, device, blob_cab, error); return klass->update_offline (provider, device, blob_fw, flags, error); } /* cancel the pending action */ if (!fu_provider_offline_invalidate (error)) return FALSE; /* online */ if (klass->update_online == NULL) { g_set_error_literal (error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "No online update possible"); return FALSE; } pending = fu_pending_new (); device_pending = fu_pending_get_device (pending, fu_device_get_id (device), NULL); if (!klass->update_online (provider, device, blob_fw, flags, &error_update)) { /* save the error to the database */ if (device_pending != NULL) { fu_pending_set_error_msg (pending, device, error_update->message, NULL); } g_propagate_error (error, error_update); return FALSE; } /* cleanup */ if (device_pending != NULL) { const gchar *tmp; /* update pending database */ fu_pending_set_state (pending, device, FU_PENDING_STATE_SUCCESS, NULL); /* delete cab file */ tmp = fu_device_get_metadata (device_pending, FU_DEVICE_KEY_FILENAME_CAB); if (tmp != NULL && g_str_has_prefix (tmp, LIBEXECDIR)) { g_autoptr(GError) error_local = NULL; g_autoptr(GFile) file = NULL; file = g_file_new_for_path (tmp); if (!g_file_delete (file, NULL, &error_local)) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "Failed to delete %s: %s", tmp, error_local->message); return FALSE; } } } return TRUE; }