mirror of
https://git.proxmox.com/git/fwupd
synced 2025-08-15 10:09:59 +00:00
Add a plugin to update PD controllers by Fresco Logic
This commit is contained in:
parent
df27f720e7
commit
1910e84c72
@ -339,6 +339,7 @@ rm ${RPM_BUILD_ROOT}%{_sbindir}/flashrom
|
|||||||
%if 0%{?enable_flashrom}
|
%if 0%{?enable_flashrom}
|
||||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_flashrom.so
|
%{_libdir}/fwupd-plugins-3/libfu_plugin_flashrom.so
|
||||||
%endif
|
%endif
|
||||||
|
%{_libdir}/fwupd-plugins-3/libfu_plugin_fresco_pd.so
|
||||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_jabra.so
|
%{_libdir}/fwupd-plugins-3/libfu_plugin_jabra.so
|
||||||
%if 0%{?have_modem_manager}
|
%if 0%{?have_modem_manager}
|
||||||
%{_libdir}/fwupd-plugins-3/libfu_plugin_modem_manager.so
|
%{_libdir}/fwupd-plugins-3/libfu_plugin_modem_manager.so
|
||||||
|
35
plugins/fresco-pd/README.md
Normal file
35
plugins/fresco-pd/README.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
Fresco PD Support
|
||||||
|
=================
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
This plugin is used to update Power Devlivery devices by Fresco.
|
||||||
|
|
||||||
|
Firmware Format
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The daemon will decompress the cabinet archive and extract a firmware blob in
|
||||||
|
an unspecifed binary format.
|
||||||
|
|
||||||
|
This plugin supports the following protocol ID:
|
||||||
|
|
||||||
|
* com.frescologic.pd
|
||||||
|
|
||||||
|
GUID Generation
|
||||||
|
---------------
|
||||||
|
|
||||||
|
These devices use the standard USB DeviceInstanceId values, e.g.
|
||||||
|
|
||||||
|
* `USB\VID_1D5C&PID_7102&REV_0001`
|
||||||
|
* `USB\VID_1D5C&PID_7102`
|
||||||
|
* `USB\VID_1D5C`
|
||||||
|
|
||||||
|
These devices also use custom GUID values, e.g.
|
||||||
|
|
||||||
|
* `USB\VID_1D5C&PID_7102&CID_01`
|
||||||
|
|
||||||
|
Vendor ID Security
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The vendor ID is set from the USB vendor, in this instance set to `USB:0x1D5C`
|
7
plugins/fresco-pd/fresco-pd.quirk
Normal file
7
plugins/fresco-pd/fresco-pd.quirk
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# FL7102
|
||||||
|
[Guid=USB\VID_1D5C&PID_7102]
|
||||||
|
Plugin = fresco_pd
|
||||||
|
|
||||||
|
# FL7112
|
||||||
|
[Guid=USB\VID_1D5C&PID_7112]
|
||||||
|
Plugin = fresco_pd
|
18
plugins/fresco-pd/fu-fresco-pd-common.c
Normal file
18
plugins/fresco-pd/fu-fresco-pd-common.c
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Fresco Logic
|
||||||
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "fu-fresco-pd-common.h"
|
||||||
|
|
||||||
|
gchar *
|
||||||
|
fu_fresco_pd_version_from_buf (const guint8 ver[4])
|
||||||
|
{
|
||||||
|
if (ver[3] == 1 || ver[3] == 2)
|
||||||
|
return g_strdup_printf ("%u.%u.%u.%u", ver[0], ver[1], ver[2], ver[3]);
|
||||||
|
return g_strdup_printf ("%u.%u.%u.%u", ver[3], ver[1], ver[2], ver[0]);
|
||||||
|
}
|
12
plugins/fresco-pd/fu-fresco-pd-common.h
Normal file
12
plugins/fresco-pd/fu-fresco-pd-common.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Fresco Logic
|
||||||
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fu-plugin.h"
|
||||||
|
|
||||||
|
gchar *fu_fresco_pd_version_from_buf (const guint8 ver[4]);
|
417
plugins/fresco-pd/fu-fresco-pd-device.c
Normal file
417
plugins/fresco-pd/fu-fresco-pd-device.c
Normal file
@ -0,0 +1,417 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Fresco Logic
|
||||||
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "fu-fresco-pd-common.h"
|
||||||
|
#include "fu-fresco-pd-device.h"
|
||||||
|
#include "fu-fresco-pd-firmware.h"
|
||||||
|
|
||||||
|
struct _FuFrescoPdDevice
|
||||||
|
{
|
||||||
|
FuUsbDevice parent_instance;
|
||||||
|
guint8 customer_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (FuFrescoPdDevice, fu_fresco_pd_device, FU_TYPE_USB_DEVICE)
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_fresco_pd_device_to_string (FuDevice *device, guint idt, GString *str)
|
||||||
|
{
|
||||||
|
FuFrescoPdDevice *self = FU_FRESCO_PD_DEVICE (device);
|
||||||
|
fu_common_string_append_ku (str, idt, "CustomerID", self->customer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_fresco_pd_device_transfer_read (FuFrescoPdDevice *self,
|
||||||
|
guint16 offset,
|
||||||
|
guint8 *buf,
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* to device */
|
||||||
|
if (g_getenv ("FWUPD_FRESCO_PD_VERBOSE") != NULL)
|
||||||
|
fu_common_dump_raw (G_LOG_DOMAIN, "read", buf, bufsz);
|
||||||
|
if (!g_usb_device_control_transfer (usb_device,
|
||||||
|
G_USB_DEVICE_DIRECTION_DEVICE_TO_HOST,
|
||||||
|
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
||||||
|
G_USB_DEVICE_RECIPIENT_DEVICE,
|
||||||
|
0x40, 0x0, offset,
|
||||||
|
buf, bufsz, &actual_length,
|
||||||
|
5000, NULL, error)) {
|
||||||
|
g_prefix_error (error, "failed to read from offset 0x%x: ", offset);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (bufsz != actual_length) {
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_NOT_SUPPORTED,
|
||||||
|
"read 0x%x bytes of 0x%x",
|
||||||
|
(guint) actual_length, bufsz);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_fresco_pd_device_transfer_write (FuFrescoPdDevice *self,
|
||||||
|
guint16 offset,
|
||||||
|
guint8 *buf,
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* to device */
|
||||||
|
if (g_getenv ("FWUPD_FRESCO_PD_VERBOSE") != NULL)
|
||||||
|
fu_common_dump_raw (G_LOG_DOMAIN, "write", buf, bufsz);
|
||||||
|
if (!g_usb_device_control_transfer (usb_device,
|
||||||
|
G_USB_DEVICE_DIRECTION_HOST_TO_DEVICE,
|
||||||
|
G_USB_DEVICE_REQUEST_TYPE_VENDOR,
|
||||||
|
G_USB_DEVICE_RECIPIENT_DEVICE,
|
||||||
|
0x41, 0x0, offset,
|
||||||
|
buf, bufsz, &actual_length,
|
||||||
|
5000, NULL, error)) {
|
||||||
|
g_prefix_error (error, "failed to write offset 0x%x: ", offset);
|
||||||
|
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
|
||||||
|
fu_fresco_pd_device_read_byte (FuFrescoPdDevice *self,
|
||||||
|
guint16 offset,
|
||||||
|
guint8 *buf,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
return fu_fresco_pd_device_transfer_read (self, offset, buf, 1, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_fresco_pd_device_write_byte (FuFrescoPdDevice *self,
|
||||||
|
guint16 offset,
|
||||||
|
guint8 buf,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
return fu_fresco_pd_device_transfer_write (self, offset, &buf, 1, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_fresco_pd_device_set_byte (FuFrescoPdDevice *self,
|
||||||
|
guint16 offset,
|
||||||
|
guint8 val,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
guint8 buf = 0x0;
|
||||||
|
if (!fu_fresco_pd_device_read_byte (self, offset, &buf, error))
|
||||||
|
return FALSE;
|
||||||
|
if (buf == val)
|
||||||
|
return TRUE;
|
||||||
|
return fu_fresco_pd_device_write_byte (self, offset, val, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_fresco_pd_device_and_byte (FuFrescoPdDevice *self,
|
||||||
|
guint16 offset,
|
||||||
|
guint8 val,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
guint8 buf = 0xff;
|
||||||
|
if (!fu_fresco_pd_device_read_byte (self, offset, &buf, error))
|
||||||
|
return FALSE;
|
||||||
|
buf &= val;
|
||||||
|
return fu_fresco_pd_device_write_byte (self, offset, buf, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_fresco_pd_device_or_byte (FuFrescoPdDevice *self,
|
||||||
|
guint16 offset,
|
||||||
|
guint8 val,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
guint8 buf;
|
||||||
|
if (!fu_fresco_pd_device_read_byte (self, offset, &buf, error))
|
||||||
|
return FALSE;
|
||||||
|
buf |= val;
|
||||||
|
return fu_fresco_pd_device_write_byte (self, offset, buf, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_fresco_pd_device_setup (FuDevice *device, GError **error)
|
||||||
|
{
|
||||||
|
FuFrescoPdDevice *self = FU_FRESCO_PD_DEVICE (device);
|
||||||
|
FuUsbDevice *usb_device = FU_USB_DEVICE (device);
|
||||||
|
guint8 ver[4] = { 0x0 };
|
||||||
|
g_autofree gchar *instance_id = NULL;
|
||||||
|
g_autofree gchar *version = NULL;
|
||||||
|
|
||||||
|
/* read existing device version */
|
||||||
|
for (guint i = 0; i < 4; i++) {
|
||||||
|
if (!fu_fresco_pd_device_transfer_read (self, 0x3000 + i, &ver[i], 1, error)) {
|
||||||
|
g_prefix_error (error, "failed to read device version [%u]: ", i);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
version = fu_fresco_pd_version_from_buf (ver);
|
||||||
|
fu_device_set_version (FU_DEVICE (self), version, FWUPD_VERSION_FORMAT_QUAD);
|
||||||
|
|
||||||
|
/* get customer ID */
|
||||||
|
self->customer_id = ver[1];
|
||||||
|
instance_id = g_strdup_printf ("USB\\VID_%04X&PID_%04X&CID_%02X",
|
||||||
|
fu_usb_device_get_vid (usb_device),
|
||||||
|
fu_usb_device_get_pid (usb_device),
|
||||||
|
self->customer_id);
|
||||||
|
fu_device_add_instance_id (device, instance_id);
|
||||||
|
|
||||||
|
/* success */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FuFirmware *
|
||||||
|
fu_fresco_pd_device_prepare_firmware (FuDevice *device,
|
||||||
|
GBytes *fw,
|
||||||
|
FwupdInstallFlags flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
FuFrescoPdDevice *self = FU_FRESCO_PD_DEVICE (device);
|
||||||
|
guint8 customer_id;
|
||||||
|
g_autoptr(FuFirmware) firmware = fu_fresco_pd_firmware_new ();
|
||||||
|
|
||||||
|
/* check size */
|
||||||
|
if (g_bytes_get_size (fw) < fu_device_get_firmware_size_min (device)) {
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"firmware too small, got 0x%x, expected >= 0x%x",
|
||||||
|
(guint) g_bytes_get_size (fw),
|
||||||
|
(guint) fu_device_get_firmware_size_min (device));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check firmware is suitable */
|
||||||
|
fu_device_set_status (device, FWUPD_STATUS_DECOMPRESSING);
|
||||||
|
if (!fu_firmware_parse (firmware, fw, flags, error))
|
||||||
|
return NULL;
|
||||||
|
customer_id = fu_fresco_pd_firmware_get_customer_id (FU_FRESCO_PD_FIRMWARE (firmware));
|
||||||
|
if (customer_id != self->customer_id) {
|
||||||
|
g_set_error (error,
|
||||||
|
FWUPD_ERROR,
|
||||||
|
FWUPD_ERROR_INVALID_FILE,
|
||||||
|
"device is incompatible with firmware x.%u.x.x",
|
||||||
|
customer_id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return g_steal_pointer (&firmware);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_fresco_pd_device_panther_reset_device (FuFrescoPdDevice *self, GError **error)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error_local = NULL;
|
||||||
|
|
||||||
|
g_debug ("resetting target device");
|
||||||
|
fu_device_set_status (FU_DEVICE (self), FWUPD_STATUS_DEVICE_RESTART);
|
||||||
|
fu_device_add_flag (FU_DEVICE (self), FWUPD_DEVICE_FLAG_WAIT_FOR_REPLUG);
|
||||||
|
|
||||||
|
/* ignore when the device reset before completing the transaction */
|
||||||
|
if (!fu_fresco_pd_device_or_byte (self, 0xA003, 1 << 3, &error_local)) {
|
||||||
|
if (g_error_matches (error_local,
|
||||||
|
G_USB_DEVICE_ERROR,
|
||||||
|
G_USB_DEVICE_ERROR_FAILED)) {
|
||||||
|
g_debug ("ignoring %s", error_local->message);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
g_propagate_prefixed_error (error, g_steal_pointer (&error_local),
|
||||||
|
"failed to reset device [%i]",
|
||||||
|
error_local->code);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_fresco_pd_device_write_firmware (FuDevice *device,
|
||||||
|
FuFirmware *firmware,
|
||||||
|
FwupdInstallFlags flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
FuFrescoPdDevice *self = FU_FRESCO_PD_DEVICE (device);
|
||||||
|
const guint8 *buf;
|
||||||
|
gsize bufsz = 0x0;
|
||||||
|
guint16 begin_addr = 0x6420;
|
||||||
|
guint8 config[3] = { 0x0 };
|
||||||
|
guint8 start_symbols[2] = { 0x0 };
|
||||||
|
g_autoptr(GBytes) fw = NULL;
|
||||||
|
|
||||||
|
/* get default blob, which we know is already bigger than FirmwareMin */
|
||||||
|
fw = fu_firmware_get_image_default_bytes (firmware, error);
|
||||||
|
if (fw == NULL)
|
||||||
|
return FALSE;
|
||||||
|
buf = g_bytes_get_data (fw, &bufsz);
|
||||||
|
|
||||||
|
/* get start symbols, and be slightly paranoid */
|
||||||
|
if (!fu_memcpy_safe (start_symbols, sizeof(start_symbols), 0x0, /* dst */
|
||||||
|
buf, bufsz, 0x4000, /* src */
|
||||||
|
sizeof(start_symbols), error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* 0xA001<bit 2> = b'0
|
||||||
|
* 0x6C00<bit 1> = b'0
|
||||||
|
* 0x6C04 = 0x08 */
|
||||||
|
fu_device_set_status (device, FWUPD_STATUS_DEVICE_BUSY);
|
||||||
|
g_debug ("disable MCU, and enable mtp write");
|
||||||
|
if (!fu_fresco_pd_device_and_byte (self, 0xa001, ~(1 << 2), error)) {
|
||||||
|
g_prefix_error (error, "failed to disable MCU bit 2: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!fu_fresco_pd_device_and_byte (self, 0x6c00, ~(1 << 1), error)) {
|
||||||
|
g_prefix_error (error, "failed to disable MCU bit 1: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!fu_fresco_pd_device_write_byte (self, 0x6c04, 0x08, error)) {
|
||||||
|
g_prefix_error (error, "failed to disable MCU: ");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill safe code in the boot code */
|
||||||
|
fu_device_set_status (device, FWUPD_STATUS_DEVICE_WRITE);
|
||||||
|
for (guint16 i = 0; i < 0x400; i += 3) {
|
||||||
|
for (guint j = 0; j < 3; j++) {
|
||||||
|
if (!fu_fresco_pd_device_read_byte (self,
|
||||||
|
begin_addr + i + j,
|
||||||
|
&config[j],
|
||||||
|
error)) {
|
||||||
|
g_prefix_error (error, "failed to read config byte %u: ", j);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (config[0] == start_symbols[0] &&
|
||||||
|
config[1] == start_symbols[1]) {
|
||||||
|
begin_addr = 0x6420 + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (config[0] == 0 && config[1] == 0 && config[2] == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_debug ("begin_addr: 0x%04x", begin_addr);
|
||||||
|
for (guint16 i = begin_addr + 3; i < begin_addr + 0x400; i += 3) {
|
||||||
|
for (guint j = 0; j < 3; j++) {
|
||||||
|
if (!fu_fresco_pd_device_read_byte (self, i + j, &config[j], error)) {
|
||||||
|
g_prefix_error (error, "failed to read config byte %u: ", j);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (config[0] == 0x74 && config[1] == 0x06 && config[2] != 0x22) {
|
||||||
|
if (!fu_fresco_pd_device_write_byte (self, i + 2, 0x22, error))
|
||||||
|
return FALSE;
|
||||||
|
} else if (config[0] == 0x6c && config[1] == 0x00 && config[2] != 0x01) {
|
||||||
|
if (!fu_fresco_pd_device_write_byte (self, i + 2, 0x01, error))
|
||||||
|
return FALSE;
|
||||||
|
} else if (config[0] == 0x00 && config[1] == 0x00 && config[2] != 0x00)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy buf offset [0 - 0x3FFFF] to mmio address [0x2000 - 0x5FFF] */
|
||||||
|
g_debug ("fill firmware body");
|
||||||
|
for (guint16 byte_index = 0; byte_index < 0x4000; byte_index++) {
|
||||||
|
if (!fu_fresco_pd_device_set_byte (self, byte_index + 0x2000, buf[byte_index], error))
|
||||||
|
return FALSE;
|
||||||
|
fu_device_set_progress_full (device, (gsize) byte_index, 0x4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write file buf 0x4200 ~ 0x4205, 6 bytes to internal address 0x6600 ~ 0x6605
|
||||||
|
* write file buf 0x4210 ~ 0x4215, 6 bytes to internal address 0x6610 ~ 0x6615
|
||||||
|
* write file buf 0x4220 ~ 0x4225, 6 bytes to internal address 0x6620 ~ 0x6625
|
||||||
|
* write file buf 0x4230, 1 byte, to internal address 0x6630 */
|
||||||
|
g_debug ("update customize data");
|
||||||
|
for (guint16 byte_index = 0; byte_index < 6; byte_index++) {
|
||||||
|
if (!fu_fresco_pd_device_set_byte (self,
|
||||||
|
0x6600 + byte_index,
|
||||||
|
buf[0x4200 + byte_index],
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_fresco_pd_device_set_byte (self,
|
||||||
|
0x6610 + byte_index,
|
||||||
|
buf[0x4210 + byte_index],
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_fresco_pd_device_set_byte (self,
|
||||||
|
0x6620 + byte_index,
|
||||||
|
buf[0x4220 + byte_index],
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (!fu_fresco_pd_device_set_byte (self, 0x6630, buf[0x4230], error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* overwrite firmware file's boot code area (0x4020 ~ 0x41ff) to the area on the device marked by begin_addr
|
||||||
|
* example: if the begin_addr = 0x6420, then copy file buf [0x4020 ~ 0x41ff] to device offset[0x6420 ~ 0x65ff] */
|
||||||
|
g_debug ("write boot configuration area");
|
||||||
|
for (guint16 byte_index = 0; byte_index < 0x1e0; byte_index += 3) {
|
||||||
|
if (!fu_fresco_pd_device_set_byte (self,
|
||||||
|
begin_addr + byte_index + 0,
|
||||||
|
buf[0x4020 + byte_index],
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_fresco_pd_device_set_byte (self,
|
||||||
|
begin_addr + byte_index + 1,
|
||||||
|
buf[0x4021 + byte_index],
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
if (!fu_fresco_pd_device_set_byte (self,
|
||||||
|
begin_addr + byte_index + 2,
|
||||||
|
buf[0x4022 + byte_index],
|
||||||
|
error))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reset the device */
|
||||||
|
return fu_fresco_pd_device_panther_reset_device (self, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_fresco_pd_device_init (FuFrescoPdDevice *self)
|
||||||
|
{
|
||||||
|
fu_device_add_icon (FU_DEVICE (self), "audio-card");
|
||||||
|
fu_device_add_flag (FU_DEVICE (self), FWUPD_DEVICE_FLAG_UPDATABLE);
|
||||||
|
fu_device_set_protocol (FU_DEVICE (self), "com.frescologic.pd");
|
||||||
|
fu_device_set_install_duration (FU_DEVICE (self), 15);
|
||||||
|
fu_device_set_remove_delay (FU_DEVICE (self), 20000);
|
||||||
|
fu_device_set_firmware_size (FU_DEVICE (self), 0x4400);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_fresco_pd_device_class_init (FuFrescoPdDeviceClass *klass)
|
||||||
|
{
|
||||||
|
FuDeviceClass *klass_device = FU_DEVICE_CLASS (klass);
|
||||||
|
klass_device->to_string = fu_fresco_pd_device_to_string;
|
||||||
|
klass_device->setup = fu_fresco_pd_device_setup;
|
||||||
|
klass_device->write_firmware = fu_fresco_pd_device_write_firmware;
|
||||||
|
klass_device->prepare_firmware = fu_fresco_pd_device_prepare_firmware;
|
||||||
|
}
|
17
plugins/fresco-pd/fu-fresco-pd-device.h
Normal file
17
plugins/fresco-pd/fu-fresco-pd-device.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fu-plugin.h"
|
||||||
|
|
||||||
|
#define FU_TYPE_FRESCO_PD_DEVICE (fu_fresco_pd_device_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (FuFrescoPdDevice, fu_fresco_pd_device, FU, FRESCO_PD_DEVICE, FuUsbDevice)
|
||||||
|
|
||||||
|
struct _FuFrescoPdDeviceClass
|
||||||
|
{
|
||||||
|
FuUsbDeviceClass parent_class;
|
||||||
|
};
|
81
plugins/fresco-pd/fu-fresco-pd-firmware.c
Normal file
81
plugins/fresco-pd/fu-fresco-pd-firmware.c
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Fresco Logic
|
||||||
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "fu-fresco-pd-common.h"
|
||||||
|
#include "fu-fresco-pd-firmware.h"
|
||||||
|
|
||||||
|
struct _FuFrescoPdFirmware {
|
||||||
|
FuFirmwareClass parent_instance;
|
||||||
|
guint8 customer_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (FuFrescoPdFirmware, fu_fresco_pd_firmware, FU_TYPE_FIRMWARE)
|
||||||
|
|
||||||
|
guint8
|
||||||
|
fu_fresco_pd_firmware_get_customer_id (FuFrescoPdFirmware *self)
|
||||||
|
{
|
||||||
|
return self->customer_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_fresco_pd_firmware_to_string (FuFirmware *firmware, guint idt, GString *str)
|
||||||
|
{
|
||||||
|
FuFrescoPdFirmware *self = FU_FRESCO_PD_FIRMWARE (firmware);
|
||||||
|
fu_common_string_append_ku (str, idt, "CustomerID", self->customer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
fu_fresco_pd_firmware_parse (FuFirmware *firmware,
|
||||||
|
GBytes *fw,
|
||||||
|
guint64 addr_start,
|
||||||
|
guint64 addr_end,
|
||||||
|
FwupdInstallFlags flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
FuFrescoPdFirmware *self = FU_FRESCO_PD_FIRMWARE (firmware);
|
||||||
|
guint8 ver[4] = { 0x0 };
|
||||||
|
gsize bufsz = 0;
|
||||||
|
const guint8 *buf = g_bytes_get_data (fw, &bufsz);
|
||||||
|
g_autofree gchar *version = NULL;
|
||||||
|
g_autoptr(FuFirmwareImage) img = fu_firmware_image_new (fw);
|
||||||
|
|
||||||
|
/* read version block */
|
||||||
|
if (!fu_memcpy_safe (ver, sizeof(ver), 0x0, /* dst */
|
||||||
|
buf, bufsz, 0x1000, /* src */
|
||||||
|
sizeof(ver), error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* customer ID is always the 2nd byte */
|
||||||
|
self->customer_id = ver[1];
|
||||||
|
|
||||||
|
/* set version number */
|
||||||
|
version = fu_fresco_pd_version_from_buf (ver);
|
||||||
|
fu_firmware_image_set_version (img, version);
|
||||||
|
fu_firmware_add_image (firmware, img);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_fresco_pd_firmware_init (FuFrescoPdFirmware *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fu_fresco_pd_firmware_class_init (FuFrescoPdFirmwareClass *klass)
|
||||||
|
{
|
||||||
|
FuFirmwareClass *klass_firmware = FU_FIRMWARE_CLASS (klass);
|
||||||
|
klass_firmware->parse = fu_fresco_pd_firmware_parse;
|
||||||
|
klass_firmware->to_string = fu_fresco_pd_firmware_to_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
FuFirmware *
|
||||||
|
fu_fresco_pd_firmware_new (void)
|
||||||
|
{
|
||||||
|
return FU_FIRMWARE (g_object_new (FU_TYPE_FRESCO_PD_FIRMWARE, NULL));
|
||||||
|
}
|
16
plugins/fresco-pd/fu-fresco-pd-firmware.h
Normal file
16
plugins/fresco-pd/fu-fresco-pd-firmware.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Fresco Logic
|
||||||
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fu-firmware.h"
|
||||||
|
|
||||||
|
#define FU_TYPE_FRESCO_PD_FIRMWARE (fu_fresco_pd_firmware_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (FuFrescoPdFirmware, fu_fresco_pd_firmware, FU, FRESCO_PD_FIRMWARE, FuFirmware)
|
||||||
|
|
||||||
|
FuFirmware *fu_fresco_pd_firmware_new (void);
|
||||||
|
guint8 fu_fresco_pd_firmware_get_customer_id (FuFrescoPdFirmware *self);
|
21
plugins/fresco-pd/fu-plugin-fresco-pd.c
Normal file
21
plugins/fresco-pd/fu-plugin-fresco-pd.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 Richard Hughes <richard@hughsie.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "fu-plugin-vfuncs.h"
|
||||||
|
#include "fu-hash.h"
|
||||||
|
|
||||||
|
#include "fu-fresco-pd-device.h"
|
||||||
|
#include "fu-fresco-pd-firmware.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
fu_plugin_init (FuPlugin *plugin)
|
||||||
|
{
|
||||||
|
fu_plugin_set_build_hash (plugin, FU_BUILD_HASH);
|
||||||
|
fu_plugin_set_device_gtype (plugin, FU_TYPE_FRESCO_PD_DEVICE);
|
||||||
|
fu_plugin_add_firmware_gtype (plugin, "fresco-pd", FU_TYPE_FRESCO_PD_FIRMWARE);
|
||||||
|
}
|
72
plugins/fresco-pd/lsusb.txt
Normal file
72
plugins/fresco-pd/lsusb.txt
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
Bus 003 Device 002: ID 1d5c:7102 Fresco Logic Generic Billboard Device
|
||||||
|
Device Descriptor:
|
||||||
|
bLength 18
|
||||||
|
bDescriptorType 1
|
||||||
|
bcdUSB 2.01
|
||||||
|
bDeviceClass 17
|
||||||
|
bDeviceSubClass 0
|
||||||
|
bDeviceProtocol 0
|
||||||
|
bMaxPacketSize0 64
|
||||||
|
idVendor 0x1d5c Fresco Logic
|
||||||
|
idProduct 0x7102
|
||||||
|
bcdDevice 1.00
|
||||||
|
iManufacturer 1 Fresco Logic, Inc
|
||||||
|
iProduct 2 Generic Billboard Device
|
||||||
|
iSerial 0
|
||||||
|
bNumConfigurations 1
|
||||||
|
Configuration Descriptor:
|
||||||
|
bLength 9
|
||||||
|
bDescriptorType 2
|
||||||
|
wTotalLength 0x0012
|
||||||
|
bNumInterfaces 1
|
||||||
|
bConfigurationValue 1
|
||||||
|
iConfiguration 0
|
||||||
|
bmAttributes 0xc0
|
||||||
|
Self Powered
|
||||||
|
MaxPower 0mA
|
||||||
|
Interface Descriptor:
|
||||||
|
bLength 9
|
||||||
|
bDescriptorType 4
|
||||||
|
bInterfaceNumber 0
|
||||||
|
bAlternateSetting 0
|
||||||
|
bNumEndpoints 0
|
||||||
|
bInterfaceClass 17
|
||||||
|
bInterfaceSubClass 0
|
||||||
|
bInterfaceProtocol 0
|
||||||
|
iInterface 0
|
||||||
|
Binary Object Store Descriptor:
|
||||||
|
bLength 5
|
||||||
|
bDescriptorType 15
|
||||||
|
wTotalLength 0x0050
|
||||||
|
bNumDeviceCaps 3
|
||||||
|
USB 2.0 Extension Device Capability:
|
||||||
|
bLength 7
|
||||||
|
bDescriptorType 16
|
||||||
|
bDevCapabilityType 2
|
||||||
|
bmAttributes 0x00000006
|
||||||
|
BESL Link Power Management (LPM) Supported
|
||||||
|
Container ID Device Capability:
|
||||||
|
bLength 20
|
||||||
|
bDescriptorType 16
|
||||||
|
bDevCapabilityType 4
|
||||||
|
bReserved 0
|
||||||
|
ContainerID {00000000-0000-0000-0000-000000000000}
|
||||||
|
Billboard Capability:
|
||||||
|
bLength 48
|
||||||
|
bDescriptorType 16
|
||||||
|
bDevCapabilityType 13
|
||||||
|
iAddtionalInfoURL 4 www.frescologic.com
|
||||||
|
bNumberOfAlternateModes 1
|
||||||
|
bPreferredAlternateMode 0
|
||||||
|
VCONN Power 0 1W
|
||||||
|
bmConfigured 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
bcdVersion 1.10
|
||||||
|
bAdditionalFailureInfo 0
|
||||||
|
bReserved 0
|
||||||
|
Alternate Modes supported by Device Container:
|
||||||
|
Alternate Mode 0 : Alternate Mode configuration successful
|
||||||
|
wSVID[0] 0x0000
|
||||||
|
bAlternateMode[0] 0
|
||||||
|
iAlternateModeString[0] 0
|
||||||
|
Device Status: 0x0001
|
||||||
|
Self Powered
|
30
plugins/fresco-pd/meson.build
Normal file
30
plugins/fresco-pd/meson.build
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
cargs = ['-DG_LOG_DOMAIN="FuPluginFrescoPd"']
|
||||||
|
|
||||||
|
install_data(['fresco-pd.quirk'],
|
||||||
|
install_dir: join_paths(datadir, 'fwupd', 'quirks.d')
|
||||||
|
)
|
||||||
|
|
||||||
|
shared_module('fu_plugin_fresco_pd',
|
||||||
|
fu_hash,
|
||||||
|
sources : [
|
||||||
|
'fu-plugin-fresco-pd.c',
|
||||||
|
'fu-fresco-pd-common.c',
|
||||||
|
'fu-fresco-pd-device.c',
|
||||||
|
'fu-fresco-pd-firmware.c',
|
||||||
|
],
|
||||||
|
include_directories : [
|
||||||
|
root_incdir,
|
||||||
|
fwupd_incdir,
|
||||||
|
fwupdplugin_incdir,
|
||||||
|
],
|
||||||
|
install : true,
|
||||||
|
install_dir: plugin_dir,
|
||||||
|
link_with : [
|
||||||
|
fwupd,
|
||||||
|
fwupdplugin,
|
||||||
|
],
|
||||||
|
c_args : cargs,
|
||||||
|
dependencies : [
|
||||||
|
plugin_deps,
|
||||||
|
],
|
||||||
|
)
|
@ -2,6 +2,7 @@ subdir('dfu')
|
|||||||
subdir('colorhug')
|
subdir('colorhug')
|
||||||
subdir('ebitdo')
|
subdir('ebitdo')
|
||||||
subdir('fastboot')
|
subdir('fastboot')
|
||||||
|
subdir('fresco-pd')
|
||||||
subdir('jabra')
|
subdir('jabra')
|
||||||
subdir('steelseries')
|
subdir('steelseries')
|
||||||
subdir('dell-dock')
|
subdir('dell-dock')
|
||||||
|
Loading…
Reference in New Issue
Block a user