mirror of
https://git.proxmox.com/git/fwupd
synced 2025-07-09 10:24:52 +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}
|
%if 0%{?enable_dummy}
|
||||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_test.so
|
%{_libdir}/fwupd-plugins-3/libfu_plugin_test.so
|
||||||
%endif
|
%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.so
|
||||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_thunderbolt_power.so
|
%{_libdir}/fwupd-plugins-3/libfu_plugin_thunderbolt_power.so
|
||||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_udev.so
|
%{_libdir}/fwupd-plugins-3/libfu_plugin_udev.so
|
||||||
|
@ -12,6 +12,7 @@ subdir('solokey')
|
|||||||
subdir('synaptics-cxaudio')
|
subdir('synaptics-cxaudio')
|
||||||
subdir('synaptics-prometheus')
|
subdir('synaptics-prometheus')
|
||||||
subdir('test')
|
subdir('test')
|
||||||
|
subdir('thelio-io')
|
||||||
subdir('udev')
|
subdir('udev')
|
||||||
subdir('unifying')
|
subdir('unifying')
|
||||||
subdir('upower')
|
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));
|
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:
|
* fu_usb_device_get_dev:
|
||||||
* @device: A #FuUsbDevice
|
* @device: A #FuUsbDevice
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <gusb.h>
|
#include <gusb.h>
|
||||||
|
#include <gudev/gudev.h>
|
||||||
|
|
||||||
#include "fu-plugin.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,
|
void fu_usb_device_set_dev (FuUsbDevice *device,
|
||||||
GUsbDevice *usb_device);
|
GUsbDevice *usb_device);
|
||||||
gboolean fu_usb_device_is_open (FuUsbDevice *device);
|
gboolean fu_usb_device_is_open (FuUsbDevice *device);
|
||||||
|
GUdevDevice *fu_usb_device_find_udev_device (FuUsbDevice *device,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
Loading…
Reference in New Issue
Block a user