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-hwids.h"
|
||||
#include "fu-usb-device.h"
|
||||
//#include "fu-hid-device.h"
|
||||
#ifdef HAVE_GUDEV
|
||||
#include "fu-udev-device.h"
|
||||
#endif
|
||||
|
@ -15,16 +15,6 @@
|
||||
#define FU_TYPE_USB_DEVICE (fu_usb_device_get_type ())
|
||||
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
|
||||
{
|
||||
FuDeviceClass parent_class;
|
||||
|
@ -556,6 +556,12 @@ LIBFWUPDPLUGIN_1.4.0 {
|
||||
fu_efivar_secure_boot_enabled;
|
||||
fu_efivar_set_data;
|
||||
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_runner_device_created;
|
||||
local: *;
|
||||
|
@ -22,6 +22,7 @@ fwupdplugin_src = [
|
||||
'fu-efivar.c',
|
||||
'fu-udev-device.c',
|
||||
'fu-usb-device.c',
|
||||
'fu-hid-device.c',
|
||||
]
|
||||
|
||||
fwupdplugin_headers = [
|
||||
@ -49,6 +50,7 @@ fwupdplugin_headers = [
|
||||
'fu-efivar.h',
|
||||
'fu-udev-device.h',
|
||||
'fu-usb-device.h',
|
||||
'fu-hid-device.h',
|
||||
]
|
||||
install_headers(
|
||||
'fwupdplugin.h',
|
||||
|
@ -32,13 +32,13 @@ typedef enum {
|
||||
|
||||
struct _FuCsrDevice
|
||||
{
|
||||
FuUsbDevice parent_instance;
|
||||
FuHidDevice parent_instance;
|
||||
FuCsrDeviceQuirks quirks;
|
||||
DfuState dfu_state;
|
||||
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_STATUS 0x02
|
||||
@ -69,73 +69,36 @@ fu_csr_device_to_string (FuDevice *device, guint idt, GString *str)
|
||||
static gboolean
|
||||
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 };
|
||||
|
||||
if (g_getenv ("FWUPD_CSR_VERBOSE") != NULL)
|
||||
fu_common_dump_raw (G_LOG_DOMAIN, "Reset", buf, sz);
|
||||
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, /* 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: ");
|
||||
if (!fu_hid_device_set_report (FU_HID_DEVICE (device),
|
||||
FU_CSR_REPORT_ID_CONTROL,
|
||||
buf, sizeof(buf),
|
||||
FU_CSR_DEVICE_TIMEOUT,
|
||||
FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||
error)) {
|
||||
g_prefix_error (error, "failed to attach: ");
|
||||
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;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
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};
|
||||
|
||||
/* hit hardware */
|
||||
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, /* bRequest */
|
||||
FU_HID_FEATURE | FU_CSR_REPORT_ID_STATUS, /* wValue */
|
||||
0x0000, /* wIndex */
|
||||
buf, sizeof(buf), &sz,
|
||||
if (!fu_hid_device_get_report (FU_HID_DEVICE (self),
|
||||
FU_CSR_REPORT_ID_STATUS,
|
||||
buf, sizeof(buf),
|
||||
FU_CSR_DEVICE_TIMEOUT,
|
||||
NULL, error)) {
|
||||
g_prefix_error (error, "Failed to GetStatus: ");
|
||||
FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||
error)) {
|
||||
g_prefix_error (error, "failed to GetStatus: ");
|
||||
return FALSE;
|
||||
}
|
||||
if (g_getenv ("FWUPD_CSR_VERBOSE") != NULL)
|
||||
fu_common_dump_raw (G_LOG_DOMAIN, "GetStatus", buf, sz);
|
||||
|
||||
/* 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) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
@ -157,8 +120,6 @@ fu_csr_device_get_status (FuCsrDevice *self, GError **error)
|
||||
static gboolean
|
||||
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,
|
||||
FU_CSR_CONTROL_CLEAR_STATUS };
|
||||
|
||||
@ -169,29 +130,13 @@ fu_csr_device_clear_status (FuCsrDevice *self, GError **error)
|
||||
return TRUE;
|
||||
|
||||
/* hit hardware */
|
||||
if (g_getenv ("FWUPD_CSR_VERBOSE") != NULL)
|
||||
fu_common_dump_raw (G_LOG_DOMAIN, "ClearStatus", buf, sz);
|
||||
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, /* bRequest */
|
||||
FU_HID_FEATURE | FU_CSR_REPORT_ID_CONTROL, /* wValue */
|
||||
0x0000, /* wIndex */
|
||||
buf, sizeof(buf), &sz,
|
||||
if (!fu_hid_device_set_report (FU_HID_DEVICE (self),
|
||||
FU_CSR_REPORT_ID_CONTROL,
|
||||
buf, sizeof(buf),
|
||||
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);
|
||||
FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||
error)) {
|
||||
g_prefix_error (error, "failed to ClearStatus: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -202,35 +147,17 @@ fu_csr_device_clear_status (FuCsrDevice *self, GError **error)
|
||||
static GBytes *
|
||||
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;
|
||||
guint8 buf[64] = {0};
|
||||
|
||||
/* hit hardware */
|
||||
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, /* bRequest */
|
||||
FU_HID_FEATURE | FU_CSR_REPORT_ID_COMMAND, /* wValue */
|
||||
0x0000, /* wIndex */
|
||||
buf, sizeof(buf), &sz,
|
||||
if (!fu_hid_device_get_report (FU_HID_DEVICE (self),
|
||||
FU_CSR_REPORT_ID_COMMAND,
|
||||
buf, sizeof(buf),
|
||||
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);
|
||||
FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||
error)) {
|
||||
g_prefix_error (error, "failed to ReadFirmware: ");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -245,7 +172,7 @@ fu_csr_device_upload_chunk (FuCsrDevice *self, GError **error)
|
||||
|
||||
/* check the length */
|
||||
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,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_INTERNAL,
|
||||
@ -256,7 +183,7 @@ fu_csr_device_upload_chunk (FuCsrDevice *self, GError **error)
|
||||
|
||||
/* return as bytes */
|
||||
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 *
|
||||
@ -331,10 +258,8 @@ fu_csr_device_upload (FuDevice *device, GError **error)
|
||||
static gboolean
|
||||
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;
|
||||
gsize chunk_sz = 0;
|
||||
gsize write_sz = 0;
|
||||
guint8 buf[FU_CSR_PACKET_DATA_SIZE] = {0};
|
||||
|
||||
/* too large? */
|
||||
@ -359,32 +284,13 @@ fu_csr_device_download_chunk (FuCsrDevice *self, guint16 idx, GBytes *chunk, GEr
|
||||
return FALSE;
|
||||
|
||||
/* hit hardware */
|
||||
if (g_getenv ("FWUPD_CSR_VERBOSE") != NULL)
|
||||
fu_common_dump_raw (G_LOG_DOMAIN, "Upgrade", buf, sizeof(buf));
|
||||
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, /* bRequest */
|
||||
FU_HID_FEATURE | FU_CSR_REPORT_ID_COMMAND, /* wValue */
|
||||
0x0000, /* wIndex */
|
||||
buf,
|
||||
sizeof(buf),
|
||||
&write_sz,
|
||||
if (!fu_hid_device_set_report (FU_HID_DEVICE (self),
|
||||
FU_CSR_REPORT_ID_COMMAND,
|
||||
buf, sizeof(buf),
|
||||
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));
|
||||
FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||
error)) {
|
||||
g_prefix_error (error, "failed to Upgrade: ");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -501,23 +407,6 @@ fu_csr_device_probe (FuUsbDevice *device, GError **error)
|
||||
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
|
||||
fu_csr_device_setup (FuDevice *device, GError **error)
|
||||
{
|
||||
@ -530,23 +419,6 @@ fu_csr_device_setup (FuDevice *device, GError **error)
|
||||
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
|
||||
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->attach = fu_csr_device_attach;
|
||||
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;
|
||||
}
|
||||
|
@ -6,7 +6,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fu-hid-device.h"
|
||||
#include "fu-plugin.h"
|
||||
|
||||
#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 <errno.h>
|
||||
|
||||
#include "fu-usb-device.h"
|
||||
#include "fu-hid-device.h"
|
||||
#include "fwupd-error.h"
|
||||
|
||||
#include "fu-dell-dock-hid.h"
|
||||
@ -81,17 +81,14 @@ fu_dell_dock_hid_set_report (FuDevice *self,
|
||||
guint8 *outbuffer,
|
||||
GError **error)
|
||||
{
|
||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
||||
gboolean ret;
|
||||
gsize actual_len = 0;
|
||||
for (gint i = 1; i <= HID_MAX_RETRIES; i++) {
|
||||
g_autoptr(GError) error_local = NULL;
|
||||
ret = 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, outbuffer, 192, &actual_len,
|
||||
HIDI2C_TRANSACTION_TIMEOUT, NULL, &error_local);
|
||||
ret = fu_hid_device_set_report (FU_HID_DEVICE (self), 0x0,
|
||||
outbuffer, 192,
|
||||
HIDI2C_TRANSACTION_TIMEOUT,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
&error_local);
|
||||
if (ret)
|
||||
break;
|
||||
if (i == HID_MAX_RETRIES ||
|
||||
@ -107,11 +104,6 @@ fu_dell_dock_hid_set_report (FuDevice *self,
|
||||
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;
|
||||
}
|
||||
@ -121,17 +113,14 @@ fu_dell_dock_hid_get_report (FuDevice *self,
|
||||
guint8 *inbuffer,
|
||||
GError **error)
|
||||
{
|
||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
||||
gboolean ret;
|
||||
gsize actual_len = 0;
|
||||
for (gint i = 1; i <= HID_MAX_RETRIES; i++) {
|
||||
g_autoptr(GError) error_local = NULL;
|
||||
ret = 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, inbuffer, 192, &actual_len,
|
||||
HIDI2C_TRANSACTION_TIMEOUT, NULL, &error_local);
|
||||
ret = fu_hid_device_get_report (FU_HID_DEVICE (self), 0x0,
|
||||
inbuffer, 192,
|
||||
HIDI2C_TRANSACTION_TIMEOUT,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
&error_local);
|
||||
if (ret)
|
||||
break;
|
||||
if (i == HID_MAX_RETRIES ||
|
||||
@ -146,11 +135,6 @@ fu_dell_dock_hid_get_report (FuDevice *self,
|
||||
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;
|
||||
}
|
||||
|
@ -21,13 +21,13 @@
|
||||
#include "fu-dell-dock-common.h"
|
||||
|
||||
struct _FuDellDockHub {
|
||||
FuUsbDevice parent_instance;
|
||||
FuHidDevice parent_instance;
|
||||
guint8 unlock_target;
|
||||
guint64 blob_major_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
|
||||
fu_dell_dock_hub_probe (FuDevice *device, GError **error)
|
||||
@ -155,37 +155,6 @@ fu_dell_dock_hub_set_quirk_kv (FuDevice *device,
|
||||
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
|
||||
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);
|
||||
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
|
||||
FuUsbDeviceClass *klass_usb_device = FU_USB_DEVICE_CLASS (klass);
|
||||
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->probe = fu_dell_dock_hub_probe;
|
||||
klass_device->write_firmware = fu_dell_dock_hub_write_fw;
|
||||
|
@ -17,9 +17,9 @@
|
||||
|
||||
#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 ())
|
||||
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);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "fu-firmware-common.h"
|
||||
#include "fu-hid-device.h"
|
||||
#include "fu-logitech-hidpp-common.h"
|
||||
#include "fu-logitech-hidpp-bootloader.h"
|
||||
#include "fu-logitech-hidpp-hidpp.h"
|
||||
@ -23,7 +24,7 @@ typedef struct
|
||||
#define FU_UNIFYING_DEVICE_EP1 0x81
|
||||
#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))
|
||||
|
||||
@ -342,17 +343,10 @@ fu_logitech_hidpp_bootloader_request (FuLogitechHidPpBootloader *self,
|
||||
buf_request, sizeof (buf_request));
|
||||
}
|
||||
if (usb_device != NULL) {
|
||||
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_request,
|
||||
sizeof (buf_request),
|
||||
&actual_length,
|
||||
if (!fu_hid_device_set_report (FU_HID_DEVICE (self), 0x0,
|
||||
buf_request, sizeof(buf_request),
|
||||
FU_UNIFYING_DEVICE_TIMEOUT_MS,
|
||||
NULL,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error)) {
|
||||
g_prefix_error (error, "failed to send data: ");
|
||||
return FALSE;
|
||||
|
@ -6,14 +6,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fu-usb-device.h"
|
||||
#include "fu-hid-device.h"
|
||||
|
||||
#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
|
||||
{
|
||||
FuUsbDeviceClass parent_class;
|
||||
FuHidDeviceClass parent_class;
|
||||
gboolean (*setup) (FuLogitechHidPpBootloader *self,
|
||||
GError **error);
|
||||
};
|
||||
|
@ -13,14 +13,12 @@
|
||||
#include "fu-rts54hid-device.h"
|
||||
|
||||
struct _FuRts54HidDevice {
|
||||
FuUsbDevice parent_instance;
|
||||
FuHidDevice parent_instance;
|
||||
gboolean fw_auth;
|
||||
gboolean dual_bank;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (FuRts54HidDevice, fu_rts54hid_device, FU_TYPE_USB_DEVICE)
|
||||
|
||||
#define FU_RTS54HID_DEVICE_TIMEOUT 1000 /* ms */
|
||||
G_DEFINE_TYPE (FuRts54HidDevice, fu_rts54hid_device, FU_TYPE_HID_DEVICE)
|
||||
|
||||
static void
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
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 };
|
||||
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);
|
||||
return FALSE;
|
||||
}
|
||||
@ -120,7 +65,10 @@ fu_rts54hid_device_reset_to_flash (FuRts54HidDevice *self, GError **error)
|
||||
};
|
||||
guint8 buf[FU_RTS54FU_HID_REPORT_LENGTH] = { 0 };
|
||||
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: ");
|
||||
return FALSE;
|
||||
}
|
||||
@ -152,7 +100,10 @@ fu_rts54hid_device_write_flash (FuRts54HidDevice *self,
|
||||
data, data_sz, 0x0, /* src */
|
||||
data_sz, error))
|
||||
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);
|
||||
return FALSE;
|
||||
}
|
||||
@ -176,10 +127,16 @@ fu_rts54hid_device_verify_update_fw (FuRts54HidDevice *self, GError **error)
|
||||
|
||||
/* set then get */
|
||||
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;
|
||||
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;
|
||||
|
||||
/* 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 };
|
||||
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: ");
|
||||
return FALSE;
|
||||
}
|
||||
@ -235,9 +195,15 @@ fu_rts54hid_device_ensure_status (FuRts54HidDevice *self, GError **error)
|
||||
|
||||
/* set then get */
|
||||
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;
|
||||
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;
|
||||
|
||||
/* check the hardware capabilities */
|
||||
@ -250,25 +216,6 @@ fu_rts54hid_device_ensure_status (FuRts54HidDevice *self, GError **error)
|
||||
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
|
||||
fu_rts54hid_device_setup (FuDevice *device, GError **error)
|
||||
{
|
||||
@ -294,25 +241,12 @@ fu_rts54hid_device_setup (FuDevice *device, GError **error)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
fu_rts54hid_device_close (FuUsbDevice *device, GError **error)
|
||||
fu_rts54hid_device_close (FuHidDevice *device, GError **error)
|
||||
{
|
||||
FuRts54HidDevice *self = FU_RTS54HID_DEVICE (device);
|
||||
GUsbDevice *usb_device = fu_usb_device_get_dev (device);
|
||||
|
||||
/* set MCU to normal clock rate */
|
||||
if (!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;
|
||||
return fu_rts54hid_device_set_clock_mode (self, FALSE, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -385,10 +319,9 @@ static void
|
||||
fu_rts54hid_device_class_init (FuRts54HidDeviceClass *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->to_string = fu_rts54hid_device_to_string;
|
||||
klass_device->setup = fu_rts54hid_device_setup;
|
||||
klass_usb_device->open = fu_rts54hid_device_open;
|
||||
klass_usb_device->close = fu_rts54hid_device_close;
|
||||
klass_hid_device->close = fu_rts54hid_device_close;
|
||||
}
|
||||
|
@ -6,16 +6,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fu-plugin.h"
|
||||
#include "fu-hid-device.h"
|
||||
|
||||
#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,
|
||||
guint8 *buf,
|
||||
gsize buf_sz,
|
||||
GError **error);
|
||||
gboolean fu_rts54hid_device_get_report (FuRts54HidDevice *self,
|
||||
guint8 *buf,
|
||||
gsize buf_sz,
|
||||
GError **error);
|
||||
#define FU_RTS54HID_DEVICE_TIMEOUT 1000 /* ms */
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "fu-chunk.h"
|
||||
#include "fu-hid-device.h"
|
||||
|
||||
#include "fu-rts54hid-common.h"
|
||||
#include "fu-rts54hid-module.h"
|
||||
#include "fu-rts54hid-device.h"
|
||||
@ -77,7 +79,10 @@ fu_rts54hid_module_i2c_write (FuRts54HidModule *self,
|
||||
data, data_sz, 0x0, /* src */
|
||||
data_sz, error))
|
||||
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);
|
||||
return FALSE;
|
||||
}
|
||||
@ -114,11 +119,17 @@ fu_rts54hid_module_i2c_read (FuRts54HidModule *self,
|
||||
|
||||
/* read from module */
|
||||
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);
|
||||
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 fu_memcpy_safe (data, data_sz, 0x0,
|
||||
buf, sizeof(buf), FU_RTS54HID_CMD_BUFFER_OFFSET_DATA,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* 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+
|
||||
*/
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
struct _FuSynapticsCxaudioDevice
|
||||
{
|
||||
FuUsbDevice parent_instance;
|
||||
FuHidDevice parent_instance;
|
||||
guint32 chip_id_base;
|
||||
guint32 chip_id;
|
||||
gboolean serial_number_set;
|
||||
@ -32,7 +32,7 @@ struct _FuSynapticsCxaudioDevice
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
fu_synaptics_cxaudio_device_output_report (FuSynapticsCxaudioDevice *self,
|
||||
guint8 *buf,
|
||||
guint16 bufsz,
|
||||
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 */
|
||||
if (report_number == 0x0) {
|
||||
if (buf[0] == 0x0) {
|
||||
g_set_error_literal (error,
|
||||
FWUPD_ERROR,
|
||||
FWUPD_ERROR_NOT_SUPPORTED,
|
||||
@ -88,30 +64,11 @@ fu_synaptics_cxaudio_device_output_report (FuSynapticsCxaudioDevice *self,
|
||||
}
|
||||
|
||||
/* to device */
|
||||
if (g_getenv ("FWUPD_SYNAPTICS_CXAUDIO_VERBOSE") != NULL)
|
||||
fu_common_dump_raw (G_LOG_DOMAIN, "HID::WRITE", 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,
|
||||
(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;
|
||||
return fu_hid_device_set_report (FU_HID_DEVICE (self), buf[0],
|
||||
buf, bufsz,
|
||||
FU_SYNAPTICS_CXAUDIO_USB_TIMEOUT,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -121,37 +78,11 @@ fu_synaptics_cxaudio_device_input_report (FuSynapticsCxaudioDevice *self,
|
||||
guint16 bufsz,
|
||||
GError **error)
|
||||
{
|
||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
||||
gsize actual_length = 0;
|
||||
|
||||
g_return_val_if_fail (buf != NULL, FALSE);
|
||||
g_return_val_if_fail (bufsz != 0, FALSE);
|
||||
|
||||
/* 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;
|
||||
return fu_hid_device_get_report (FU_HID_DEVICE (self), ReportID,
|
||||
buf, bufsz,
|
||||
FU_SYNAPTICS_CXAUDIO_USB_TIMEOUT,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
@ -643,23 +574,6 @@ fu_synaptics_cxaudio_device_setup (FuDevice *device, GError **error)
|
||||
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 *
|
||||
fu_synaptics_cxaudio_device_prepare_firmware (FuDevice *device,
|
||||
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_protocol (FU_DEVICE (self), "com.synaptics.cxaudio");
|
||||
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
|
||||
fu_synaptics_cxaudio_device_class_init (FuSynapticsCxaudioDeviceClass *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->set_quirk_kv = fu_synaptics_cxaudio_device_set_quirk_kv;
|
||||
klass_device->setup = fu_synaptics_cxaudio_device_setup;
|
||||
klass_device->write_firmware = fu_synaptics_cxaudio_device_write_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
|
||||
|
||||
#include "fu-hid-device.h"
|
||||
#include "fu-plugin.h"
|
||||
|
||||
#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
|
||||
{
|
||||
FuUsbDeviceClass parent_class;
|
||||
FuHidDeviceClass parent_class;
|
||||
};
|
||||
|
@ -35,7 +35,7 @@ typedef enum {
|
||||
|
||||
struct _FuWacDevice
|
||||
{
|
||||
FuUsbDevice parent_instance;
|
||||
FuHidDevice parent_instance;
|
||||
GPtrArray *flash_descriptors;
|
||||
GArray *checksums;
|
||||
guint32 status_word;
|
||||
@ -48,7 +48,7 @@ struct _FuWacDevice
|
||||
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 *
|
||||
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
|
||||
fu_wac_device_get_feature_report (FuWacDevice *self,
|
||||
guint8 *buf, gsize bufsz,
|
||||
FuWacDeviceFeatureFlags flags,
|
||||
FuHidDeviceFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
||||
gsize sz = 0;
|
||||
guint8 cmd = buf[0];
|
||||
|
||||
/* hit hardware */
|
||||
if ((flags & FU_WAC_DEVICE_FEATURE_FLAG_NO_DEBUG) == 0)
|
||||
fu_wac_buffer_dump ("GET", cmd, buf, bufsz);
|
||||
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, /* bRequest */
|
||||
FU_HID_FEATURE | cmd, /* wValue */
|
||||
0x0000, /* wIndex */
|
||||
buf, bufsz, &sz,
|
||||
if (!fu_hid_device_get_report (FU_HID_DEVICE (self), cmd,
|
||||
buf, bufsz,
|
||||
FU_WAC_DEVICE_TIMEOUT,
|
||||
NULL, error)) {
|
||||
g_prefix_error (error, "Failed to get feature report: ");
|
||||
flags | FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
if ((flags & FU_WAC_DEVICE_FEATURE_FLAG_NO_DEBUG) == 0)
|
||||
fu_wac_buffer_dump ("GE2", cmd, buf, sz);
|
||||
|
||||
/* 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) {
|
||||
g_set_error (error,
|
||||
FWUPD_ERROR,
|
||||
@ -185,42 +163,17 @@ fu_wac_device_get_feature_report (FuWacDevice *self,
|
||||
gboolean
|
||||
fu_wac_device_set_feature_report (FuWacDevice *self,
|
||||
guint8 *buf, gsize bufsz,
|
||||
FuWacDeviceFeatureFlags flags,
|
||||
FuHidDeviceFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
GUsbDevice *usb_device = fu_usb_device_get_dev (FU_USB_DEVICE (self));
|
||||
gsize sz = 0;
|
||||
guint8 cmd = buf[0];
|
||||
|
||||
/* hit hardware */
|
||||
fu_wac_buffer_dump ("SET", cmd, buf, bufsz);
|
||||
if (g_getenv ("FWUPD_WAC_EMULATE") != NULL)
|
||||
return TRUE;
|
||||
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, /* bRequest */
|
||||
FU_HID_FEATURE | cmd, /* wValue */
|
||||
0x0000, /* wIndex */
|
||||
buf, bufsz, &sz,
|
||||
return fu_hid_device_set_report (FU_HID_DEVICE (self), buf[0],
|
||||
buf, bufsz,
|
||||
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;
|
||||
flags | FU_HID_DEVICE_FLAG_IS_FEATURE,
|
||||
error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -238,7 +191,7 @@ fu_wac_device_ensure_flash_descriptors (FuWacDevice *self, GError **error)
|
||||
memset (buf, 0xff, sz);
|
||||
buf[0] = FU_WAC_REPORT_ID_GET_FLASH_DESCRIPTOR;
|
||||
if (!fu_wac_device_get_feature_report (self, buf, sz,
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
@ -265,7 +218,7 @@ fu_wac_device_ensure_status (FuWacDevice *self, GError **error)
|
||||
/* hit hardware */
|
||||
buf[0] = FU_WAC_REPORT_ID_GET_STATUS;
|
||||
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
@ -287,7 +240,7 @@ fu_wac_device_ensure_checksums (FuWacDevice *self, GError **error)
|
||||
memset (buf, 0xff, sz);
|
||||
buf[0] = FU_WAC_REPORT_ID_GET_CHECKSUMS;
|
||||
if (!fu_wac_device_get_feature_report (self, buf, sz,
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
@ -316,7 +269,7 @@ fu_wac_device_ensure_firmware_index (FuWacDevice *self, GError **error)
|
||||
|
||||
/* hit hardware */
|
||||
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
@ -333,7 +286,7 @@ fu_wac_device_ensure_parameters (FuWacDevice *self, GError **error)
|
||||
|
||||
/* hit hardware */
|
||||
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
@ -383,7 +336,7 @@ fu_wac_device_write_block (FuWacDevice *self,
|
||||
|
||||
/* hit hardware */
|
||||
return fu_wac_device_set_feature_report (self, buf, bufsz,
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error);
|
||||
}
|
||||
|
||||
@ -398,7 +351,7 @@ fu_wac_device_erase_block (FuWacDevice *self, guint32 addr, GError **error)
|
||||
|
||||
/* hit hardware */
|
||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error);
|
||||
}
|
||||
|
||||
@ -410,7 +363,7 @@ fu_wac_device_update_reset (FuWacDevice *self, GError **error)
|
||||
|
||||
/* hit hardware */
|
||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error);
|
||||
}
|
||||
|
||||
@ -429,7 +382,7 @@ fu_wac_device_set_checksum_of_block (FuWacDevice *self,
|
||||
|
||||
/* hit hardware */
|
||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error);
|
||||
}
|
||||
|
||||
@ -446,7 +399,7 @@ fu_wac_device_calculate_checksum_of_block (FuWacDevice *self,
|
||||
|
||||
/* hit hardware */
|
||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error);
|
||||
}
|
||||
|
||||
@ -458,7 +411,7 @@ fu_wac_device_write_checksum_table (FuWacDevice *self, GError **error)
|
||||
|
||||
/* hit hardware */
|
||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error);
|
||||
}
|
||||
|
||||
@ -471,7 +424,7 @@ fu_wac_device_switch_to_flash_loader (FuWacDevice *self, GError **error)
|
||||
|
||||
/* hit hardware */
|
||||
return fu_wac_device_set_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
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;
|
||||
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error)) {
|
||||
g_prefix_error (error, "Failed to get GetFirmwareVersionBluetooth: ");
|
||||
return FALSE;
|
||||
@ -714,7 +667,7 @@ fu_wac_device_add_modules (FuWacDevice *self, GError **error)
|
||||
[1 ... 31] = 0xff };
|
||||
|
||||
if (!fu_wac_device_get_feature_report (self, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NONE,
|
||||
FU_HID_DEVICE_FLAG_NONE,
|
||||
error)) {
|
||||
g_prefix_error (error, "Failed to get DeviceFirmwareDescriptor: ");
|
||||
return FALSE;
|
||||
@ -780,23 +733,6 @@ fu_wac_device_add_modules (FuWacDevice *self, GError **error)
|
||||
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
|
||||
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->to_string = fu_wac_device_to_string;
|
||||
klass_device->setup = fu_wac_device_setup;
|
||||
klass_usb_device->open = fu_wac_device_open;
|
||||
klass_usb_device->close = fu_wac_device_close;
|
||||
}
|
||||
|
@ -7,26 +7,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "fu-plugin.h"
|
||||
#include "fu-hid-device.h"
|
||||
|
||||
#define FU_TYPE_WAC_DEVICE (fu_wac_device_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (FuWacDevice, fu_wac_device, FU, WAC_DEVICE, FuUsbDevice)
|
||||
|
||||
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;
|
||||
G_DECLARE_FINAL_TYPE (FuWacDevice, fu_wac_device, FU, WAC_DEVICE, FuHidDevice)
|
||||
|
||||
gboolean fu_wac_device_update_reset (FuWacDevice *self,
|
||||
GError **error);
|
||||
gboolean fu_wac_device_get_feature_report (FuWacDevice *self,
|
||||
guint8 *buf,
|
||||
gsize bufsz,
|
||||
FuWacDeviceFeatureFlags flags,
|
||||
FuHidDeviceFlags flags,
|
||||
GError **error);
|
||||
gboolean fu_wac_device_set_feature_report (FuWacDevice *self,
|
||||
guint8 *buf,
|
||||
gsize bufsz,
|
||||
FuWacDeviceFeatureFlags flags,
|
||||
FuHidDeviceFlags flags,
|
||||
GError **error);
|
||||
|
@ -130,8 +130,7 @@ fu_wac_module_refresh (FuWacModule *self, GError **error)
|
||||
|
||||
/* get from hardware */
|
||||
if (!fu_wac_device_get_feature_report (parent_device, buf, sizeof(buf),
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_ALLOW_TRUNC |
|
||||
FU_WAC_DEVICE_FEATURE_FLAG_NO_DEBUG,
|
||||
FU_HID_DEVICE_FLAG_ALLOW_TRUNC,
|
||||
error)) {
|
||||
g_prefix_error (error, "failed to refresh status: ");
|
||||
return FALSE;
|
||||
@ -211,7 +210,7 @@ fu_wac_module_set_feature (FuWacModule *self,
|
||||
|
||||
/* send to hardware */
|
||||
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)) {
|
||||
g_prefix_error (error, "failed to set module feature: ");
|
||||
return FALSE;
|
||||
|
Loading…
Reference in New Issue
Block a user