mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-15 16:41:10 +00:00
Add FuHidDevice abstraction
Quite a few plugins use HID commands to communicate with the hardware. At the mement we have ~6 implementations of SET_REPORT and are soon to add one more. Move this into common code.
This commit is contained in:
parent
c134451aeb
commit
c04f5a3e15
327
libfwupdplugin/fu-hid-device.c
Normal file
327
libfwupdplugin/fu-hid-device.c
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017-2020 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define G_LOG_DOMAIN "FuHidDevice"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "fu-hid-device.h"
|
||||||
|
|
||||||
|
#define FU_HID_REPORT_GET 0x01
|
||||||
|
#define FU_HID_REPORT_SET 0x09
|
||||||
|
|
||||||
|
#define FU_HID_REPORT_TYPE_INPUT 0x01
|
||||||
|
#define FU_HID_REPORT_TYPE_OUTPUT 0x02
|
||||||
|
#define FU_HID_REPORT_TYPE_FEATURE 0x03
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:fu-hid-device
|
||||||
|
* @short_description: a HID device
|
||||||
|
*
|
||||||
|
* An object that represents a HID device.
|
||||||
|
*
|
||||||
|
* See also: #FuDevice
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FuUsbDevice *usb_device;
|
||||||
|
guint8 interface;
|
||||||
|
} FuHidDevicePrivate;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE (FuHidDevice, fu_hid_device, FU_TYPE_USB_DEVICE)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_INTERFACE,
|
||||||
|
PROP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GET_PRIVATE(o) (fu_hid_device_get_instance_private (o))
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_hid_device_get_property (GObject *object, guint prop_id,
|
||||||
|
GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
FuHidDevice *device = FU_HID_DEVICE (object);
|
||||||
|
FuHidDevicePrivate *priv = GET_PRIVATE (device);
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_INTERFACE:
|
||||||
|
g_value_set_uint (value, priv->interface);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_hid_device_set_property (GObject *object, guint prop_id,
|
||||||
|
const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
FuHidDevice *device = FU_HID_DEVICE (object);
|
||||||
|
switch (prop_id) {
|
||||||
|
case PROP_INTERFACE:
|
||||||
|
fu_hid_device_set_interface (device, g_value_get_uint (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_hid_device_open (FuUsbDevice *device, GError **error)
|
||||||
|
{
|
||||||
|
FuHidDevice *self = FU_HID_DEVICE (device);
|
||||||
|
FuHidDeviceClass *klass = FU_HID_DEVICE_GET_CLASS (device);
|
||||||
|
FuHidDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
GUsbDevice *usb_device = fu_usb_device_get_dev (device);
|
||||||
|
|
||||||
|
/* claim */
|
||||||
|
if (!g_usb_device_claim_interface (usb_device, priv->interface,
|
||||||
|
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
||||||
|
error)) {
|
||||||
|
g_prefix_error (error, "failed to claim HID interface: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* subclassed */
|
||||||
|
if (klass->open != NULL) {
|
||||||
|
if (!klass->open (self, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_hid_device_close (FuUsbDevice *device, GError **error)
|
||||||
|
{
|
||||||
|
FuHidDevice *self = FU_HID_DEVICE (device);
|
||||||
|
FuHidDeviceClass *klass = FU_HID_DEVICE_GET_CLASS (device);
|
||||||
|
FuHidDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
GUsbDevice *usb_device = fu_usb_device_get_dev (device);
|
||||||
|
|
||||||
|
/* subclassed */
|
||||||
|
if (klass->close != NULL) {
|
||||||
|
if (!klass->close (self, error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release */
|
||||||
|
if (!g_usb_device_release_interface (usb_device, priv->interface,
|
||||||
|
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
||||||
|
error)) {
|
||||||
|
g_prefix_error (error, "failed to release HID interface: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_hid_device_set_interface:
|
||||||
|
* @self: A #FuHidDevice
|
||||||
|
* @interface: An interface number, e.g. 0x03
|
||||||
|
*
|
||||||
|
* Sets the HID USB interface number.
|
||||||
|
*
|
||||||
|
* Since: 1.4.0
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
fu_hid_device_set_interface (FuHidDevice *self, guint8 interface)
|
||||||
|
{
|
||||||
|
FuHidDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
g_return_if_fail (FU_HID_DEVICE (self));
|
||||||
|
priv->interface = interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_hid_device_get_interface:
|
||||||
|
* @self: A #FuHidDevice
|
||||||
|
*
|
||||||
|
* Gets the HID USB interface number.
|
||||||
|
*
|
||||||
|
* Returns: integer
|
||||||
|
*
|
||||||
|
* Since: 1.4.0
|
||||||
|
**/
|
||||||
|
guint8
|
||||||
|
fu_hid_device_get_interface (FuHidDevice *self)
|
||||||
|
{
|
||||||
|
FuHidDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
g_return_val_if_fail (FU_HID_DEVICE (self), 0xff);
|
||||||
|
return priv->interface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_hid_device_set_report:
|
||||||
|
* @self: A #FuHidDevice
|
||||||
|
* @value: low byte of wValue
|
||||||
|
* @buf: (nullable): a mutable buffer of data to send
|
||||||
|
* @bufsz: Size of @buf
|
||||||
|
* @timeout: timeout in ms
|
||||||
|
* @flags: #FuHidDeviceFlags e.g. %FU_HID_DEVICE_FLAG_ALLOW_TRUNC
|
||||||
|
* @error: a #GError or %NULL
|
||||||
|
*
|
||||||
|
* Calls SetReport on the hardware.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE for success
|
||||||
|
*
|
||||||
|
* Since: 1.4.0
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
fu_hid_device_set_report (FuHidDevice *self,
|
||||||
|
guint8 value,
|
||||||
|
guint8 *buf,
|
||||||
|
gsize bufsz,
|
||||||
|
guint timeout,
|
||||||
|
FuHidDeviceFlags flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
FuHidDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
||||||
|
gsize actual_len = 0;
|
||||||
|
guint16 wvalue = (FU_HID_REPORT_TYPE_OUTPUT << 8) | value;
|
||||||
|
|
||||||
|
/* special case */
|
||||||
|
if (flags & FU_HID_DEVICE_FLAG_IS_FEATURE)
|
||||||
|
wvalue = (FU_HID_REPORT_TYPE_FEATURE << 8) | value;
|
||||||
|
|
||||||
|
g_return_val_if_fail (FU_HID_DEVICE (self), FALSE);
|
||||||
|
g_return_val_if_fail (buf != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (bufsz != 0, FALSE);
|
||||||
|
|
||||||
|
if (g_getenv ("FU_HID_DEVICE_VERBOSE") != NULL)
|
||||||
|
fu_common_dump_raw (G_LOG_DOMAIN, "HID::SetReport", buf, bufsz);
|
||||||
|
if (!g_usb_device_control_transfer (usb_device,
|
||||||
|
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
||||||
|
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
||||||
|
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
||||||
|
FU_HID_REPORT_SET,
|
||||||
|
wvalue, priv->interface,
|
||||||
|
buf, bufsz,
|
||||||
|
&actual_len,
|
||||||
|
timeout,
|
||||||
|
NULL, error)) {
|
||||||
|
g_prefix_error (error, "failed to SetReport: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if ((flags & FU_HID_DEVICE_FLAG_ALLOW_TRUNC) == 0 && actual_len != bufsz) {
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
||||||
|
"only wrote %" G_GSIZE_FORMAT "bytes", actual_len);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_hid_device_get_report:
|
||||||
|
* @self: A #FuHidDevice
|
||||||
|
* @value: low byte of wValue
|
||||||
|
* @buf: (nullable): a mutable buffer of data to send
|
||||||
|
* @bufsz: Size of @buf
|
||||||
|
* @timeout: timeout in ms
|
||||||
|
* @flags: #FuHidDeviceFlags e.g. %FU_HID_DEVICE_FLAG_ALLOW_TRUNC
|
||||||
|
* @error: a #GError or %NULL
|
||||||
|
*
|
||||||
|
* Calls GetReport on the hardware.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE for success
|
||||||
|
*
|
||||||
|
* Since: 1.4.0
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
fu_hid_device_get_report (FuHidDevice *self,
|
||||||
|
guint8 value,
|
||||||
|
guint8 *buf,
|
||||||
|
gsize bufsz,
|
||||||
|
guint timeout,
|
||||||
|
FuHidDeviceFlags flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
FuHidDevicePrivate *priv = GET_PRIVATE (self);
|
||||||
|
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
||||||
|
gsize actual_len = 0;
|
||||||
|
guint16 wvalue = (FU_HID_REPORT_TYPE_INPUT << 8) | value;
|
||||||
|
|
||||||
|
g_return_val_if_fail (FU_HID_DEVICE (self), FALSE);
|
||||||
|
g_return_val_if_fail (buf != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (bufsz != 0, FALSE);
|
||||||
|
|
||||||
|
/* special case */
|
||||||
|
if (flags & FU_HID_DEVICE_FLAG_IS_FEATURE)
|
||||||
|
wvalue = (FU_HID_REPORT_TYPE_FEATURE << 8) | value;
|
||||||
|
|
||||||
|
if (g_getenv ("FU_HID_DEVICE_VERBOSE") != NULL)
|
||||||
|
fu_common_dump_raw (G_LOG_DOMAIN, "HID::GetReport", buf, actual_len);
|
||||||
|
if (!g_usb_device_control_transfer (usb_device,
|
||||||
|
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
|
||||||
|
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
||||||
|
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
||||||
|
FU_HID_REPORT_GET,
|
||||||
|
wvalue, priv->interface,
|
||||||
|
buf, bufsz,
|
||||||
|
&actual_len, /* actual length */
|
||||||
|
timeout,
|
||||||
|
NULL, error)) {
|
||||||
|
g_prefix_error (error, "failed to GetReport: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (g_getenv ("FU_HID_DEVICE_VERBOSE") != NULL)
|
||||||
|
fu_common_dump_raw (G_LOG_DOMAIN, "HID::GetReport", buf, actual_len);
|
||||||
|
if ((flags & FU_HID_DEVICE_FLAG_ALLOW_TRUNC) == 0 && actual_len != bufsz) {
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
||||||
|
"only read %" G_GSIZE_FORMAT "bytes", actual_len);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_hid_device_init (FuHidDevice *device)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fu_hid_device_new:
|
||||||
|
* @usb_device: A #GUsbDevice
|
||||||
|
*
|
||||||
|
* Creates a new #FuHidDevice.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a #FuHidDevice
|
||||||
|
*
|
||||||
|
* Since: 1.4.0
|
||||||
|
**/
|
||||||
|
FuHidDevice *
|
||||||
|
fu_hid_device_new (GUsbDevice *usb_device)
|
||||||
|
{
|
||||||
|
FuHidDevice *device = g_object_new (FU_TYPE_HID_DEVICE, NULL);
|
||||||
|
fu_usb_device_set_dev (FU_USB_DEVICE (device), usb_device);
|
||||||
|
return FU_HID_DEVICE (device);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_hid_device_class_init (FuHidDeviceClass *klass)
|
||||||
|
{
|
||||||
|
FuUsbDeviceClass *klass_usb_device = FU_USB_DEVICE_CLASS (klass);
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
|
object_class->get_property = fu_hid_device_get_property;
|
||||||
|
object_class->set_property = fu_hid_device_set_property;
|
||||||
|
klass_usb_device->open = fu_hid_device_open;
|
||||||
|
klass_usb_device->close = fu_hid_device_close;
|
||||||
|
|
||||||
|
pspec = g_param_spec_uint ("interface", NULL, NULL,
|
||||||
|
0x00, 0xff, 0x00,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_NAME);
|
||||||
|
g_object_class_install_property (object_class, PROP_INTERFACE, pspec);
|
||||||
|
}
|
58
libfwupdplugin/fu-hid-device.h
Normal file
58
libfwupdplugin/fu-hid-device.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017-2020 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "fu-usb-device.h"
|
||||||
|
|
||||||
|
#define FU_TYPE_HID_DEVICE (fu_hid_device_get_type ())
|
||||||
|
G_DECLARE_DERIVABLE_TYPE (FuHidDevice, fu_hid_device, FU, HID_DEVICE, FuUsbDevice)
|
||||||
|
|
||||||
|
struct _FuHidDeviceClass
|
||||||
|
{
|
||||||
|
FuUsbDeviceClass parent_class;
|
||||||
|
gboolean (*open) (FuHidDevice *device,
|
||||||
|
GError **error);
|
||||||
|
gboolean (*close) (FuHidDevice *device,
|
||||||
|
GError **error);
|
||||||
|
gpointer __reserved[29];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FuHidDeviceFlags:
|
||||||
|
* @FU_HID_DEVICE_FLAG_NONE: No flags set
|
||||||
|
* @FU_HID_DEVICE_FLAG_ALLOW_TRUNC: Allow truncated reads and writes
|
||||||
|
* @FU_HID_DEVICE_FLAG_IS_FEATURE: Use %FU_HID_REPORT_TYPE_FEATURE for wValue
|
||||||
|
*
|
||||||
|
* Flags used when calling fu_hid_device_get_report() and fu_hid_device_set_report().
|
||||||
|
**/
|
||||||
|
typedef enum {
|
||||||
|
FU_HID_DEVICE_FLAG_NONE = 0,
|
||||||
|
FU_HID_DEVICE_FLAG_ALLOW_TRUNC = 1 << 0,
|
||||||
|
FU_HID_DEVICE_FLAG_IS_FEATURE = 1 << 1,
|
||||||
|
FU_HID_DEVICE_FLAG_LAST
|
||||||
|
} FuHidDeviceFlags;
|
||||||
|
|
||||||
|
FuHidDevice *fu_hid_device_new (GUsbDevice *usb_device);
|
||||||
|
void fu_hid_device_set_interface (FuHidDevice *self,
|
||||||
|
guint8 interface);
|
||||||
|
guint8 fu_hid_device_get_interface (FuHidDevice *self);
|
||||||
|
gboolean fu_hid_device_set_report (FuHidDevice *self,
|
||||||
|
guint8 value,
|
||||||
|
guint8 *buf,
|
||||||
|
gsize bufsz,
|
||||||
|
guint timeout,
|
||||||
|
FuHidDeviceFlags flags,
|
||||||
|
GError **error);
|
||||||
|
gboolean fu_hid_device_get_report (FuHidDevice *self,
|
||||||
|
guint8 value,
|
||||||
|
guint8 *buf,
|
||||||
|
gsize bufsz,
|
||||||
|
guint timeout,
|
||||||
|
FuHidDeviceFlags flags,
|
||||||
|
GError **error);
|
@ -17,6 +17,7 @@
|
|||||||
#include "fu-quirks.h"
|
#include "fu-quirks.h"
|
||||||
#include "fu-hwids.h"
|
#include "fu-hwids.h"
|
||||||
#include "fu-usb-device.h"
|
#include "fu-usb-device.h"
|
||||||
|
//#include "fu-hid-device.h"
|
||||||
#ifdef HAVE_GUDEV
|
#ifdef HAVE_GUDEV
|
||||||
#include "fu-udev-device.h"
|
#include "fu-udev-device.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,16 +15,6 @@
|
|||||||
#define FU_TYPE_USB_DEVICE (fu_usb_device_get_type ())
|
#define FU_TYPE_USB_DEVICE (fu_usb_device_get_type ())
|
||||||
G_DECLARE_DERIVABLE_TYPE (FuUsbDevice, fu_usb_device, FU, USB_DEVICE, FuDevice)
|
G_DECLARE_DERIVABLE_TYPE (FuUsbDevice, fu_usb_device, FU, USB_DEVICE, FuDevice)
|
||||||
|
|
||||||
/* HID */
|
|
||||||
#define FU_HID_REPORT_GET 0x01
|
|
||||||
#define FU_HID_REPORT_SET 0x09
|
|
||||||
|
|
||||||
#define FU_HID_REPORT_TYPE_INPUT 0x01
|
|
||||||
#define FU_HID_REPORT_TYPE_OUTPUT 0x02
|
|
||||||
#define FU_HID_REPORT_TYPE_FEATURE 0x03
|
|
||||||
|
|
||||||
#define FU_HID_FEATURE 0x0300
|
|
||||||
|
|
||||||
struct _FuUsbDeviceClass
|
struct _FuUsbDeviceClass
|
||||||
{
|
{
|
||||||
FuDeviceClass parent_class;
|
FuDeviceClass parent_class;
|
||||||
|
@ -556,6 +556,12 @@ LIBFWUPDPLUGIN_1.4.0 {
|
|||||||
fu_efivar_secure_boot_enabled;
|
fu_efivar_secure_boot_enabled;
|
||||||
fu_efivar_set_data;
|
fu_efivar_set_data;
|
||||||
fu_efivar_supported;
|
fu_efivar_supported;
|
||||||
|
fu_hid_device_get_interface;
|
||||||
|
fu_hid_device_get_report;
|
||||||
|
fu_hid_device_get_type;
|
||||||
|
fu_hid_device_new;
|
||||||
|
fu_hid_device_set_interface;
|
||||||
|
fu_hid_device_set_report;
|
||||||
fu_plugin_get_config_value_boolean;
|
fu_plugin_get_config_value_boolean;
|
||||||
fu_plugin_runner_device_created;
|
fu_plugin_runner_device_created;
|
||||||
local: *;
|
local: *;
|
||||||
|
@ -22,6 +22,7 @@ fwupdplugin_src = [
|
|||||||
'fu-efivar.c',
|
'fu-efivar.c',
|
||||||
'fu-udev-device.c',
|
'fu-udev-device.c',
|
||||||
'fu-usb-device.c',
|
'fu-usb-device.c',
|
||||||
|
'fu-hid-device.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
fwupdplugin_headers = [
|
fwupdplugin_headers = [
|
||||||
@ -49,6 +50,7 @@ fwupdplugin_headers = [
|
|||||||
'fu-efivar.h',
|
'fu-efivar.h',
|
||||||
'fu-udev-device.h',
|
'fu-udev-device.h',
|
||||||
'fu-usb-device.h',
|
'fu-usb-device.h',
|
||||||
|
'fu-hid-device.h',
|
||||||
]
|
]
|
||||||
install_headers(
|
install_headers(
|
||||||
'fwupdplugin.h',
|
'fwupdplugin.h',
|
||||||
|
@ -32,13 +32,13 @@ typedef enum {
|
|||||||
|
|
||||||
struct _FuCsrDevice
|
struct _FuCsrDevice
|
||||||
{
|
{
|
||||||
FuUsbDevice parent_instance;
|
FuHidDevice parent_instance;
|
||||||
FuCsrDeviceQuirks quirks;
|
FuCsrDeviceQuirks quirks;
|
||||||
DfuState dfu_state;
|
DfuState dfu_state;
|
||||||
guint32 dnload_timeout;
|
guint32 dnload_timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (FuCsrDevice, fu_csr_device, FU_TYPE_USB_DEVICE)
|
G_DEFINE_TYPE (FuCsrDevice, fu_csr_device, FU_TYPE_HID_DEVICE)
|
||||||
|
|
||||||
#define FU_CSR_REPORT_ID_COMMAND 0x01
|
#define FU_CSR_REPORT_ID_COMMAND 0x01
|
||||||
#define FU_CSR_REPORT_ID_STATUS 0x02
|
#define FU_CSR_REPORT_ID_STATUS 0x02
|
||||||
@ -69,73 +69,36 @@ fu_csr_device_to_string (FuDevice *device, guint idt, GString *str)
|
|||||||
static gboolean
|
static gboolean
|
||||||
fu_csr_device_attach (FuDevice *device, GError **error)
|
fu_csr_device_attach (FuDevice *device, GError **error)
|
||||||
{
|
{
|
||||||
FuCsrDevice *self = FU_CSR_DEVICE (device);
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
gsize sz = 0;
|
|
||||||
guint8 buf[] = { FU_CSR_REPORT_ID_CONTROL, FU_CSR_CONTROL_RESET };
|
guint8 buf[] = { FU_CSR_REPORT_ID_CONTROL, FU_CSR_CONTROL_RESET };
|
||||||
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (device),
|
||||||
if (g_getenv ("FWUPD_CSR_VERBOSE") != NULL)
|
FU_CSR_REPORT_ID_CONTROL,
|
||||||
fu_common_dump_raw (G_LOG_DOMAIN, "Reset", buf, sz);
|
buf, sizeof(buf),
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
FU_CSR_DEVICE_TIMEOUT,
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
error)) {
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
g_prefix_error (error, "failed to attach: ");
|
||||||
FU_HID_REPORT_SET, /* bRequest */
|
|
||||||
FU_HID_FEATURE | FU_CSR_REPORT_ID_CONTROL, /* wValue */
|
|
||||||
0x0000, /* wIndex */
|
|
||||||
buf, sizeof(buf), &sz,
|
|
||||||
FU_CSR_DEVICE_TIMEOUT, /* timeout */
|
|
||||||
NULL, error)) {
|
|
||||||
g_prefix_error (error, "Failed to ClearStatus: ");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check packet */
|
|
||||||
if (sz != FU_CSR_CONTROL_HEADER_SIZE) {
|
|
||||||
g_set_error (error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INTERNAL,
|
|
||||||
"Reset packet was %" G_GSIZE_FORMAT " expected %i",
|
|
||||||
sz, FU_CSR_CONTROL_HEADER_SIZE);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_csr_device_get_status (FuCsrDevice *self, GError **error)
|
fu_csr_device_get_status (FuCsrDevice *self, GError **error)
|
||||||
{
|
{
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
gsize sz = 0;
|
|
||||||
guint8 buf[64] = {0};
|
guint8 buf[64] = {0};
|
||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
if (!fu_hid_device_get_report (FU_HID_DEVICE (self),
|
||||||
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
|
FU_CSR_REPORT_ID_STATUS,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
buf, sizeof(buf),
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
FU_CSR_DEVICE_TIMEOUT,
|
||||||
FU_HID_REPORT_GET, /* bRequest */
|
FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||||
FU_HID_FEATURE | FU_CSR_REPORT_ID_STATUS, /* wValue */
|
error)) {
|
||||||
0x0000, /* wIndex */
|
g_prefix_error (error, "failed to GetStatus: ");
|
||||||
buf, sizeof(buf), &sz,
|
|
||||||
FU_CSR_DEVICE_TIMEOUT,
|
|
||||||
NULL, error)) {
|
|
||||||
g_prefix_error (error, "Failed to GetStatus: ");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (g_getenv ("FWUPD_CSR_VERBOSE") != NULL)
|
|
||||||
fu_common_dump_raw (G_LOG_DOMAIN, "GetStatus", buf, sz);
|
|
||||||
|
|
||||||
/* check packet */
|
/* check packet */
|
||||||
if (sz != FU_CSR_STATUS_HEADER_SIZE) {
|
|
||||||
g_set_error (error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INTERNAL,
|
|
||||||
"GetStatus packet was %" G_GSIZE_FORMAT " expected %i",
|
|
||||||
sz, FU_CSR_STATUS_HEADER_SIZE);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (buf[0] != FU_CSR_REPORT_ID_STATUS) {
|
if (buf[0] != FU_CSR_REPORT_ID_STATUS) {
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
FWUPD_ERROR,
|
FWUPD_ERROR,
|
||||||
@ -157,8 +120,6 @@ fu_csr_device_get_status (FuCsrDevice *self, GError **error)
|
|||||||
static gboolean
|
static gboolean
|
||||||
fu_csr_device_clear_status (FuCsrDevice *self, GError **error)
|
fu_csr_device_clear_status (FuCsrDevice *self, GError **error)
|
||||||
{
|
{
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
gsize sz = 0;
|
|
||||||
guint8 buf[] = { FU_CSR_REPORT_ID_CONTROL,
|
guint8 buf[] = { FU_CSR_REPORT_ID_CONTROL,
|
||||||
FU_CSR_CONTROL_CLEAR_STATUS };
|
FU_CSR_CONTROL_CLEAR_STATUS };
|
||||||
|
|
||||||
@ -169,29 +130,13 @@ fu_csr_device_clear_status (FuCsrDevice *self, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
if (g_getenv ("FWUPD_CSR_VERBOSE") != NULL)
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (self),
|
||||||
fu_common_dump_raw (G_LOG_DOMAIN, "ClearStatus", buf, sz);
|
FU_CSR_REPORT_ID_CONTROL,
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
buf, sizeof(buf),
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
FU_CSR_DEVICE_TIMEOUT,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
error)) {
|
||||||
FU_HID_REPORT_SET, /* bRequest */
|
g_prefix_error (error, "failed to ClearStatus: ");
|
||||||
FU_HID_FEATURE | FU_CSR_REPORT_ID_CONTROL, /* wValue */
|
|
||||||
0x0000, /* wIndex */
|
|
||||||
buf, sizeof(buf), &sz,
|
|
||||||
FU_CSR_DEVICE_TIMEOUT,
|
|
||||||
NULL, error)) {
|
|
||||||
g_prefix_error (error, "Failed to ClearStatus: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check packet */
|
|
||||||
if (sz != FU_CSR_CONTROL_HEADER_SIZE) {
|
|
||||||
g_set_error (error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INTERNAL,
|
|
||||||
"ClearStatus packet was %" G_GSIZE_FORMAT " expected %i",
|
|
||||||
sz, FU_CSR_CONTROL_HEADER_SIZE);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,35 +147,17 @@ fu_csr_device_clear_status (FuCsrDevice *self, GError **error)
|
|||||||
static GBytes *
|
static GBytes *
|
||||||
fu_csr_device_upload_chunk (FuCsrDevice *self, GError **error)
|
fu_csr_device_upload_chunk (FuCsrDevice *self, GError **error)
|
||||||
{
|
{
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
gsize sz = 0;
|
|
||||||
guint16 data_sz;
|
guint16 data_sz;
|
||||||
guint8 buf[64] = {0};
|
guint8 buf[64] = {0};
|
||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
if (!fu_hid_device_get_report (FU_HID_DEVICE (self),
|
||||||
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
|
FU_CSR_REPORT_ID_COMMAND,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
buf, sizeof(buf),
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
FU_CSR_DEVICE_TIMEOUT,
|
||||||
FU_HID_REPORT_GET, /* bRequest */
|
FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||||
FU_HID_FEATURE | FU_CSR_REPORT_ID_COMMAND, /* wValue */
|
error)) {
|
||||||
0x0000, /* wIndex */
|
g_prefix_error (error, "failed to ReadFirmware: ");
|
||||||
buf, sizeof(buf), &sz,
|
|
||||||
FU_CSR_DEVICE_TIMEOUT,
|
|
||||||
NULL, error)) {
|
|
||||||
g_prefix_error (error, "Failed to ReadFirmware: ");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (g_getenv ("FWUPD_CSR_VERBOSE") != NULL)
|
|
||||||
fu_common_dump_raw (G_LOG_DOMAIN, "ReadFirmware", buf, sz);
|
|
||||||
|
|
||||||
/* too small to parse */
|
|
||||||
if (sz < FU_CSR_COMMAND_HEADER_SIZE) {
|
|
||||||
g_set_error (error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INTERNAL,
|
|
||||||
"ReadFirmware packet too small, got %" G_GSIZE_FORMAT,
|
|
||||||
sz);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +172,7 @@ fu_csr_device_upload_chunk (FuCsrDevice *self, GError **error)
|
|||||||
|
|
||||||
/* check the length */
|
/* check the length */
|
||||||
data_sz = fu_common_read_uint16 (&buf[1], G_LITTLE_ENDIAN);
|
data_sz = fu_common_read_uint16 (&buf[1], G_LITTLE_ENDIAN);
|
||||||
if (data_sz + FU_CSR_COMMAND_HEADER_SIZE != (guint16) sz) {
|
if (data_sz + FU_CSR_COMMAND_HEADER_SIZE != (guint16) sizeof(buf)) {
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
FWUPD_ERROR,
|
FWUPD_ERROR,
|
||||||
FWUPD_ERROR_INTERNAL,
|
FWUPD_ERROR_INTERNAL,
|
||||||
@ -256,7 +183,7 @@ fu_csr_device_upload_chunk (FuCsrDevice *self, GError **error)
|
|||||||
|
|
||||||
/* return as bytes */
|
/* return as bytes */
|
||||||
return g_bytes_new (buf + FU_CSR_COMMAND_HEADER_SIZE,
|
return g_bytes_new (buf + FU_CSR_COMMAND_HEADER_SIZE,
|
||||||
sz - FU_CSR_COMMAND_HEADER_SIZE);
|
sizeof(buf) - FU_CSR_COMMAND_HEADER_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FuFirmware *
|
static FuFirmware *
|
||||||
@ -331,10 +258,8 @@ fu_csr_device_upload (FuDevice *device, GError **error)
|
|||||||
static gboolean
|
static gboolean
|
||||||
fu_csr_device_download_chunk (FuCsrDevice *self, guint16 idx, GBytes *chunk, GError **error)
|
fu_csr_device_download_chunk (FuCsrDevice *self, guint16 idx, GBytes *chunk, GError **error)
|
||||||
{
|
{
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
const guint8 *chunk_data;
|
const guint8 *chunk_data;
|
||||||
gsize chunk_sz = 0;
|
gsize chunk_sz = 0;
|
||||||
gsize write_sz = 0;
|
|
||||||
guint8 buf[FU_CSR_PACKET_DATA_SIZE] = {0};
|
guint8 buf[FU_CSR_PACKET_DATA_SIZE] = {0};
|
||||||
|
|
||||||
/* too large? */
|
/* too large? */
|
||||||
@ -359,32 +284,13 @@ fu_csr_device_download_chunk (FuCsrDevice *self, guint16 idx, GBytes *chunk, GEr
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
if (g_getenv ("FWUPD_CSR_VERBOSE") != NULL)
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (self),
|
||||||
fu_common_dump_raw (G_LOG_DOMAIN, "Upgrade", buf, sizeof(buf));
|
FU_CSR_REPORT_ID_COMMAND,
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
buf, sizeof(buf),
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
FU_CSR_DEVICE_TIMEOUT,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
error)) {
|
||||||
FU_HID_REPORT_SET, /* bRequest */
|
g_prefix_error (error, "failed to Upgrade: ");
|
||||||
FU_HID_FEATURE | FU_CSR_REPORT_ID_COMMAND, /* wValue */
|
|
||||||
0x0000, /* wIndex */
|
|
||||||
buf,
|
|
||||||
sizeof(buf),
|
|
||||||
&write_sz,
|
|
||||||
FU_CSR_DEVICE_TIMEOUT,
|
|
||||||
NULL, error)) {
|
|
||||||
g_prefix_error (error, "Failed to Upgrade: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check packet */
|
|
||||||
if (write_sz != sizeof(buf)) {
|
|
||||||
g_set_error (error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INTERNAL,
|
|
||||||
"Not all packet written for upgrade got "
|
|
||||||
"%" G_GSIZE_FORMAT " expected %" G_GSIZE_FORMAT,
|
|
||||||
write_sz, sizeof(buf));
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,23 +407,6 @@ fu_csr_device_probe (FuUsbDevice *device, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_csr_device_open (FuUsbDevice *device, GError **error)
|
|
||||||
{
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (device);
|
|
||||||
|
|
||||||
/* open device and clear status */
|
|
||||||
if (!g_usb_device_claim_interface (usb_device, 0x00, /* HID */
|
|
||||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
|
||||||
error)) {
|
|
||||||
g_prefix_error (error, "failed to claim HID interface: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_csr_device_setup (FuDevice *device, GError **error)
|
fu_csr_device_setup (FuDevice *device, GError **error)
|
||||||
{
|
{
|
||||||
@ -530,23 +419,6 @@ fu_csr_device_setup (FuDevice *device, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_csr_device_close (FuUsbDevice *device, GError **error)
|
|
||||||
{
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (device);
|
|
||||||
|
|
||||||
/* we're done here */
|
|
||||||
if (!g_usb_device_release_interface (usb_device, 0x00, /* HID */
|
|
||||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
|
||||||
error)) {
|
|
||||||
g_prefix_error (error, "failed to release interface: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fu_csr_device_init (FuCsrDevice *self)
|
fu_csr_device_init (FuCsrDevice *self)
|
||||||
{
|
{
|
||||||
@ -564,7 +436,5 @@ fu_csr_device_class_init (FuCsrDeviceClass *klass)
|
|||||||
klass_device->prepare_firmware = fu_csr_device_prepare_firmware;
|
klass_device->prepare_firmware = fu_csr_device_prepare_firmware;
|
||||||
klass_device->attach = fu_csr_device_attach;
|
klass_device->attach = fu_csr_device_attach;
|
||||||
klass_device->setup = fu_csr_device_setup;
|
klass_device->setup = fu_csr_device_setup;
|
||||||
klass_usb_device->open = fu_csr_device_open;
|
|
||||||
klass_usb_device->close = fu_csr_device_close;
|
|
||||||
klass_usb_device->probe = fu_csr_device_probe;
|
klass_usb_device->probe = fu_csr_device_probe;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "fu-hid-device.h"
|
||||||
#include "fu-plugin.h"
|
#include "fu-plugin.h"
|
||||||
|
|
||||||
#define FU_TYPE_CSR_DEVICE (fu_csr_device_get_type ())
|
#define FU_TYPE_CSR_DEVICE (fu_csr_device_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (FuCsrDevice, fu_csr_device, FU, CSR_DEVICE, FuUsbDevice)
|
G_DECLARE_FINAL_TYPE (FuCsrDevice, fu_csr_device, FU, CSR_DEVICE, FuHidDevice)
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "fu-usb-device.h"
|
#include "fu-hid-device.h"
|
||||||
#include "fwupd-error.h"
|
#include "fwupd-error.h"
|
||||||
|
|
||||||
#include "fu-dell-dock-hid.h"
|
#include "fu-dell-dock-hid.h"
|
||||||
@ -81,17 +81,14 @@ fu_dell_dock_hid_set_report (FuDevice *self,
|
|||||||
guint8 *outbuffer,
|
guint8 *outbuffer,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
gsize actual_len = 0;
|
|
||||||
for (gint i = 1; i <= HID_MAX_RETRIES; i++) {
|
for (gint i = 1; i <= HID_MAX_RETRIES; i++) {
|
||||||
g_autoptr(GError) error_local = NULL;
|
g_autoptr(GError) error_local = NULL;
|
||||||
ret = g_usb_device_control_transfer (
|
ret = fu_hid_device_set_report (FU_HID_DEVICE (self), 0x0,
|
||||||
usb_device, G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
outbuffer, 192,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
HIDI2C_TRANSACTION_TIMEOUT,
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE, FU_HID_REPORT_SET, 0x0200,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
0x0000, outbuffer, 192, &actual_len,
|
&error_local);
|
||||||
HIDI2C_TRANSACTION_TIMEOUT, NULL, &error_local);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
if (i == HID_MAX_RETRIES ||
|
if (i == HID_MAX_RETRIES ||
|
||||||
@ -107,11 +104,6 @@ fu_dell_dock_hid_set_report (FuDevice *self,
|
|||||||
g_usleep (G_USEC_PER_SEC);
|
g_usleep (G_USEC_PER_SEC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (actual_len != 192) {
|
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
|
||||||
"only wrote %" G_GSIZE_FORMAT "bytes", actual_len);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -121,17 +113,14 @@ fu_dell_dock_hid_get_report (FuDevice *self,
|
|||||||
guint8 *inbuffer,
|
guint8 *inbuffer,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
gsize actual_len = 0;
|
|
||||||
for (gint i = 1; i <= HID_MAX_RETRIES; i++) {
|
for (gint i = 1; i <= HID_MAX_RETRIES; i++) {
|
||||||
g_autoptr(GError) error_local = NULL;
|
g_autoptr(GError) error_local = NULL;
|
||||||
ret = g_usb_device_control_transfer (
|
ret = fu_hid_device_get_report (FU_HID_DEVICE (self), 0x0,
|
||||||
usb_device, G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
|
inbuffer, 192,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
HIDI2C_TRANSACTION_TIMEOUT,
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE, FU_HID_REPORT_GET, 0x0100,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
0x0000, inbuffer, 192, &actual_len,
|
&error_local);
|
||||||
HIDI2C_TRANSACTION_TIMEOUT, NULL, &error_local);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
if (i == HID_MAX_RETRIES ||
|
if (i == HID_MAX_RETRIES ||
|
||||||
@ -146,11 +135,6 @@ fu_dell_dock_hid_get_report (FuDevice *self,
|
|||||||
error_local->message);
|
error_local->message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (actual_len != 192) {
|
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
|
||||||
"only read %" G_GSIZE_FORMAT "bytes", actual_len);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,13 @@
|
|||||||
#include "fu-dell-dock-common.h"
|
#include "fu-dell-dock-common.h"
|
||||||
|
|
||||||
struct _FuDellDockHub {
|
struct _FuDellDockHub {
|
||||||
FuUsbDevice parent_instance;
|
FuHidDevice parent_instance;
|
||||||
guint8 unlock_target;
|
guint8 unlock_target;
|
||||||
guint64 blob_major_offset;
|
guint64 blob_major_offset;
|
||||||
guint64 blob_minor_offset;
|
guint64 blob_minor_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (FuDellDockHub, fu_dell_dock_hub, FU_TYPE_USB_DEVICE)
|
G_DEFINE_TYPE (FuDellDockHub, fu_dell_dock_hub, FU_TYPE_HID_DEVICE)
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_dell_dock_hub_probe (FuDevice *device, GError **error)
|
fu_dell_dock_hub_probe (FuDevice *device, GError **error)
|
||||||
@ -155,37 +155,6 @@ fu_dell_dock_hub_set_quirk_kv (FuDevice *device,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_dell_dock_hub_open (FuUsbDevice *fu_usb_device, GError **error)
|
|
||||||
{
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (fu_usb_device);
|
|
||||||
|
|
||||||
/* open device and clear status */
|
|
||||||
if (!g_usb_device_claim_interface (
|
|
||||||
usb_device, 0, /* HID */
|
|
||||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER, error)) {
|
|
||||||
g_prefix_error (error, "failed to claim HID interface: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_dell_dock_hub_close (FuUsbDevice *fu_usb_device, GError **error)
|
|
||||||
{
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (fu_usb_device);
|
|
||||||
|
|
||||||
if (!g_usb_device_release_interface (
|
|
||||||
usb_device, 0, /* HID */
|
|
||||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER, error)) {
|
|
||||||
g_prefix_error (error, "failed to release interface: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fu_dell_dock_hub_finalize (GObject *object)
|
fu_dell_dock_hub_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
@ -202,10 +171,7 @@ fu_dell_dock_hub_class_init (FuDellDockHubClass *klass)
|
|||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
|
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
|
||||||
FuUsbDeviceClass *klass_usb_device = FU_USB_DEVICE_CLASS (klass);
|
|
||||||
object_class->finalize = fu_dell_dock_hub_finalize;
|
object_class->finalize = fu_dell_dock_hub_finalize;
|
||||||
klass_usb_device->open = fu_dell_dock_hub_open;
|
|
||||||
klass_usb_device->close = fu_dell_dock_hub_close;
|
|
||||||
klass_device->setup = fu_dell_dock_hid_get_hub_version;
|
klass_device->setup = fu_dell_dock_hid_get_hub_version;
|
||||||
klass_device->probe = fu_dell_dock_hub_probe;
|
klass_device->probe = fu_dell_dock_hub_probe;
|
||||||
klass_device->write_firmware = fu_dell_dock_hub_write_fw;
|
klass_device->write_firmware = fu_dell_dock_hub_write_fw;
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "fu-usb-device.h"
|
#include "fu-hid-device.h"
|
||||||
|
|
||||||
#define FU_TYPE_DELL_DOCK_HUB (fu_dell_dock_hub_get_type ())
|
#define FU_TYPE_DELL_DOCK_HUB (fu_dell_dock_hub_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (FuDellDockHub, fu_dell_dock_hub, FU, DELL_DOCK_HUB, FuUsbDevice)
|
G_DECLARE_FINAL_TYPE (FuDellDockHub, fu_dell_dock_hub, FU, DELL_DOCK_HUB, FuHidDevice)
|
||||||
|
|
||||||
FuDellDockHub *fu_dell_dock_hub_new (FuUsbDevice *device);
|
FuDellDockHub *fu_dell_dock_hub_new (FuUsbDevice *device);
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "fu-firmware-common.h"
|
#include "fu-firmware-common.h"
|
||||||
|
#include "fu-hid-device.h"
|
||||||
#include "fu-logitech-hidpp-common.h"
|
#include "fu-logitech-hidpp-common.h"
|
||||||
#include "fu-logitech-hidpp-bootloader.h"
|
#include "fu-logitech-hidpp-bootloader.h"
|
||||||
#include "fu-logitech-hidpp-hidpp.h"
|
#include "fu-logitech-hidpp-hidpp.h"
|
||||||
@ -23,7 +24,7 @@ typedef struct
|
|||||||
#define FU_UNIFYING_DEVICE_EP1 0x81
|
#define FU_UNIFYING_DEVICE_EP1 0x81
|
||||||
#define FU_UNIFYING_DEVICE_EP3 0x83
|
#define FU_UNIFYING_DEVICE_EP3 0x83
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (FuLogitechHidPpBootloader, fu_logitech_hidpp_bootloader, FU_TYPE_USB_DEVICE)
|
G_DEFINE_TYPE_WITH_PRIVATE (FuLogitechHidPpBootloader, fu_logitech_hidpp_bootloader, FU_TYPE_HID_DEVICE)
|
||||||
|
|
||||||
#define GET_PRIVATE(o) (fu_logitech_hidpp_bootloader_get_instance_private (o))
|
#define GET_PRIVATE(o) (fu_logitech_hidpp_bootloader_get_instance_private (o))
|
||||||
|
|
||||||
@ -342,18 +343,11 @@ fu_logitech_hidpp_bootloader_request (FuLogitechHidPpBootloader *self,
|
|||||||
buf_request, sizeof (buf_request));
|
buf_request, sizeof (buf_request));
|
||||||
}
|
}
|
||||||
if (usb_device != NULL) {
|
if (usb_device != NULL) {
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (self), 0x0,
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
buf_request, sizeof(buf_request),
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
FU_UNIFYING_DEVICE_TIMEOUT_MS,
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
FU_HID_REPORT_SET,
|
error)) {
|
||||||
0x0200, 0x0000,
|
|
||||||
buf_request,
|
|
||||||
sizeof (buf_request),
|
|
||||||
&actual_length,
|
|
||||||
FU_UNIFYING_DEVICE_TIMEOUT_MS,
|
|
||||||
NULL,
|
|
||||||
error)) {
|
|
||||||
g_prefix_error (error, "failed to send data: ");
|
g_prefix_error (error, "failed to send data: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -6,14 +6,14 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fu-usb-device.h"
|
#include "fu-hid-device.h"
|
||||||
|
|
||||||
#define FU_TYPE_UNIFYING_BOOTLOADER (fu_logitech_hidpp_bootloader_get_type ())
|
#define FU_TYPE_UNIFYING_BOOTLOADER (fu_logitech_hidpp_bootloader_get_type ())
|
||||||
G_DECLARE_DERIVABLE_TYPE (FuLogitechHidPpBootloader, fu_logitech_hidpp_bootloader, FU, UNIFYING_BOOTLOADER, FuUsbDevice)
|
G_DECLARE_DERIVABLE_TYPE (FuLogitechHidPpBootloader, fu_logitech_hidpp_bootloader, FU, UNIFYING_BOOTLOADER, FuHidDevice)
|
||||||
|
|
||||||
struct _FuLogitechHidPpBootloaderClass
|
struct _FuLogitechHidPpBootloaderClass
|
||||||
{
|
{
|
||||||
FuUsbDeviceClass parent_class;
|
FuHidDeviceClass parent_class;
|
||||||
gboolean (*setup) (FuLogitechHidPpBootloader *self,
|
gboolean (*setup) (FuLogitechHidPpBootloader *self,
|
||||||
GError **error);
|
GError **error);
|
||||||
};
|
};
|
||||||
|
@ -13,14 +13,12 @@
|
|||||||
#include "fu-rts54hid-device.h"
|
#include "fu-rts54hid-device.h"
|
||||||
|
|
||||||
struct _FuRts54HidDevice {
|
struct _FuRts54HidDevice {
|
||||||
FuUsbDevice parent_instance;
|
FuHidDevice parent_instance;
|
||||||
gboolean fw_auth;
|
gboolean fw_auth;
|
||||||
gboolean dual_bank;
|
gboolean dual_bank;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (FuRts54HidDevice, fu_rts54hid_device, FU_TYPE_USB_DEVICE)
|
G_DEFINE_TYPE (FuRts54HidDevice, fu_rts54hid_device, FU_TYPE_HID_DEVICE)
|
||||||
|
|
||||||
#define FU_RTS54HID_DEVICE_TIMEOUT 1000 /* ms */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fu_rts54hid_device_to_string (FuDevice *device, guint idt, GString *str)
|
fu_rts54hid_device_to_string (FuDevice *device, guint idt, GString *str)
|
||||||
@ -30,62 +28,6 @@ fu_rts54hid_device_to_string (FuDevice *device, guint idt, GString *str)
|
|||||||
fu_common_string_append_kb (str, idt, "DualBank", self->dual_bank);
|
fu_common_string_append_kb (str, idt, "DualBank", self->dual_bank);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
|
||||||
fu_rts54hid_device_set_report (FuRts54HidDevice *self,
|
|
||||||
guint8 *buf, gsize buf_sz,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
gsize actual_len = 0;
|
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
|
||||||
FU_HID_REPORT_SET,
|
|
||||||
0x0200, 0x0000,
|
|
||||||
buf, buf_sz,
|
|
||||||
&actual_len,
|
|
||||||
FU_RTS54HID_DEVICE_TIMEOUT * 2,
|
|
||||||
NULL, error)) {
|
|
||||||
g_prefix_error (error, "failed to SetReport: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (actual_len != buf_sz) {
|
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
|
||||||
"only wrote %" G_GSIZE_FORMAT "bytes", actual_len);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
|
||||||
fu_rts54hid_device_get_report (FuRts54HidDevice *self,
|
|
||||||
guint8 *buf, gsize buf_sz,
|
|
||||||
GError **error)
|
|
||||||
{
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
gsize actual_len = 0;
|
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
|
||||||
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
|
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
|
||||||
FU_HID_REPORT_GET,
|
|
||||||
0x0100, 0x0000,
|
|
||||||
buf, buf_sz,
|
|
||||||
&actual_len, /* actual length */
|
|
||||||
FU_RTS54HID_DEVICE_TIMEOUT,
|
|
||||||
NULL, error)) {
|
|
||||||
g_prefix_error (error, "failed to GetReport: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (actual_len != buf_sz) {
|
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
|
||||||
"only read %" G_GSIZE_FORMAT "bytes", actual_len);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_rts54hid_device_set_clock_mode (FuRts54HidDevice *self, gboolean enable, GError **error)
|
fu_rts54hid_device_set_clock_mode (FuRts54HidDevice *self, gboolean enable, GError **error)
|
||||||
{
|
{
|
||||||
@ -101,7 +43,10 @@ fu_rts54hid_device_set_clock_mode (FuRts54HidDevice *self, gboolean enable, GErr
|
|||||||
};
|
};
|
||||||
guint8 buf[FU_RTS54FU_HID_REPORT_LENGTH] = { 0 };
|
guint8 buf[FU_RTS54FU_HID_REPORT_LENGTH] = { 0 };
|
||||||
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
||||||
if (!fu_rts54hid_device_set_report (self, buf, sizeof(buf), error)) {
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (self), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT * 2,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error)) {
|
||||||
g_prefix_error (error, "failed to set clock-mode=%i: ", enable);
|
g_prefix_error (error, "failed to set clock-mode=%i: ", enable);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -120,7 +65,10 @@ fu_rts54hid_device_reset_to_flash (FuRts54HidDevice *self, GError **error)
|
|||||||
};
|
};
|
||||||
guint8 buf[FU_RTS54FU_HID_REPORT_LENGTH] = { 0 };
|
guint8 buf[FU_RTS54FU_HID_REPORT_LENGTH] = { 0 };
|
||||||
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
||||||
if (!fu_rts54hid_device_set_report (self, buf, sizeof(buf), error)) {
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (self), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT * 2,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error)) {
|
||||||
g_prefix_error (error, "failed to soft reset: ");
|
g_prefix_error (error, "failed to soft reset: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -152,7 +100,10 @@ fu_rts54hid_device_write_flash (FuRts54HidDevice *self,
|
|||||||
data, data_sz, 0x0, /* src */
|
data, data_sz, 0x0, /* src */
|
||||||
data_sz, error))
|
data_sz, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (!fu_rts54hid_device_set_report (self, buf, sizeof(buf), error)) {
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (self), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT * 2,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error)) {
|
||||||
g_prefix_error (error, "failed to write flash @%08x: ", (guint) addr);
|
g_prefix_error (error, "failed to write flash @%08x: ", (guint) addr);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -176,10 +127,16 @@ fu_rts54hid_device_verify_update_fw (FuRts54HidDevice *self, GError **error)
|
|||||||
|
|
||||||
/* set then get */
|
/* set then get */
|
||||||
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
||||||
if (!fu_rts54hid_device_set_report (self, buf, sizeof(buf), error))
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (self), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT * 2,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
g_usleep (4 * G_USEC_PER_SEC);
|
g_usleep (4 * G_USEC_PER_SEC);
|
||||||
if (!fu_rts54hid_device_get_report (self, buf, sizeof(buf), error))
|
if (!fu_hid_device_get_report (FU_HID_DEVICE (self), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* check device status */
|
/* check device status */
|
||||||
@ -210,7 +167,10 @@ fu_rts54hid_device_erase_spare_bank (FuRts54HidDevice *self, GError **error)
|
|||||||
};
|
};
|
||||||
guint8 buf[FU_RTS54FU_HID_REPORT_LENGTH] = { 0 };
|
guint8 buf[FU_RTS54FU_HID_REPORT_LENGTH] = { 0 };
|
||||||
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
||||||
if (!fu_rts54hid_device_set_report (self, buf, sizeof(buf), error)) {
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (self), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT * 2,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error)) {
|
||||||
g_prefix_error (error, "failed to erase spare bank: ");
|
g_prefix_error (error, "failed to erase spare bank: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -235,9 +195,15 @@ fu_rts54hid_device_ensure_status (FuRts54HidDevice *self, GError **error)
|
|||||||
|
|
||||||
/* set then get */
|
/* set then get */
|
||||||
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
||||||
if (!fu_rts54hid_device_set_report (self, buf, sizeof(buf), error))
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (self), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT * 2,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (!fu_rts54hid_device_get_report (self, buf, sizeof(buf), error))
|
if (!fu_hid_device_get_report (FU_HID_DEVICE (self), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* check the hardware capabilities */
|
/* check the hardware capabilities */
|
||||||
@ -250,25 +216,6 @@ fu_rts54hid_device_ensure_status (FuRts54HidDevice *self, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_rts54hid_device_open (FuUsbDevice *device, GError **error)
|
|
||||||
{
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (device);
|
|
||||||
|
|
||||||
/* disconnect, set config, reattach kernel driver */
|
|
||||||
if (!g_usb_device_set_configuration (usb_device, 0x00, error))
|
|
||||||
return FALSE;
|
|
||||||
if (!g_usb_device_claim_interface (usb_device, 0x00, /* HID */
|
|
||||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
|
||||||
error)) {
|
|
||||||
g_prefix_error (error, "failed to claim interface: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_rts54hid_device_setup (FuDevice *device, GError **error)
|
fu_rts54hid_device_setup (FuDevice *device, GError **error)
|
||||||
{
|
{
|
||||||
@ -294,25 +241,12 @@ fu_rts54hid_device_setup (FuDevice *device, GError **error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_rts54hid_device_close (FuUsbDevice *device, GError **error)
|
fu_rts54hid_device_close (FuHidDevice *device, GError **error)
|
||||||
{
|
{
|
||||||
FuRts54HidDevice *self = FU_RTS54HID_DEVICE (device);
|
FuRts54HidDevice *self = FU_RTS54HID_DEVICE (device);
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (device);
|
|
||||||
|
|
||||||
/* set MCU to normal clock rate */
|
/* set MCU to normal clock rate */
|
||||||
if (!fu_rts54hid_device_set_clock_mode (self, FALSE, error))
|
return fu_rts54hid_device_set_clock_mode (self, FALSE, error);
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* we're done here */
|
|
||||||
if (!g_usb_device_release_interface (usb_device, 0x00, /* HID */
|
|
||||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
|
||||||
error)) {
|
|
||||||
g_prefix_error (error, "failed to release interface: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -385,10 +319,9 @@ static void
|
|||||||
fu_rts54hid_device_class_init (FuRts54HidDeviceClass *klass)
|
fu_rts54hid_device_class_init (FuRts54HidDeviceClass *klass)
|
||||||
{
|
{
|
||||||
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
|
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
|
||||||
FuUsbDeviceClass *klass_usb_device = FU_USB_DEVICE_CLASS (klass);
|
FuHidDeviceClass *klass_hid_device = FU_HID_DEVICE_CLASS (klass);
|
||||||
klass_device->write_firmware = fu_rts54hid_device_write_firmware;
|
klass_device->write_firmware = fu_rts54hid_device_write_firmware;
|
||||||
klass_device->to_string = fu_rts54hid_device_to_string;
|
klass_device->to_string = fu_rts54hid_device_to_string;
|
||||||
klass_device->setup = fu_rts54hid_device_setup;
|
klass_device->setup = fu_rts54hid_device_setup;
|
||||||
klass_usb_device->open = fu_rts54hid_device_open;
|
klass_hid_device->close = fu_rts54hid_device_close;
|
||||||
klass_usb_device->close = fu_rts54hid_device_close;
|
|
||||||
}
|
}
|
||||||
|
@ -6,16 +6,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fu-plugin.h"
|
#include "fu-hid-device.h"
|
||||||
|
|
||||||
#define FU_TYPE_RTS54HID_DEVICE (fu_rts54hid_device_get_type ())
|
#define FU_TYPE_RTS54HID_DEVICE (fu_rts54hid_device_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (FuRts54HidDevice, fu_rts54hid_device, FU, RTS54HID_DEVICE, FuUsbDevice)
|
G_DECLARE_FINAL_TYPE (FuRts54HidDevice, fu_rts54hid_device, FU, RTS54HID_DEVICE, FuHidDevice)
|
||||||
|
|
||||||
gboolean fu_rts54hid_device_set_report (FuRts54HidDevice *self,
|
#define FU_RTS54HID_DEVICE_TIMEOUT 1000 /* ms */
|
||||||
guint8 *buf,
|
|
||||||
gsize buf_sz,
|
|
||||||
GError **error);
|
|
||||||
gboolean fu_rts54hid_device_get_report (FuRts54HidDevice *self,
|
|
||||||
guint8 *buf,
|
|
||||||
gsize buf_sz,
|
|
||||||
GError **error);
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "fu-chunk.h"
|
#include "fu-chunk.h"
|
||||||
|
#include "fu-hid-device.h"
|
||||||
|
|
||||||
#include "fu-rts54hid-common.h"
|
#include "fu-rts54hid-common.h"
|
||||||
#include "fu-rts54hid-module.h"
|
#include "fu-rts54hid-module.h"
|
||||||
#include "fu-rts54hid-device.h"
|
#include "fu-rts54hid-device.h"
|
||||||
@ -77,7 +79,10 @@ fu_rts54hid_module_i2c_write (FuRts54HidModule *self,
|
|||||||
data, data_sz, 0x0, /* src */
|
data, data_sz, 0x0, /* src */
|
||||||
data_sz, error))
|
data_sz, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
if (!fu_rts54hid_device_set_report (parent, buf, sizeof(buf), error)) {
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (parent), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT * 2,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error)) {
|
||||||
g_prefix_error (error, "failed to write i2c @%04x: ", self->slave_addr);
|
g_prefix_error (error, "failed to write i2c @%04x: ", self->slave_addr);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -114,11 +119,17 @@ fu_rts54hid_module_i2c_read (FuRts54HidModule *self,
|
|||||||
|
|
||||||
/* read from module */
|
/* read from module */
|
||||||
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
memcpy (buf, &cmd_buffer, sizeof(cmd_buffer));
|
||||||
if (!fu_rts54hid_device_set_report (parent, buf, sizeof(buf), error)) {
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (parent), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT * 2,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error)) {
|
||||||
g_prefix_error (error, "failed to write i2c @%04x: ", self->slave_addr);
|
g_prefix_error (error, "failed to write i2c @%04x: ", self->slave_addr);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!fu_rts54hid_device_get_report (parent, buf, sizeof(buf), error))
|
if (!fu_hid_device_get_report (FU_HID_DEVICE (parent), 0x0, buf, sizeof(buf),
|
||||||
|
FU_RTS54HID_DEVICE_TIMEOUT,
|
||||||
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
return fu_memcpy_safe (data, data_sz, 0x0,
|
return fu_memcpy_safe (data, data_sz, 0x0,
|
||||||
buf, sizeof(buf), FU_RTS54HID_CMD_BUFFER_OFFSET_DATA,
|
buf, sizeof(buf), FU_RTS54HID_CMD_BUFFER_OFFSET_DATA,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2019 Synaptics Incorporated
|
* Copyright (C) 2005-2019 Synaptics Incorporated
|
||||||
* Copyright (C) 2019 Richard Hughes <richard@hughsie.com>
|
* Copyright (C) 2019-2020 Richard Hughes <richard@hughsie.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: LGPL-2.1+
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
*/
|
*/
|
||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
struct _FuSynapticsCxaudioDevice
|
struct _FuSynapticsCxaudioDevice
|
||||||
{
|
{
|
||||||
FuUsbDevice parent_instance;
|
FuHidDevice parent_instance;
|
||||||
guint32 chip_id_base;
|
guint32 chip_id_base;
|
||||||
guint32 chip_id;
|
guint32 chip_id;
|
||||||
gboolean serial_number_set;
|
gboolean serial_number_set;
|
||||||
@ -32,7 +32,7 @@ struct _FuSynapticsCxaudioDevice
|
|||||||
guint8 patch_level;
|
guint8 patch_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (FuSynapticsCxaudioDevice, fu_synaptics_cxaudio_device, FU_TYPE_USB_DEVICE)
|
G_DEFINE_TYPE (FuSynapticsCxaudioDevice, fu_synaptics_cxaudio_device, FU_TYPE_HID_DEVICE)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fu_synaptics_cxaudio_device_to_string (FuDevice *device, guint idt, GString *str)
|
fu_synaptics_cxaudio_device_to_string (FuDevice *device, guint idt, GString *str)
|
||||||
@ -48,38 +48,14 @@ fu_synaptics_cxaudio_device_to_string (FuDevice *device, guint idt, GString *str
|
|||||||
fu_common_string_append_kb (str, idt, "SerialNumberSet", self->serial_number_set);
|
fu_common_string_append_kb (str, idt, "SerialNumberSet", self->serial_number_set);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_synaptics_cxaudio_device_open (FuUsbDevice *device, GError **error)
|
|
||||||
{
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (device);
|
|
||||||
|
|
||||||
/* get firmware version */
|
|
||||||
if (!g_usb_device_claim_interface (usb_device, FU_SYNAPTICS_CXAUDIO_HID_INTERFACE,
|
|
||||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
|
||||||
error)) {
|
|
||||||
g_prefix_error (error, "failed to claim interface: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_synaptics_cxaudio_device_output_report (FuSynapticsCxaudioDevice *self,
|
fu_synaptics_cxaudio_device_output_report (FuSynapticsCxaudioDevice *self,
|
||||||
guint8 *buf,
|
guint8 *buf,
|
||||||
guint16 bufsz,
|
guint16 bufsz,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
guint16 report_number = buf[0];
|
|
||||||
gsize actual_length = 0;
|
|
||||||
|
|
||||||
g_return_val_if_fail (buf != NULL, FALSE);
|
|
||||||
g_return_val_if_fail (bufsz != 0, FALSE);
|
|
||||||
|
|
||||||
/* weird */
|
/* weird */
|
||||||
if (report_number == 0x0) {
|
if (buf[0] == 0x0) {
|
||||||
g_set_error_literal (error,
|
g_set_error_literal (error,
|
||||||
FWUPD_ERROR,
|
FWUPD_ERROR,
|
||||||
FWUPD_ERROR_NOT_SUPPORTED,
|
FWUPD_ERROR_NOT_SUPPORTED,
|
||||||
@ -88,30 +64,11 @@ fu_synaptics_cxaudio_device_output_report (FuSynapticsCxaudioDevice *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* to device */
|
/* to device */
|
||||||
if (g_getenv ("FWUPD_SYNAPTICS_CXAUDIO_VERBOSE") != NULL)
|
return fu_hid_device_set_report (FU_HID_DEVICE (self), buf[0],
|
||||||
fu_common_dump_raw (G_LOG_DOMAIN, "HID::WRITE", buf, bufsz);
|
buf, bufsz,
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
FU_SYNAPTICS_CXAUDIO_USB_TIMEOUT,
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
error);
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
|
||||||
FU_HID_REPORT_SET,
|
|
||||||
(FU_HID_REPORT_TYPE_OUTPUT << 8) | report_number,
|
|
||||||
FU_SYNAPTICS_CXAUDIO_HID_INTERFACE,
|
|
||||||
buf, bufsz, &actual_length,
|
|
||||||
FU_SYNAPTICS_CXAUDIO_USB_TIMEOUT, NULL, error)) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (bufsz != actual_length) {
|
|
||||||
g_set_error (error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_NOT_SUPPORTED,
|
|
||||||
"wrote 0x%x bytes of 0x%x",
|
|
||||||
(guint) actual_length, bufsz);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -121,37 +78,11 @@ fu_synaptics_cxaudio_device_input_report (FuSynapticsCxaudioDevice *self,
|
|||||||
guint16 bufsz,
|
guint16 bufsz,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
return fu_hid_device_get_report (FU_HID_DEVICE (self), ReportID,
|
||||||
gsize actual_length = 0;
|
buf, bufsz,
|
||||||
|
FU_SYNAPTICS_CXAUDIO_USB_TIMEOUT,
|
||||||
g_return_val_if_fail (buf != NULL, FALSE);
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
g_return_val_if_fail (bufsz != 0, FALSE);
|
error);
|
||||||
|
|
||||||
/* from device */
|
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
|
||||||
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
|
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
|
||||||
FU_HID_REPORT_GET,
|
|
||||||
(FU_HID_REPORT_TYPE_INPUT << 8) | ReportID,
|
|
||||||
FU_SYNAPTICS_CXAUDIO_HID_INTERFACE,
|
|
||||||
buf, bufsz, &actual_length,
|
|
||||||
FU_SYNAPTICS_CXAUDIO_USB_TIMEOUT, NULL, error)) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (g_getenv ("FWUPD_SYNAPTICS_CXAUDIO_VERBOSE") != NULL)
|
|
||||||
fu_common_dump_raw (G_LOG_DOMAIN, "HID::READ", buf, bufsz);
|
|
||||||
if (bufsz != actual_length) {
|
|
||||||
g_set_error (error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_NOT_SUPPORTED,
|
|
||||||
"read 0x%x bytes of expected 0x%x",
|
|
||||||
(guint) actual_length, bufsz);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -643,23 +574,6 @@ fu_synaptics_cxaudio_device_setup (FuDevice *device, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_synaptics_cxaudio_device_close (FuUsbDevice *device, GError **error)
|
|
||||||
{
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (device);
|
|
||||||
|
|
||||||
/* we're done here */
|
|
||||||
if (!g_usb_device_release_interface (usb_device, FU_SYNAPTICS_CXAUDIO_HID_INTERFACE,
|
|
||||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
|
||||||
error)) {
|
|
||||||
g_prefix_error (error, "failed to release interface: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FuFirmware *
|
static FuFirmware *
|
||||||
fu_synaptics_cxaudio_device_prepare_firmware (FuDevice *device,
|
fu_synaptics_cxaudio_device_prepare_firmware (FuDevice *device,
|
||||||
GBytes *fw,
|
GBytes *fw,
|
||||||
@ -854,18 +768,16 @@ fu_synaptics_cxaudio_device_init (FuSynapticsCxaudioDevice *self)
|
|||||||
fu_device_set_install_duration (FU_DEVICE (self), 3); /* seconds */
|
fu_device_set_install_duration (FU_DEVICE (self), 3); /* seconds */
|
||||||
fu_device_set_protocol (FU_DEVICE (self), "com.synaptics.cxaudio");
|
fu_device_set_protocol (FU_DEVICE (self), "com.synaptics.cxaudio");
|
||||||
fu_device_set_remove_delay (FU_DEVICE (self), FU_DEVICE_REMOVE_DELAY_RE_ENUMERATE);
|
fu_device_set_remove_delay (FU_DEVICE (self), FU_DEVICE_REMOVE_DELAY_RE_ENUMERATE);
|
||||||
|
fu_hid_device_set_interface (FU_HID_DEVICE (self), FU_SYNAPTICS_CXAUDIO_HID_INTERFACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fu_synaptics_cxaudio_device_class_init (FuSynapticsCxaudioDeviceClass *klass)
|
fu_synaptics_cxaudio_device_class_init (FuSynapticsCxaudioDeviceClass *klass)
|
||||||
{
|
{
|
||||||
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
|
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
|
||||||
FuUsbDeviceClass *klass_usb_device = FU_USB_DEVICE_CLASS (klass);
|
|
||||||
klass_device->to_string = fu_synaptics_cxaudio_device_to_string;
|
klass_device->to_string = fu_synaptics_cxaudio_device_to_string;
|
||||||
klass_device->set_quirk_kv = fu_synaptics_cxaudio_device_set_quirk_kv;
|
klass_device->set_quirk_kv = fu_synaptics_cxaudio_device_set_quirk_kv;
|
||||||
klass_device->setup = fu_synaptics_cxaudio_device_setup;
|
klass_device->setup = fu_synaptics_cxaudio_device_setup;
|
||||||
klass_device->write_firmware = fu_synaptics_cxaudio_device_write_firmware;
|
klass_device->write_firmware = fu_synaptics_cxaudio_device_write_firmware;
|
||||||
klass_device->prepare_firmware = fu_synaptics_cxaudio_device_prepare_firmware;
|
klass_device->prepare_firmware = fu_synaptics_cxaudio_device_prepare_firmware;
|
||||||
klass_usb_device->open = fu_synaptics_cxaudio_device_open;
|
|
||||||
klass_usb_device->close = fu_synaptics_cxaudio_device_close;
|
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "fu-hid-device.h"
|
||||||
#include "fu-plugin.h"
|
#include "fu-plugin.h"
|
||||||
|
|
||||||
#define FU_TYPE_SYNAPTICS_CXAUDIO_DEVICE (fu_synaptics_cxaudio_device_get_type ())
|
#define FU_TYPE_SYNAPTICS_CXAUDIO_DEVICE (fu_synaptics_cxaudio_device_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (FuSynapticsCxaudioDevice, fu_synaptics_cxaudio_device, FU, SYNAPTICS_CXAUDIO_DEVICE, FuUsbDevice)
|
G_DECLARE_FINAL_TYPE (FuSynapticsCxaudioDevice, fu_synaptics_cxaudio_device, FU, SYNAPTICS_CXAUDIO_DEVICE, FuHidDevice)
|
||||||
|
|
||||||
struct _FuSynapticsCxaudioDeviceClass
|
struct _FuSynapticsCxaudioDeviceClass
|
||||||
{
|
{
|
||||||
FuUsbDeviceClass parent_class;
|
FuHidDeviceClass parent_class;
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,7 @@ typedef enum {
|
|||||||
|
|
||||||
struct _FuWacDevice
|
struct _FuWacDevice
|
||||||
{
|
{
|
||||||
FuUsbDevice parent_instance;
|
FuHidDevice parent_instance;
|
||||||
GPtrArray *flash_descriptors;
|
GPtrArray *flash_descriptors;
|
||||||
GArray *checksums;
|
GArray *checksums;
|
||||||
guint32 status_word;
|
guint32 status_word;
|
||||||
@ -48,7 +48,7 @@ struct _FuWacDevice
|
|||||||
guint16 configuration;
|
guint16 configuration;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (FuWacDevice, fu_wac_device, FU_TYPE_USB_DEVICE)
|
G_DEFINE_TYPE (FuWacDevice, fu_wac_device, FU_TYPE_HID_DEVICE)
|
||||||
|
|
||||||
static GString *
|
static GString *
|
||||||
fu_wac_device_status_to_string (guint32 status_word)
|
fu_wac_device_status_to_string (guint32 status_word)
|
||||||
@ -135,42 +135,20 @@ fu_wac_device_to_string (FuDevice *device, guint idt, GString *str)
|
|||||||
gboolean
|
gboolean
|
||||||
fu_wac_device_get_feature_report (FuWacDevice *self,
|
fu_wac_device_get_feature_report (FuWacDevice *self,
|
||||||
guint8 *buf, gsize bufsz,
|
guint8 *buf, gsize bufsz,
|
||||||
FuWacDeviceFeatureFlags flags,
|
FuHidDeviceFlags flags,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
gsize sz = 0;
|
|
||||||
guint8 cmd = buf[0];
|
guint8 cmd = buf[0];
|
||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
if ((flags & FU_WAC_DEVICE_FEATURE_FLAG_NO_DEBUG) == 0)
|
if (!fu_hid_device_get_report (FU_HID_DEVICE (self), cmd,
|
||||||
fu_wac_buffer_dump ("GET", cmd, buf, bufsz);
|
buf, bufsz,
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
FU_WAC_DEVICE_TIMEOUT,
|
||||||
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
|
flags | FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
error))
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
|
||||||
FU_HID_REPORT_GET, /* bRequest */
|
|
||||||
FU_HID_FEATURE | cmd, /* wValue */
|
|
||||||
0x0000, /* wIndex */
|
|
||||||
buf, bufsz, &sz,
|
|
||||||
FU_WAC_DEVICE_TIMEOUT,
|
|
||||||
NULL, error)) {
|
|
||||||
g_prefix_error (error, "Failed to get feature report: ");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
if ((flags & FU_WAC_DEVICE_FEATURE_FLAG_NO_DEBUG) == 0)
|
|
||||||
fu_wac_buffer_dump ("GE2", cmd, buf, sz);
|
|
||||||
|
|
||||||
/* check packet */
|
/* check packet */
|
||||||
if ((flags & FU_WAC_DEVICE_FEATURE_FLAG_ALLOW_TRUNC) == 0 && sz != bufsz) {
|
|
||||||
g_set_error (error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INTERNAL,
|
|
||||||
"packet get bytes %" G_GSIZE_FORMAT
|
|
||||||
" expected %" G_GSIZE_FORMAT,
|
|
||||||
sz, bufsz);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (buf[0] != cmd) {
|
if (buf[0] != cmd) {
|
||||||
g_set_error (error,
|
g_set_error (error,
|
||||||
FWUPD_ERROR,
|
FWUPD_ERROR,
|
||||||
@ -185,42 +163,17 @@ fu_wac_device_get_feature_report (FuWacDevice *self,
|
|||||||
gboolean
|
gboolean
|
||||||
fu_wac_device_set_feature_report (FuWacDevice *self,
|
fu_wac_device_set_feature_report (FuWacDevice *self,
|
||||||
guint8 *buf, gsize bufsz,
|
guint8 *buf, gsize bufsz,
|
||||||
FuWacDeviceFeatureFlags flags,
|
FuHidDeviceFlags flags,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
|
||||||
gsize sz = 0;
|
|
||||||
guint8 cmd = buf[0];
|
|
||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
fu_wac_buffer_dump ("SET", cmd, buf, bufsz);
|
|
||||||
if (g_getenv ("FWUPD_WAC_EMULATE") != NULL)
|
if (g_getenv ("FWUPD_WAC_EMULATE") != NULL)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
if (!g_usb_device_control_transfer (usb_device,
|
return fu_hid_device_set_report (FU_HID_DEVICE (self), buf[0],
|
||||||
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
buf, bufsz,
|
||||||
G_USB_DEVICE_REQUEST_TYPE_CLASS,
|
FU_WAC_DEVICE_TIMEOUT,
|
||||||
G_USB_DEVICE_RECIPIENT_INTERFACE,
|
flags | FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||||
FU_HID_REPORT_SET, /* bRequest */
|
error);
|
||||||
FU_HID_FEATURE | cmd, /* wValue */
|
|
||||||
0x0000, /* wIndex */
|
|
||||||
buf, bufsz, &sz,
|
|
||||||
FU_WAC_DEVICE_TIMEOUT,
|
|
||||||
NULL, error)) {
|
|
||||||
g_prefix_error (error, "Failed to set feature report: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check packet */
|
|
||||||
if ((flags & FU_WAC_DEVICE_FEATURE_FLAG_ALLOW_TRUNC) == 0 && sz != bufsz) {
|
|
||||||
g_set_error (error,
|
|
||||||
FWUPD_ERROR,
|
|
||||||
FWUPD_ERROR_INTERNAL,
|
|
||||||
"packet sent bytes %" G_GSIZE_FORMAT
|
|
||||||
" expected %" G_GSIZE_FORMAT,
|
|
||||||
sz, bufsz);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -238,7 +191,7 @@ fu_wac_device_ensure_flash_descriptors (FuWacDevice *self, GError **error)
|
|||||||
memset (buf, 0xff, sz);
|
memset (buf, 0xff, sz);
|
||||||
buf[0] = FU_WAC_REPORT_ID_GET_FLASH_DESCRIPTOR;
|
buf[0] = FU_WAC_REPORT_ID_GET_FLASH_DESCRIPTOR;
|
||||||
if (!fu_wac_device_get_feature_report (self, buf, sz,
|
if (!fu_wac_device_get_feature_report (self, buf, sz,
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error))
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -265,7 +218,7 @@ fu_wac_device_ensure_status (FuWacDevice *self, GError **error)
|
|||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
buf[0] = FU_WAC_REPORT_ID_GET_STATUS;
|
buf[0] = FU_WAC_REPORT_ID_GET_STATUS;
|
||||||
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error))
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -287,7 +240,7 @@ fu_wac_device_ensure_checksums (FuWacDevice *self, GError **error)
|
|||||||
memset (buf, 0xff, sz);
|
memset (buf, 0xff, sz);
|
||||||
buf[0] = FU_WAC_REPORT_ID_GET_CHECKSUMS;
|
buf[0] = FU_WAC_REPORT_ID_GET_CHECKSUMS;
|
||||||
if (!fu_wac_device_get_feature_report (self, buf, sz,
|
if (!fu_wac_device_get_feature_report (self, buf, sz,
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error))
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -316,7 +269,7 @@ fu_wac_device_ensure_firmware_index (FuWacDevice *self, GError **error)
|
|||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error))
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -333,7 +286,7 @@ fu_wac_device_ensure_parameters (FuWacDevice *self, GError **error)
|
|||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error))
|
error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -383,7 +336,7 @@ fu_wac_device_write_block (FuWacDevice *self,
|
|||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
return fu_wac_device_set_feature_report (self, buf, bufsz,
|
return fu_wac_device_set_feature_report (self, buf, bufsz,
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +351,7 @@ fu_wac_device_erase_block (FuWacDevice *self, guint32 addr, GError **error)
|
|||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,7 +363,7 @@ fu_wac_device_update_reset (FuWacDevice *self, GError **error)
|
|||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,7 +382,7 @@ fu_wac_device_set_checksum_of_block (FuWacDevice *self,
|
|||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +399,7 @@ fu_wac_device_calculate_checksum_of_block (FuWacDevice *self,
|
|||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,7 +411,7 @@ fu_wac_device_write_checksum_table (FuWacDevice *self, GError **error)
|
|||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,7 +424,7 @@ fu_wac_device_switch_to_flash_loader (FuWacDevice *self, GError **error)
|
|||||||
|
|
||||||
/* hit hardware */
|
/* hit hardware */
|
||||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error);
|
error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -676,7 +629,7 @@ fu_wac_device_add_modules_bluetooth (FuWacDevice *self, GError **error)
|
|||||||
|
|
||||||
buf[0] = FU_WAC_REPORT_ID_GET_FIRMWARE_VERSION_BLUETOOTH;
|
buf[0] = FU_WAC_REPORT_ID_GET_FIRMWARE_VERSION_BLUETOOTH;
|
||||||
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error)) {
|
error)) {
|
||||||
g_prefix_error (error, "Failed to get GetFirmwareVersionBluetooth: ");
|
g_prefix_error (error, "Failed to get GetFirmwareVersionBluetooth: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -714,7 +667,7 @@ fu_wac_device_add_modules (FuWacDevice *self, GError **error)
|
|||||||
[1 ... 31] = 0xff };
|
[1 ... 31] = 0xff };
|
||||||
|
|
||||||
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
FU_HID_DEVICE_FLAG_NONE,
|
||||||
error)) {
|
error)) {
|
||||||
g_prefix_error (error, "Failed to get DeviceFirmwareDescriptor: ");
|
g_prefix_error (error, "Failed to get DeviceFirmwareDescriptor: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -780,23 +733,6 @@ fu_wac_device_add_modules (FuWacDevice *self, GError **error)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
fu_wac_device_open (FuUsbDevice *device, GError **error)
|
|
||||||
{
|
|
||||||
GUsbDevice *usb_device = fu_usb_device_get_dev (device);
|
|
||||||
|
|
||||||
/* open device */
|
|
||||||
if (!g_usb_device_claim_interface (usb_device, 0x00, /* HID */
|
|
||||||
G_USB_DEVICE_CLAIM_INTERFACE_BIND_KERNEL_DRIVER,
|
|
||||||
error)) {
|
|
||||||
g_prefix_error (error, "failed to claim HID interface: ");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* success */
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
fu_wac_device_setup (FuDevice *device, GError **error)
|
fu_wac_device_setup (FuDevice *device, GError **error)
|
||||||
{
|
{
|
||||||
@ -879,6 +815,5 @@ fu_wac_device_class_init (FuWacDeviceClass *klass)
|
|||||||
klass_device->write_firmware = fu_wac_device_write_firmware;
|
klass_device->write_firmware = fu_wac_device_write_firmware;
|
||||||
klass_device->to_string = fu_wac_device_to_string;
|
klass_device->to_string = fu_wac_device_to_string;
|
||||||
klass_device->setup = fu_wac_device_setup;
|
klass_device->setup = fu_wac_device_setup;
|
||||||
klass_usb_device->open = fu_wac_device_open;
|
|
||||||
klass_usb_device->close = fu_wac_device_close;
|
klass_usb_device->close = fu_wac_device_close;
|
||||||
}
|
}
|
||||||
|
@ -7,26 +7,20 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "fu-plugin.h"
|
#include "fu-plugin.h"
|
||||||
|
#include "fu-hid-device.h"
|
||||||
|
|
||||||
#define FU_TYPE_WAC_DEVICE (fu_wac_device_get_type ())
|
#define FU_TYPE_WAC_DEVICE (fu_wac_device_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (FuWacDevice, fu_wac_device, FU, WAC_DEVICE, FuUsbDevice)
|
G_DECLARE_FINAL_TYPE (FuWacDevice, fu_wac_device, FU, WAC_DEVICE, FuHidDevice)
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE = 0,
|
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_ALLOW_TRUNC = 1 << 0,
|
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NO_DEBUG = 1 << 1,
|
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_LAST
|
|
||||||
} FuWacDeviceFeatureFlags;
|
|
||||||
|
|
||||||
gboolean fu_wac_device_update_reset (FuWacDevice *self,
|
gboolean fu_wac_device_update_reset (FuWacDevice *self,
|
||||||
GError **error);
|
GError **error);
|
||||||
gboolean fu_wac_device_get_feature_report (FuWacDevice *self,
|
gboolean fu_wac_device_get_feature_report (FuWacDevice *self,
|
||||||
guint8 *buf,
|
guint8 *buf,
|
||||||
gsize bufsz,
|
gsize bufsz,
|
||||||
FuWacDeviceFeatureFlags flags,
|
FuHidDeviceFlags flags,
|
||||||
GError **error);
|
GError **error);
|
||||||
gboolean fu_wac_device_set_feature_report (FuWacDevice *self,
|
gboolean fu_wac_device_set_feature_report (FuWacDevice *self,
|
||||||
guint8 *buf,
|
guint8 *buf,
|
||||||
gsize bufsz,
|
gsize bufsz,
|
||||||
FuWacDeviceFeatureFlags flags,
|
FuHidDeviceFlags flags,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
@ -130,8 +130,7 @@ fu_wac_module_refresh (FuWacModule *self, GError **error)
|
|||||||
|
|
||||||
/* get from hardware */
|
/* get from hardware */
|
||||||
if (!fu_wac_device_get_feature_report (parent_device, buf, sizeof(buf),
|
if (!fu_wac_device_get_feature_report (parent_device, buf, sizeof(buf),
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_ALLOW_TRUNC |
|
FU_HID_DEVICE_FLAG_ALLOW_TRUNC,
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_NO_DEBUG,
|
|
||||||
error)) {
|
error)) {
|
||||||
g_prefix_error (error, "failed to refresh status: ");
|
g_prefix_error (error, "failed to refresh status: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -211,7 +210,7 @@ fu_wac_module_set_feature (FuWacModule *self,
|
|||||||
|
|
||||||
/* send to hardware */
|
/* send to hardware */
|
||||||
if (!fu_wac_device_set_feature_report (parent_device, buf, len + 3,
|
if (!fu_wac_device_set_feature_report (parent_device, buf, len + 3,
|
||||||
FU_WAC_DEVICE_FEATURE_FLAG_ALLOW_TRUNC,
|
FU_HID_DEVICE_FLAG_ALLOW_TRUNC,
|
||||||
error)) {
|
error)) {
|
||||||
g_prefix_error (error, "failed to set module feature: ");
|
g_prefix_error (error, "failed to set module feature: ");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
Loading…
Reference in New Issue
Block a user