Skip to content

Commit

Permalink
thunderbolt-power: Use bolt force power API if available
Browse files Browse the repository at this point in the history
This is new support for bolt supported by
https://gitlab.freedesktop.org/bolt/bolt/merge_requests/101
  • Loading branch information
Mario Limonciello committed Aug 23, 2018
1 parent 6d794e2 commit 7a1c878
Showing 1 changed file with 119 additions and 1 deletion.
120 changes: 119 additions & 1 deletion plugins/thunderbolt-power/fu-plugin-thunderbolt-power.c
Expand Up @@ -9,13 +9,18 @@
#include <errno.h>
#include <fcntl.h>
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <gudev/gudev.h>

#include "fu-plugin-vfuncs.h"
#include "fu-device-metadata.h"

#define BOLT_DBUS_SERVICE "org.freedesktop.bolt"
#define BOLT_DBUS_PATH "/org/freedesktop/bolt"
#define BOLT_DBUS_INTERFACE "org.freedesktop.bolt1.Manager"

#ifndef HAVE_GUDEV_232
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"
Expand All @@ -32,8 +37,105 @@ struct FuPluginData {
gboolean needs_forcepower;
gboolean updating;
guint timeout_id;
gboolean bolt_supported;
gint bolt_fd;
};

static void
fu_plugin_thunderbolt_power_bolt_supported (FuPlugin *plugin)
{
FuPluginData *data = fu_plugin_get_data (plugin);
g_autoptr(GDBusConnection) connection = NULL;
g_autoptr(GVariant) val = NULL;
g_autoptr(GDBusProxy) proxy = NULL;
g_autoptr(GError) error_local = NULL;

connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error_local);
if (connection == NULL) {
g_warning ("Failed to initialize d-bus connection: %s",
error_local->message);
return;
}

proxy = g_dbus_proxy_new_sync (connection,
G_DBUS_PROXY_FLAGS_NONE,
NULL,
BOLT_DBUS_SERVICE,
BOLT_DBUS_PATH,
BOLT_DBUS_INTERFACE,
NULL,
&error_local);
if (proxy == NULL) {
g_warning ("Failed to initialize d-bus proxy: %s",
error_local->message);
return;
}
val = g_dbus_proxy_call_sync (proxy,
"ListGuards",
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
NULL);
data->bolt_supported = (val != NULL);
g_debug ("Bolt force power support: %d", data->bolt_supported);
}

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;
g_autoptr(GError) err = 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 retunred: %d",
g_unix_fd_list_get_length (fds));
return FALSE;
}
data->bolt_fd = g_unix_fd_list_get (fds, 0, NULL);

return TRUE;
}

static void
fu_plugin_thunderbolt_power_get_path (FuPlugin *plugin)
{
Expand Down Expand Up @@ -66,7 +168,7 @@ fu_plugin_thunderbolt_power_get_path (FuPlugin *plugin)
"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",
g_debug ("Direct kernel force power support at %s",
data->force_path);
break;
}
Expand All @@ -89,6 +191,16 @@ fu_plugin_thunderbolt_power_set (FuPlugin *plugin, gboolean enable,
gint fd;
gint ret;

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

if (!fu_plugin_thunderbolt_power_supported (plugin)) {
g_set_error (error,
FWUPD_ERROR,
Expand Down Expand Up @@ -200,6 +312,9 @@ fu_plugin_init (FuPlugin *plugin)
/* initially set to true, will wait for a device_register to reset */
data->needs_forcepower = TRUE;

/* determine if we have bolt Force Power support */
fu_plugin_thunderbolt_power_bolt_supported (plugin);

/* determines whether to run device_registered */
fu_plugin_thunderbolt_power_get_path (plugin);

Expand All @@ -217,6 +332,9 @@ fu_plugin_destroy (FuPlugin *plugin)
}
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);
}

void
Expand Down

0 comments on commit 7a1c878

Please sign in to comment.