mirror of
https://git.proxmox.com/git/fwupd
synced 2025-05-15 07:24:46 +00:00

Devices may want to support more than one protocol, and for some devices (e.g. Unifying peripherals stuck in bootloader mode) you might not even be able to query for the correct protocol anyway.
92 lines
2.6 KiB
C
92 lines
2.6 KiB
C
/*
|
|
* Copyright (C) 2020 Cypress Semiconductor Corporation.
|
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1+
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "fu-ccgx-hid-device.h"
|
|
|
|
struct _FuCcgxHidDevice
|
|
{
|
|
FuHidDevice parent_instance;
|
|
};
|
|
|
|
G_DEFINE_TYPE (FuCcgxHidDevice, fu_ccgx_hid_device, FU_TYPE_HID_DEVICE)
|
|
|
|
#define FU_CCGX_HID_DEVICE_TIMEOUT 5000 /* ms */
|
|
#define FU_CCGX_HID_DEVICE_RETRY_DELAY 30 /* ms */
|
|
#define FU_CCGX_HID_DEVICE_RETRY_CNT 5
|
|
|
|
static gboolean
|
|
fu_ccgx_hid_device_enable_hpi_mode_cb (FuDevice *device,
|
|
gpointer user_data,
|
|
GError **error)
|
|
{
|
|
guint8 buf[5] = {0xEE, 0xBC, 0xA6, 0xB9, 0xA8};
|
|
|
|
fu_device_set_status (device, FWUPD_STATUS_DEVICE_RESTART);
|
|
if (!fu_hid_device_set_report (FU_HID_DEVICE (device), buf[0],
|
|
buf, sizeof(buf),
|
|
FU_CCGX_HID_DEVICE_TIMEOUT,
|
|
FU_HID_DEVICE_FLAG_NONE,
|
|
error)) {
|
|
g_prefix_error (error, "switch to HPI mode error: ");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
fu_ccgx_hid_device_detach (FuDevice *device, GError **error)
|
|
{
|
|
if (!fu_device_retry (device,
|
|
fu_ccgx_hid_device_enable_hpi_mode_cb,
|
|
FU_CCGX_HID_DEVICE_RETRY_CNT,
|
|
NULL, error))
|
|
return FALSE;
|
|
fu_device_add_flag (device, FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
fu_ccgx_hid_device_setup (FuDevice *device, GError **error)
|
|
{
|
|
/* This seems insane... but we need to switch the device from HID
|
|
* mode to HPI mode at startup. The device continues to function
|
|
* exactly as before and no user-visible effects are noted */
|
|
if (!fu_device_retry (device,
|
|
fu_ccgx_hid_device_enable_hpi_mode_cb,
|
|
FU_CCGX_HID_DEVICE_RETRY_CNT,
|
|
NULL, error))
|
|
return FALSE;
|
|
|
|
/* never add this device, the daemon does not expect the device to
|
|
* disconnect before it is added */
|
|
g_set_error_literal (error,
|
|
FWUPD_ERROR,
|
|
FWUPD_ERROR_NOT_SUPPORTED,
|
|
"device is replugging into HPI mode");
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
fu_ccgx_hid_device_init (FuCcgxHidDevice *self)
|
|
{
|
|
fu_device_add_protocol (FU_DEVICE (self), "com.cypress.ccgx");
|
|
fu_device_add_flag (FU_DEVICE (self), FWUPD_DEVICE_FLAG_REQUIRE_AC);
|
|
fu_device_add_flag (FU_DEVICE (self), FWUPD_DEVICE_FLAG_WILL_DISAPPEAR);
|
|
fu_device_add_internal_flag (FU_DEVICE (self), FU_DEVICE_INTERNAL_FLAG_REPLUG_MATCH_GUID);
|
|
fu_device_retry_set_delay (FU_DEVICE (self), FU_CCGX_HID_DEVICE_RETRY_DELAY);
|
|
}
|
|
|
|
static void
|
|
fu_ccgx_hid_device_class_init (FuCcgxHidDeviceClass *klass)
|
|
{
|
|
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
|
|
klass_device->detach = fu_ccgx_hid_device_detach;
|
|
klass_device->setup = fu_ccgx_hid_device_setup;
|
|
}
|