Coverage Report

Created: 2026-08-13 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/plugins/synaptics-cape/fu-synaptics-cape-hid-firmware.c
Line
Count
Source
1
/*
2
 * Copyright 2021 Synaptics Incorporated <simon.ho@synaptics.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#include "config.h"
8
9
#include <string.h>
10
11
#include "fu-synaptics-cape-hid-firmware.h"
12
#include "fu-synaptics-cape-struct.h"
13
14
struct _FuSynapticsCapeHidFirmware {
15
  FuSynapticsCapeFirmware parent_instance;
16
};
17
18
658
G_DEFINE_TYPE(FuSynapticsCapeHidFirmware,
19
658
        fu_synaptics_cape_hid_firmware,
20
658
        FU_TYPE_SYNAPTICS_CAPE_FIRMWARE)
21
658
22
658
static gboolean
23
658
fu_synaptics_cape_hid_firmware_parse(FuFirmware *firmware,
24
658
             FuInputStream *stream,
25
658
             FuFirmwareParseFlags flags,
26
658
             GError **error)
27
658
{
28
244
  FuSynapticsCapeHidFirmware *self = FU_SYNAPTICS_CAPE_HID_FIRMWARE(firmware);
29
244
  gsize streamsz = 0;
30
244
  g_autofree gchar *version_str = NULL;
31
244
  g_autoptr(FuFirmware) img_hdr = fu_firmware_new();
32
244
  g_autoptr(FuStructSynapticsCapeHidHdr) st = NULL;
33
244
  g_autoptr(FuInputStream) stream_hdr = NULL;
34
244
  g_autoptr(FuInputStream) stream_body = NULL;
35
36
  /* sanity check */
37
244
  if (!fu_input_stream_size(stream, &streamsz, error))
38
0
    return FALSE;
39
244
  if ((guint32)streamsz % 4 != 0) {
40
23
    g_set_error_literal(error,
41
23
            FWUPD_ERROR,
42
23
            FWUPD_ERROR_INVALID_FILE,
43
23
            "data not aligned to 32 bits");
44
23
    return FALSE;
45
23
  }
46
47
  /* unpack */
48
221
  st = fu_struct_synaptics_cape_hid_hdr_parse_stream(stream, 0x0, error);
49
221
  if (st == NULL)
50
53
    return FALSE;
51
168
  fu_synaptics_cape_firmware_set_vid(FU_SYNAPTICS_CAPE_FIRMWARE(self),
52
168
             fu_struct_synaptics_cape_hid_hdr_get_vid(st));
53
168
  fu_synaptics_cape_firmware_set_pid(FU_SYNAPTICS_CAPE_FIRMWARE(self),
54
168
             fu_struct_synaptics_cape_hid_hdr_get_pid(st));
55
168
  version_str = g_strdup_printf("%u.%u.%u.%u",
56
168
              fu_struct_synaptics_cape_hid_hdr_get_ver_z(st),
57
168
              fu_struct_synaptics_cape_hid_hdr_get_ver_y(st),
58
168
              fu_struct_synaptics_cape_hid_hdr_get_ver_x(st),
59
168
              fu_struct_synaptics_cape_hid_hdr_get_ver_w(st));
60
168
  fu_firmware_set_version(FU_FIRMWARE(self), version_str);
61
62
  /* top-most part of header */
63
168
  stream_hdr = fu_partial_input_stream_new(stream,
64
168
             0,
65
168
             FU_STRUCT_SYNAPTICS_CAPE_HID_HDR_OFFSET_VER_W,
66
168
             error);
67
168
  if (stream_hdr == NULL)
68
0
    return FALSE;
69
168
  if (!fu_firmware_parse_stream(img_hdr, stream_hdr, 0x0, flags, error))
70
0
    return FALSE;
71
168
  fu_firmware_set_id(img_hdr, FU_FIRMWARE_ID_HEADER);
72
168
  if (!fu_firmware_add_image(firmware, img_hdr, error))
73
0
    return FALSE;
74
75
  /* body */
76
168
  stream_body =
77
168
      fu_partial_input_stream_new(stream, st->buf->len, streamsz - st->buf->len, error);
78
168
  if (stream_body == NULL)
79
0
    return FALSE;
80
168
  if (!fu_firmware_set_stream(firmware, stream_body, error))
81
0
    return FALSE;
82
168
  fu_firmware_set_id(firmware, FU_FIRMWARE_ID_PAYLOAD);
83
168
  return TRUE;
84
168
}
85
86
static GByteArray *
87
fu_synaptics_cape_hid_firmware_write(FuFirmware *firmware, GError **error)
88
168
{
89
168
  FuSynapticsCapeHidFirmware *self = FU_SYNAPTICS_CAPE_HID_FIRMWARE(firmware);
90
168
  guint64 ver = fu_firmware_get_version_raw(firmware);
91
168
  g_autoptr(FuStructSynapticsCapeHidHdr) st_hdr = fu_struct_synaptics_cape_hid_hdr_new();
92
168
  g_autoptr(GBytes) payload = NULL;
93
94
  /* pack */
95
168
  fu_struct_synaptics_cape_hid_hdr_set_vid(
96
168
      st_hdr,
97
168
      fu_synaptics_cape_firmware_get_vid(FU_SYNAPTICS_CAPE_FIRMWARE(self)));
98
168
  fu_struct_synaptics_cape_hid_hdr_set_pid(
99
168
      st_hdr,
100
168
      fu_synaptics_cape_firmware_get_pid(FU_SYNAPTICS_CAPE_FIRMWARE(self)));
101
168
  fu_struct_synaptics_cape_hid_hdr_set_crc(st_hdr, 0xFFFF);
102
168
  fu_struct_synaptics_cape_hid_hdr_set_ver_w(st_hdr, ver >> 0);
103
168
  fu_struct_synaptics_cape_hid_hdr_set_ver_x(st_hdr, ver >> 16);
104
168
  fu_struct_synaptics_cape_hid_hdr_set_ver_y(st_hdr, ver >> 32);
105
168
  fu_struct_synaptics_cape_hid_hdr_set_ver_z(st_hdr, ver >> 48);
106
107
  /* payload */
108
168
  payload = fu_firmware_get_bytes_with_patches(firmware, error);
109
168
  if (payload == NULL)
110
9
    return NULL;
111
159
  fu_byte_array_append_bytes(st_hdr->buf, payload);
112
159
  fu_byte_array_align_up(st_hdr->buf, FU_FIRMWARE_ALIGNMENT_4, 0xFF);
113
114
159
  return g_steal_pointer(&st_hdr->buf);
115
168
}
116
117
static void
118
fu_synaptics_cape_hid_firmware_init(FuSynapticsCapeHidFirmware *self)
119
244
{
120
244
}
121
122
static void
123
fu_synaptics_cape_hid_firmware_class_init(FuSynapticsCapeHidFirmwareClass *klass)
124
1
{
125
1
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
126
1
  fu_firmware_add_image_gtype(firmware_class, FU_TYPE_FIRMWARE);
127
1
  firmware_class->parse = fu_synaptics_cape_hid_firmware_parse;
128
1
  firmware_class->write = fu_synaptics_cape_hid_firmware_write;
129
1
  fu_firmware_set_size_max(firmware_class, 16 * FU_MB);
130
1
}
131
132
FuFirmware *
133
fu_synaptics_cape_hid_firmware_new(void)
134
0
{
135
0
  return FU_FIRMWARE(g_object_new(FU_TYPE_SYNAPTICS_CAPE_HID_FIRMWARE, NULL));
136
0
}