Coverage Report

Created: 2025-11-11 06:44

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
0
G_DEFINE_TYPE(FuSynapticsCapeHidFirmware,
19
0
        fu_synaptics_cape_hid_firmware,
20
0
        FU_TYPE_SYNAPTICS_CAPE_FIRMWARE)
21
0
22
0
static gboolean
23
0
fu_synaptics_cape_hid_firmware_parse(FuFirmware *firmware,
24
0
             GInputStream *stream,
25
0
             FuFirmwareParseFlags flags,
26
0
             GError **error)
27
0
{
28
0
  FuSynapticsCapeHidFirmware *self = FU_SYNAPTICS_CAPE_HID_FIRMWARE(firmware);
29
0
  gsize streamsz = 0;
30
0
  g_autofree gchar *version_str = NULL;
31
0
  g_autoptr(FuFirmware) img_hdr = fu_firmware_new();
32
0
  g_autoptr(FuStructSynapticsCapeHidHdr) st = NULL;
33
0
  g_autoptr(GInputStream) stream_hdr = NULL;
34
0
  g_autoptr(GInputStream) stream_body = NULL;
35
36
  /* sanity check */
37
0
  if (!fu_input_stream_size(stream, &streamsz, error))
38
0
    return FALSE;
39
0
  if ((guint32)streamsz % 4 != 0) {
40
0
    g_set_error_literal(error,
41
0
            FWUPD_ERROR,
42
0
            FWUPD_ERROR_INVALID_FILE,
43
0
            "data not aligned to 32 bits");
44
0
    return FALSE;
45
0
  }
46
47
  /* unpack */
48
0
  st = fu_struct_synaptics_cape_hid_hdr_parse_stream(stream, 0x0, error);
49
0
  if (st == NULL)
50
0
    return FALSE;
51
0
  fu_synaptics_cape_firmware_set_vid(FU_SYNAPTICS_CAPE_FIRMWARE(self),
52
0
             fu_struct_synaptics_cape_hid_hdr_get_vid(st));
53
0
  fu_synaptics_cape_firmware_set_pid(FU_SYNAPTICS_CAPE_FIRMWARE(self),
54
0
             fu_struct_synaptics_cape_hid_hdr_get_pid(st));
55
0
  version_str = g_strdup_printf("%u.%u.%u.%u",
56
0
              fu_struct_synaptics_cape_hid_hdr_get_ver_z(st),
57
0
              fu_struct_synaptics_cape_hid_hdr_get_ver_y(st),
58
0
              fu_struct_synaptics_cape_hid_hdr_get_ver_x(st),
59
0
              fu_struct_synaptics_cape_hid_hdr_get_ver_w(st));
60
0
  fu_firmware_set_version(FU_FIRMWARE(self), version_str);
61
62
  /* top-most part of header */
63
0
  stream_hdr = fu_partial_input_stream_new(stream,
64
0
             0,
65
0
             FU_STRUCT_SYNAPTICS_CAPE_HID_HDR_OFFSET_VER_W,
66
0
             error);
67
0
  if (stream_hdr == NULL)
68
0
    return FALSE;
69
0
  if (!fu_firmware_parse_stream(img_hdr, stream_hdr, 0x0, flags, error))
70
0
    return FALSE;
71
0
  fu_firmware_set_id(img_hdr, FU_FIRMWARE_ID_HEADER);
72
0
  if (!fu_firmware_add_image(firmware, img_hdr, error))
73
0
    return FALSE;
74
75
  /* body */
76
0
  stream_body =
77
0
      fu_partial_input_stream_new(stream, st->buf->len, streamsz - st->buf->len, error);
78
0
  if (stream_body == NULL)
79
0
    return FALSE;
80
0
  if (!fu_firmware_set_stream(firmware, stream_body, error))
81
0
    return FALSE;
82
0
  fu_firmware_set_id(firmware, FU_FIRMWARE_ID_PAYLOAD);
83
0
  return TRUE;
84
0
}
85
86
static GByteArray *
87
fu_synaptics_cape_hid_firmware_write(FuFirmware *firmware, GError **error)
88
0
{
89
0
  FuSynapticsCapeHidFirmware *self = FU_SYNAPTICS_CAPE_HID_FIRMWARE(firmware);
90
0
  guint64 ver = fu_firmware_get_version_raw(firmware);
91
0
  g_autoptr(FuStructSynapticsCapeHidHdr) st_hdr = fu_struct_synaptics_cape_hid_hdr_new();
92
0
  g_autoptr(GBytes) payload = NULL;
93
94
  /* pack */
95
0
  fu_struct_synaptics_cape_hid_hdr_set_vid(
96
0
      st_hdr,
97
0
      fu_synaptics_cape_firmware_get_vid(FU_SYNAPTICS_CAPE_FIRMWARE(self)));
98
0
  fu_struct_synaptics_cape_hid_hdr_set_pid(
99
0
      st_hdr,
100
0
      fu_synaptics_cape_firmware_get_pid(FU_SYNAPTICS_CAPE_FIRMWARE(self)));
101
0
  fu_struct_synaptics_cape_hid_hdr_set_crc(st_hdr, 0xFFFF);
102
0
  fu_struct_synaptics_cape_hid_hdr_set_ver_w(st_hdr, ver >> 0);
103
0
  fu_struct_synaptics_cape_hid_hdr_set_ver_x(st_hdr, ver >> 16);
104
0
  fu_struct_synaptics_cape_hid_hdr_set_ver_y(st_hdr, ver >> 32);
105
0
  fu_struct_synaptics_cape_hid_hdr_set_ver_z(st_hdr, ver >> 48);
106
107
  /* payload */
108
0
  payload = fu_firmware_get_bytes_with_patches(firmware, error);
109
0
  if (payload == NULL)
110
0
    return NULL;
111
0
  fu_byte_array_append_bytes(st_hdr->buf, payload);
112
0
  fu_byte_array_align_up(st_hdr->buf, FU_FIRMWARE_ALIGNMENT_4, 0xFF);
113
114
0
  return g_steal_pointer(&st_hdr->buf);
115
0
}
116
117
static void
118
fu_synaptics_cape_hid_firmware_init(FuSynapticsCapeHidFirmware *self)
119
0
{
120
0
}
121
122
static void
123
fu_synaptics_cape_hid_firmware_class_init(FuSynapticsCapeHidFirmwareClass *klass)
124
0
{
125
0
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
126
0
  firmware_class->parse = fu_synaptics_cape_hid_firmware_parse;
127
0
  firmware_class->write = fu_synaptics_cape_hid_firmware_write;
128
0
}
129
130
FuFirmware *
131
fu_synaptics_cape_hid_firmware_new(void)
132
0
{
133
0
  return FU_FIRMWARE(g_object_new(FU_TYPE_SYNAPTICS_CAPE_HID_FIRMWARE, NULL));
134
0
}