mirror of
https://git.proxmox.com/git/fwupd
synced 2025-07-06 09:04:58 +00:00
thelio-io: Add a plugin to detach the Thelio IO board
This does not use the DFU runtime to detach.
This commit is contained in:
parent
a1f9d5850b
commit
59593b0c50
@ -336,6 +336,7 @@ rm ${RPM_BUILD_ROOT}%{_sbindir}/flashrom
|
||||
%if 0%{?enable_dummy}
|
||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_test.so
|
||||
%endif
|
||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_thelio_io.so
|
||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_thunderbolt.so
|
||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_thunderbolt_power.so
|
||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_udev.so
|
||||
|
@ -12,6 +12,7 @@ subdir('solokey')
|
||||
subdir('synaptics-cxaudio')
|
||||
subdir('synaptics-prometheus')
|
||||
subdir('test')
|
||||
subdir('thelio-io')
|
||||
subdir('udev')
|
||||
subdir('unifying')
|
||||
subdir('upower')
|
||||
|
17
plugins/thelio-io/README.md
Normal file
17
plugins/thelio-io/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
Thelio IO Support
|
||||
=================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This plugin is used to detach the Thelio IO device to DFU mode.
|
||||
|
||||
To switch to this mode `1` has to be written to the `bootloader` file
|
||||
in sysfs.
|
||||
|
||||
GUID Generation
|
||||
---------------
|
||||
|
||||
These devices use the standard USB DeviceInstanceId values, e.g.
|
||||
|
||||
* `USB\VID_1209&PID_1776&REV_0001`
|
44
plugins/thelio-io/fu-plugin-thelio-io.c
Normal file
44
plugins/thelio-io/fu-plugin-thelio-io.c
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
|
||||
* Copyright (C) 2019 Jeremy Soller <jeremy@system76.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "fu-plugin-vfuncs.h"
|
||||
|
||||
#include "fu-thelio-io-device.h"
|
||||
|
||||
void
|
||||
fu_plugin_init (FuPlugin *plugin)
|
||||
{
|
||||
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
|
||||
fu_plugin_add_rule (plugin, FU_PLUGIN_RULE_REQUIRES_QUIRK, FU_QUIRKS_PLUGIN);
|
||||
}
|
||||
|
||||
gboolean
|
||||
fu_plugin_update_detach (FuPlugin *plugin, FuDevice *device, GError **error)
|
||||
{
|
||||
g_autoptr(FuDeviceLocker) locker = fu_device_locker_new (device, error);
|
||||
if (locker == NULL)
|
||||
return FALSE;
|
||||
if (!fu_device_detach (device, error))
|
||||
return FALSE;
|
||||
fu_device_add_flag (device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
fu_plugin_usb_device_added (FuPlugin *plugin, FuUsbDevice *device, GError **error)
|
||||
{
|
||||
g_autoptr(FuThelioIoDevice) dev = NULL;
|
||||
g_autoptr(FuDeviceLocker) locker = NULL;
|
||||
dev = fu_thelio_io_device_new (device);
|
||||
locker = fu_device_locker_new (dev, error);
|
||||
if (locker == NULL)
|
||||
return FALSE;
|
||||
fu_plugin_device_add (plugin, FU_DEVICE (dev));
|
||||
return TRUE;
|
||||
}
|
103
plugins/thelio-io/fu-thelio-io-device.c
Normal file
103
plugins/thelio-io/fu-thelio-io-device.c
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
|
||||
* Copyright (C) 2019 Jeremy Soller <jeremy@system76.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "fu-io-channel.h"
|
||||
#include "fu-thelio-io-device.h"
|
||||
|
||||
struct _FuThelioIoDevice {
|
||||
FuUsbDevice parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (FuThelioIoDevice, fu_thelio_io_device, FU_TYPE_USB_DEVICE)
|
||||
|
||||
static gboolean
|
||||
fu_thelio_io_device_probe (FuDevice *device, GError **error)
|
||||
{
|
||||
const gchar *devpath;
|
||||
g_autofree gchar *fn = NULL;
|
||||
g_autofree gchar *buf = NULL;
|
||||
g_autoptr(GUdevDevice) udev_device = NULL;
|
||||
|
||||
fu_device_add_instance_id (device, "USB\\VID_03EB&PID_2FF4");
|
||||
|
||||
/* convert GUsbDevice to GUdevDevice */
|
||||
udev_device = fu_usb_device_find_udev_device (FU_USB_DEVICE (device), error);
|
||||
if (udev_device == NULL)
|
||||
return FALSE;
|
||||
|
||||
devpath = g_udev_device_get_sysfs_path (udev_device);
|
||||
if (G_UNLIKELY (devpath == NULL)) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR, FWUPD_ERROR_INTERNAL,
|
||||
"Could not determine sysfs path for device");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fn = g_build_filename (devpath, "revision", NULL);
|
||||
if (!g_file_get_contents(fn, &buf, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
fu_device_set_version (device, (const gchar *) buf, FWUPD_VERSION_FORMAT_TRIPLET);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_thelio_io_device_detach (FuDevice *device, GError **error)
|
||||
{
|
||||
const gchar *devpath;
|
||||
g_autofree gchar *fn = NULL;
|
||||
g_autoptr(FuIOChannel) io_channel = NULL;
|
||||
g_autoptr(GUdevDevice) udev_device = NULL;
|
||||
const guint8 buf[] = { '1', '\n' };
|
||||
|
||||
/* convert GUsbDevice to GUdevDevice */
|
||||
udev_device = fu_usb_device_find_udev_device (FU_USB_DEVICE (device), error);
|
||||
if (udev_device == NULL)
|
||||
return FALSE;
|
||||
fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART);
|
||||
|
||||
devpath = g_udev_device_get_sysfs_path (udev_device);
|
||||
if (G_UNLIKELY (devpath == NULL)) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR, FWUPD_ERROR_INTERNAL,
|
||||
"Could not determine sysfs path for device");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fn = g_build_filename (devpath, "bootloader", NULL);
|
||||
io_channel = fu_io_channel_new_file (fn, error);
|
||||
if (io_channel == NULL)
|
||||
return FALSE;
|
||||
return fu_io_channel_write_raw (io_channel, buf, sizeof(buf),
|
||||
500, FU_IO_CHANNEL_FLAG_SINGLE_SHOT, error);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_thelio_io_device_init (FuThelioIoDevice *self)
|
||||
{
|
||||
fu_device_add_flag (FU_DEVICE (self), FWUPD_DEVICE_FLAG_UPDATABLE);
|
||||
fu_device_set_remove_delay (FU_DEVICE (self), FU_DEVICE_REMOVE_DELAY_RE_ENUMERATE);
|
||||
}
|
||||
|
||||
static void
|
||||
fu_thelio_io_device_class_init (FuThelioIoDeviceClass *klass)
|
||||
{
|
||||
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
|
||||
klass_device->probe = fu_thelio_io_device_probe;
|
||||
klass_device->detach = fu_thelio_io_device_detach;
|
||||
}
|
||||
|
||||
FuThelioIoDevice *
|
||||
fu_thelio_io_device_new (FuUsbDevice *device)
|
||||
{
|
||||
FuThelioIoDevice *self = g_object_new (FU_TYPE_THELIO_IO_DEVICE, NULL);
|
||||
fu_device_incorporate (FU_DEVICE (self), FU_DEVICE (device));
|
||||
return self;
|
||||
}
|
19
plugins/thelio-io/fu-thelio-io-device.h
Normal file
19
plugins/thelio-io/fu-thelio-io-device.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
|
||||
* Copyright (C) 2019 Jeremy Soller <jeremy@system76.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fu-plugin.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define FU_TYPE_THELIO_IO_DEVICE (fu_thelio_io_device_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (FuThelioIoDevice, fu_thelio_io_device, FU, THELIO_IO_DEVICE, FuUsbDevice)
|
||||
|
||||
FuThelioIoDevice *fu_thelio_io_device_new (FuUsbDevice *device);
|
||||
|
||||
G_END_DECLS
|
27
plugins/thelio-io/meson.build
Normal file
27
plugins/thelio-io/meson.build
Normal file
@ -0,0 +1,27 @@
|
||||
cargs = ['-DG_LOG_DOMAIN="FuPluginThelioIo"']
|
||||
|
||||
install_data(['thelio-io.quirk'],
|
||||
install_dir: join_paths(datadir, 'fwupd', 'quirks.d')
|
||||
)
|
||||
|
||||
shared_module('fu_plugin_thelio_io',
|
||||
fu_hash,
|
||||
sources : [
|
||||
'fu-plugin-thelio-io.c',
|
||||
'fu-thelio-io-device.c',
|
||||
],
|
||||
include_directories : [
|
||||
include_directories('../..'),
|
||||
include_directories('../../src'),
|
||||
include_directories('../../libfwupd'),
|
||||
],
|
||||
install : true,
|
||||
install_dir: plugin_dir,
|
||||
link_with : [
|
||||
libfwupdprivate,
|
||||
],
|
||||
c_args : cargs,
|
||||
dependencies : [
|
||||
plugin_deps,
|
||||
],
|
||||
)
|
3
plugins/thelio-io/thelio-io.quirk
Normal file
3
plugins/thelio-io/thelio-io.quirk
Normal file
@ -0,0 +1,3 @@
|
||||
# System76 Thelio IO
|
||||
[DeviceInstanceId=USB\VID_1209&PID_1776&REV_0001]
|
||||
Plugin = thelio_io
|
@ -388,6 +388,55 @@ fu_usb_device_set_dev (FuUsbDevice *device, GUsbDevice *usb_device)
|
||||
g_usb_device_get_platform_id (usb_device));
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_usb_device_find_udev_device:
|
||||
* @device: A #FuUsbDevice
|
||||
* @usb_device: A #GUsbDevice, or %NULL
|
||||
*
|
||||
* Gets the matching #GUdevDevice for the #GUsbDevice.
|
||||
*
|
||||
* Returns: a #GUdevDevice, or NULL if unset or invalid
|
||||
*
|
||||
* Since: 1.3.2
|
||||
**/
|
||||
GUdevDevice *
|
||||
fu_usb_device_find_udev_device (FuUsbDevice *device, GError **error)
|
||||
{
|
||||
FuUsbDevicePrivate *priv = GET_PRIVATE (device);
|
||||
g_autoptr(GList) devices = NULL;
|
||||
g_autoptr(GUdevClient) gudev_client = g_udev_client_new (NULL);
|
||||
|
||||
/* find all tty devices */
|
||||
devices = g_udev_client_query_by_subsystem (gudev_client, "usb");
|
||||
for (GList *l = devices; l != NULL; l = l->next) {
|
||||
GUdevDevice *dev = G_UDEV_DEVICE (l->data);
|
||||
|
||||
/* check correct device */
|
||||
if (g_udev_device_get_sysfs_attr_as_int (dev, "busnum") !=
|
||||
g_usb_device_get_bus (priv->usb_device))
|
||||
continue;
|
||||
if (g_udev_device_get_sysfs_attr_as_int (dev, "devnum") !=
|
||||
g_usb_device_get_address (priv->usb_device))
|
||||
continue;
|
||||
|
||||
/* success */
|
||||
g_debug ("USB device %u:%u is %s",
|
||||
g_usb_device_get_bus (priv->usb_device),
|
||||
g_usb_device_get_address (priv->usb_device),
|
||||
g_udev_device_get_sysfs_path (dev));
|
||||
return g_object_ref (dev);
|
||||
}
|
||||
|
||||
/* failure */
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
"could not find sysfs device for %u:%u",
|
||||
g_usb_device_get_bus (priv->usb_device),
|
||||
g_usb_device_get_address (priv->usb_device));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* fu_usb_device_get_dev:
|
||||
* @device: A #FuUsbDevice
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gusb.h>
|
||||
#include <gudev/gudev.h>
|
||||
|
||||
#include "fu-plugin.h"
|
||||
|
||||
@ -45,5 +46,7 @@ GUsbDevice *fu_usb_device_get_dev (FuUsbDevice *device);
|
||||
void fu_usb_device_set_dev (FuUsbDevice *device,
|
||||
GUsbDevice *usb_device);
|
||||
gboolean fu_usb_device_is_open (FuUsbDevice *device);
|
||||
GUdevDevice *fu_usb_device_find_udev_device (FuUsbDevice *device,
|
||||
GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
Loading…
Reference in New Issue
Block a user