fwupd/libfwupdplugin/fu-usb-device-ms-ds20.c
Richard Hughes bfebede490 Add support for platform capability descriptors so devices can set quirks
This feature adds support for platform capability BOS descriptors which allows
the device itself to ship quirk data.

Use `sudo fwupdtool get-devices --save-backends=FILENAME` to save fake backend
devices to a file. This allows easy creation of self tests that do not require
physical hardware.
2022-09-13 12:07:35 +01:00

120 lines
3.1 KiB
C

/*
* Copyright (C) 2022 Richard Hughes <richard@hughsie.com>
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#include "config.h"
#include "fu-mem.h"
#include "fu-usb-device-ms-ds20.h"
struct _FuUsbDeviceMsDs20 {
FuUsbDeviceDs20 parent_instance;
};
G_DEFINE_TYPE(FuUsbDeviceMsDs20, fu_usb_device_ms_ds20, FU_TYPE_USB_DEVICE_DS20)
#define USB_OS_20_SET_HEADER_DESCRIPTOR 0x00
#define USB_OS_20_SUBSET_HEADER_CONFIGURATION 0x01
#define USB_OS_20_SUBSET_HEADER_FUNCTION 0x02
#define USB_OS_20_FEATURE_COMPATBLE_ID 0x03
#define USB_OS_20_FEATURE_REG_PROPERTY 0x04
#define USB_OS_20_FEATURE_MIN_RESUME_TIME 0x05
#define USB_OS_20_FEATURE_MODEL_ID 0x06
#define USB_OS_20_FEATURE_CCGP_DEVICE 0x07
#define USB_OS_20_FEATURE_VENDOR_REVISION 0x08
static const gchar *
fu_usb_device_os20_type_to_string(guint16 type)
{
if (type == USB_OS_20_SET_HEADER_DESCRIPTOR)
return "set-header-descriptor";
if (type == USB_OS_20_SUBSET_HEADER_CONFIGURATION)
return "subset-header-configuration";
if (type == USB_OS_20_SUBSET_HEADER_FUNCTION)
return "subset-header-function";
if (type == USB_OS_20_FEATURE_COMPATBLE_ID)
return "feature-compatble-id";
if (type == USB_OS_20_FEATURE_REG_PROPERTY)
return "feature-reg-property";
if (type == USB_OS_20_FEATURE_MIN_RESUME_TIME)
return "feature-min-resume-time";
if (type == USB_OS_20_FEATURE_MODEL_ID)
return "feature-model-id";
if (type == USB_OS_20_FEATURE_CCGP_DEVICE)
return "feature-ccgp-device";
if (type == USB_OS_20_FEATURE_VENDOR_REVISION)
return "feature-vendor-revision";
return NULL;
}
static gboolean
fu_usb_device_ms_ds20_parse(FuUsbDeviceDs20 *self,
GBytes *blob,
FuUsbDevice *device,
GError **error)
{
gsize bufsz = 0;
const guint8 *buf = g_bytes_get_data(blob, &bufsz);
/* get length and type only */
for (gsize offset = 0; offset < bufsz;) {
guint16 desc_sz = 0;
guint16 desc_type = 0;
if (!fu_memread_uint16_safe(buf,
bufsz,
offset + 0x0,
&desc_sz,
G_LITTLE_ENDIAN,
error))
return FALSE;
if (desc_sz == 0)
break;
if (!fu_memread_uint16_safe(buf,
bufsz,
offset + 0x2,
&desc_type,
G_LITTLE_ENDIAN,
error))
return FALSE;
g_debug("USB OS descriptor type 0x%04x [%s], length 0x%04x",
desc_type,
fu_usb_device_os20_type_to_string(desc_type),
desc_sz);
offset += desc_sz;
}
/* success */
return TRUE;
}
static void
fu_usb_device_ms_ds20_class_init(FuUsbDeviceMsDs20Class *klass)
{
FuUsbDeviceDs20Class *usb_device_ds20_klass = FU_USB_DEVICE_DS20_CLASS(klass);
usb_device_ds20_klass->parse = fu_usb_device_ms_ds20_parse;
}
static void
fu_usb_device_ms_ds20_init(FuUsbDeviceMsDs20 *self)
{
fu_firmware_set_version_raw(FU_FIRMWARE(self), 0x06030000); /* Windows 8.1 */
fu_firmware_set_id(FU_FIRMWARE(self), "d8dd60df-4589-4cc7-9cd2-659d9e648a9f");
}
/**
* fu_usb_device_ms_ds20_new:
*
* Creates a new #FuUsbDeviceMsDs20.
*
* Returns: (transfer full): a #FuFirmware
*
* Since: 1.8.5
**/
FuFirmware *
fu_usb_device_ms_ds20_new(void)
{
return g_object_new(FU_TYPE_USB_DEVICE_MS_DS20, NULL);
}