Add a plugin to update PD controllers by Fresco Logic

This commit is contained in:
Richard Hughes 2020-01-17 11:42:21 +00:00
parent df27f720e7
commit 1910e84c72
13 changed files with 728 additions and 0 deletions

View File

@ -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

View 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`

View 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

View 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]);
}

View 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]);

View 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;
}

View 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;
};

View 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));
}

View 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);

View 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);
}

View 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

View 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,
],
)

View File

@ -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')