Exemplo n.º 1
0
static gboolean
fu_plugin_thunderbolt_power_coldplug (FuPlugin *plugin, GError **error)
{
	FuPluginData *data = fu_plugin_get_data (plugin);

	if (!fu_plugin_thunderbolt_power_supported (plugin)) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_NOT_SUPPORTED,
			     "missing kernel support for intel-wmi-thunderbolt");
		return FALSE;
	}

	/* this means no devices were found at coldplug by thunderbolt plugin */
	if (data->needs_forcepower) {
		if (!fu_plugin_thunderbolt_power_set (plugin, TRUE, error))
			return FALSE;
		/* in case this was a re-coldplug */
		if (data->timeout_id != 0)
			g_source_remove (data->timeout_id);

		/* reset force power to off after enough time to enumerate */
		data->timeout_id =
			g_timeout_add (TBT_NEW_DEVICE_TIMEOUT * 10000,
				       fu_plugin_thunderbolt_power_reset_cb,
				       plugin);
	}

	return TRUE;
}
Exemplo n.º 2
0
static gboolean
fu_plugin_thunderbolt_power_reset_cb (gpointer user_data)
{
	FuPlugin *plugin = FU_PLUGIN (user_data);
	FuPluginData *data = fu_plugin_get_data (plugin);

	if (!fu_plugin_thunderbolt_power_set (plugin, FALSE, NULL))
		g_warning ("failed to reset thunderbolt power");
	data->timeout_id = 0;
	return FALSE;
}
Exemplo n.º 3
0
void
fu_plugin_destroy (FuPlugin *plugin)
{
	FuPluginData *data = fu_plugin_get_data (plugin);
	if (data->timeout_id != 0) {
		g_source_remove (data->timeout_id);
		data->timeout_id = 0;
	}
	g_object_unref (data->udev);
	g_free (data->force_path);
}
Exemplo n.º 4
0
static gboolean
fu_plugin_thunderbolt_power_bolt_force_power (FuPlugin *plugin,
					      GError **error)
{
	FuPluginData *data = fu_plugin_get_data (plugin);
	g_autoptr(GDBusConnection) connection = NULL;
	g_autoptr(GDBusProxy) proxy = NULL;
	g_autoptr(GUnixFDList) fds = NULL;
	g_autoptr(GVariant) val = NULL;
	GVariant *input;

	input = g_variant_new ("(ss)",
				"fwupd",   /* who */
				"");       /* flags */

	connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, error);
	if (connection == NULL)
		return FALSE;

	proxy = g_dbus_proxy_new_sync (connection,
					G_DBUS_PROXY_FLAGS_NONE,
					NULL,
					BOLT_DBUS_SERVICE,
					BOLT_DBUS_PATH,
					BOLT_DBUS_INTERFACE,
					NULL,
					error);
	if (proxy == NULL)
		return FALSE;

	val = g_dbus_proxy_call_with_unix_fd_list_sync (proxy,
							"ForcePower",
							input,
							G_DBUS_CALL_FLAGS_NONE,
							-1,
							NULL,
							&fds,
							NULL,
							error);

	if (val == NULL)
		return FALSE;

	if (g_unix_fd_list_get_length (fds) != 1) {
		g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
				"invalid number of file descriptors returned: %d",
				g_unix_fd_list_get_length (fds));
		return FALSE;
	}
	data->bolt_fd = g_unix_fd_list_get (fds, 0, NULL);

	return TRUE;
}
Exemplo n.º 5
0
gboolean
fu_plugin_update_prepare (FuPlugin *plugin,
			  FwupdInstallFlags flags,
			  FuDevice *device,
			  GError **error)
{
	FuPluginData *data = fu_plugin_get_data (plugin);
	g_autoptr(GUdevDevice) udevice = NULL;
	const gchar *devpath;

	/* only run for thunderbolt plugin */
	if (g_strcmp0 (fu_device_get_plugin (device), "thunderbolt") != 0)
		return TRUE;

	/* reset any timers that might still be running from coldplug */
	if (data->timeout_id != 0) {
		g_source_remove (data->timeout_id);
		data->timeout_id = 0;
	}

	devpath = fu_device_get_metadata (device, "sysfs-path");

	udevice = g_udev_client_query_by_sysfs_path (data->udev, devpath);
	if (udevice != NULL) {
		data->needs_forcepower = FALSE;
		return TRUE;
	}
	data->updating = TRUE;
	if (!fu_plugin_thunderbolt_power_set (plugin, TRUE, error))
		return FALSE;

	data->needs_forcepower = TRUE;

	/* wait for the device to come back onto the bus */
	fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART);
	for (guint i = 0; i < 5; i++) {
		g_autoptr(GUdevDevice) udevice_tmp = NULL;
		g_usleep (TBT_NEW_DEVICE_TIMEOUT * G_USEC_PER_SEC);
		udevice_tmp = g_udev_client_query_by_sysfs_path (data->udev, devpath);
		if (udevice_tmp != NULL)
			return TRUE;
	}

	/* device did not wake up */
	g_set_error (error,
		     FWUPD_ERROR,
		     FWUPD_ERROR_NOT_SUPPORTED,
		     "device did not wake up when required");
	return FALSE;
}
Exemplo n.º 6
0
void
fu_plugin_destroy (FuPlugin *plugin)
{
	FuPluginData *data = fu_plugin_get_data (plugin);
	if (data->timeout_id != 0) {
		g_source_remove (data->timeout_id);
		data->timeout_id = 0;
	}
	g_object_unref (data->udev);
	g_free (data->force_path);
	/* in case destroying before force power turned off */
	if (data->bolt_fd >= 0)
		g_close (data->bolt_fd, NULL);
}
Exemplo n.º 7
0
gboolean
fu_plugin_update_cleanup (FuPlugin *plugin,
			  FuDevice *device,
			  GError **error)
{
	FuPluginData *data = fu_plugin_get_data (plugin);

	/* only run for thunderbolt plugin */
	if (g_strcmp0 (fu_device_get_plugin (device), "thunderbolt") != 0)
		return TRUE;

	if (data->needs_forcepower &&
	    !fu_plugin_thunderbolt_power_set (plugin, FALSE, error))
		return FALSE;
	return TRUE;
}
Exemplo n.º 8
0
void
fu_plugin_device_registered (FuPlugin *plugin, FuDevice *device)
{
	FuPluginData *data = fu_plugin_get_data (plugin);

	/* thunderbolt plugin */
	if (g_strcmp0 (fu_device_get_plugin (device), "thunderbolt") == 0 &&
	    fu_plugin_thunderbolt_power_supported (plugin)) {
		data->needs_forcepower = FALSE;
		if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_INTERNAL)) {
			fu_device_set_metadata_boolean (device,
							FU_DEVICE_METADATA_TBT_CAN_FORCE_POWER,
							TRUE);
		}
	}
}
Exemplo n.º 9
0
static gboolean
fu_plugin_thunderbolt_power_set (FuPlugin *plugin, gboolean enable,
				 GError **error)
{
	FuPluginData *data = fu_plugin_get_data (plugin);

	/* prefer bolt API if available */
	if (fu_plugin_thunderbolt_power_bolt_supported (plugin)) {
		g_debug ("Setting force power to %d using bolt", enable);
		if (enable)
			return fu_plugin_thunderbolt_power_bolt_force_power (plugin, error);
		return data->bolt_fd >= 0 ? g_close (data->bolt_fd, error) : TRUE;
	}

	return fu_plugin_thunderbolt_power_kernel_force_power (plugin, enable, error);
}
Exemplo n.º 10
0
static void
fu_plugin_thunderbolt_reset_timeout (FuPlugin *plugin)
{
	FuPluginData *data = fu_plugin_get_data (plugin);

	if (!data->needs_forcepower || data->updating)
		return;

	g_debug ("Setting timeout to %d seconds",
		 TBT_NEW_DEVICE_TIMEOUT * 10);

	/* in case this was a re-coldplug */
	if (data->timeout_id != 0)
		g_source_remove (data->timeout_id);

	/* reset force power to off after enough time to enumerate */
	data->timeout_id =
		g_timeout_add (TBT_NEW_DEVICE_TIMEOUT * 10000,
				fu_plugin_thunderbolt_power_reset_cb,
				plugin);
}
Exemplo n.º 11
0
static void
fu_plugin_thunderbolt_power_get_path (FuPlugin *plugin)
{
	FuPluginData *data = fu_plugin_get_data (plugin);
	g_autoptr(GList) devices = NULL;
	const gchar *basepath;
	const gchar *driver;

	/* in case driver went away */
	if (data->force_path != NULL) {
		g_free (data->force_path);
		data->force_path = NULL;
	}

	devices = g_udev_client_query_by_subsystem (data->udev, "wmi");
	for (GList* l = devices; l != NULL; l = l->next) {
		g_autofree gchar *built_path = NULL;
		GUdevDevice *device = l->data;

		/* only supports intel-wmi-thunderbolt for now */
		driver = g_udev_device_get_driver (device);
		if (g_strcmp0 (driver, "intel-wmi-thunderbolt") != 0)
			continue;

		/* check for the attribute to be loaded */
		basepath = g_udev_device_get_sysfs_path (device);
		if (basepath == NULL)
			continue;
		built_path = g_build_path ("/", basepath,
					   "force_power", NULL);
		if (g_file_test (built_path, G_FILE_TEST_IS_REGULAR)) {
			data->force_path = g_steal_pointer (&built_path);
			g_debug ("Detected force power support at %s",
				 data->force_path);
			break;
		}
	}
	g_list_foreach (devices, (GFunc) g_object_unref, NULL);
}
Exemplo n.º 12
0
static gboolean
fu_plugin_thunderbolt_power_kernel_force_power (FuPlugin *plugin, gboolean enable,
						GError **error)
{
	FuPluginData *data = fu_plugin_get_data (plugin);
	gint fd;
	gint ret;

	if (!fu_plugin_thunderbolt_power_kernel_supported (plugin)) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_NOT_SUPPORTED,
			     "unable to set power to %d (missing kernel support)",
			     enable);
		return FALSE;
	}
	g_debug ("Setting force power to %d using kernel", enable);
	fd = g_open (data->force_path, O_WRONLY);
	if (fd == -1) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_INTERNAL,
			     "failed to open %s", data->force_path);
		return FALSE;
	}
	ret = write (fd, enable ? "1" : "0", 1);
	if (ret < 1) {
		g_set_error (error, G_IO_ERROR,
			     g_io_error_from_errno (errno),
			     "could not write to force_power': %s",
			     g_strerror (errno));
		g_close (fd, NULL);
		return FALSE;
	}

	return g_close (fd, error);
}
Exemplo n.º 13
0
static gboolean
fu_plugin_thunderbolt_power_coldplug (FuPlugin *plugin, GError **error)
{
	FuPluginData *data = fu_plugin_get_data (plugin);

	if (!fu_plugin_thunderbolt_power_bolt_supported (plugin) &&
	    !fu_plugin_thunderbolt_power_kernel_supported (plugin)) {
		g_set_error (error,
			     FWUPD_ERROR,
			     FWUPD_ERROR_NOT_SUPPORTED,
			     "No support for force power via kernel or bolt");
		return FALSE;
	}

	/* this means no devices were found at coldplug by thunderbolt plugin */
	if (data->needs_forcepower) {
		if (!fu_plugin_thunderbolt_power_set (plugin, TRUE, error))
			return FALSE;

		fu_plugin_thunderbolt_reset_timeout (plugin);
	}

	return TRUE;
}
Exemplo n.º 14
0
static gboolean
fu_plugin_thunderbolt_power_supported (FuPlugin *plugin)
{
	FuPluginData *data = fu_plugin_get_data (plugin);
	return data->force_path != NULL;
}