Coverage Report

Created: 2026-08-13 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/plugins/genesys/fu-genesys-usbhub-firmware.c
Line
Count
Source
1
/*
2
 * Copyright 2023 Adam.Chen <Adam.Chen@genesyslogic.com.tw>
3
 * Copyright 2021 Gaƫl PORTAY <gael.portay@collabora.com>
4
 *
5
 * SPDX-License-Identifier: LGPL-2.1-or-later
6
 */
7
8
#include "config.h"
9
10
#include "fu-genesys-common.h"
11
#include "fu-genesys-usbhub-codesign-firmware.h"
12
#include "fu-genesys-usbhub-dev-firmware.h"
13
#include "fu-genesys-usbhub-firmware.h"
14
#include "fu-genesys-usbhub-pd-firmware.h"
15
#include "fu-genesys-usbhub-struct.h"
16
17
struct _FuGenesysUsbhubFirmware {
18
  FuFirmware parent_instance;
19
  FuStructGenesysTsStatic *st_static_ts;
20
  FuGenesysChip chip;
21
};
22
23
2.63k
G_DEFINE_TYPE(FuGenesysUsbhubFirmware, fu_genesys_usbhub_firmware, FU_TYPE_FIRMWARE)
24
2.63k
25
2.63k
static gboolean
26
2.63k
fu_genesys_usbhub_firmware_get_chip(FuGenesysUsbhubFirmware *self,
27
2.63k
            FuInputStream *stream,
28
2.63k
            GError **error)
29
2.63k
{
30
804
  guint8 project_ic_type[6] = {0};
31
32
  /* recognize GL3523 code base product */
33
804
  if (!fu_input_stream_read_safe(
34
804
    stream,
35
804
    project_ic_type,
36
804
    sizeof(project_ic_type),
37
804
    0, /* dst */
38
804
    GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3523 +
39
804
        FU_STRUCT_GENESYS_TS_STATIC_OFFSET_MASK_PROJECT_IC_TYPE, /* src */
40
804
    sizeof(project_ic_type),
41
804
    error))
42
22
    return FALSE;
43
44
782
  if (memcmp(project_ic_type, "3521", 4) == 0) {
45
2
    self->chip.model = ISP_MODEL_HUB_GL3521;
46
2
    self->chip.revision =
47
2
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
48
2
    return TRUE;
49
2
  }
50
51
780
  if (memcmp(project_ic_type, "3523", 4) == 0) {
52
43
    self->chip.model = ISP_MODEL_HUB_GL3523;
53
43
    self->chip.revision =
54
43
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
55
43
    return TRUE;
56
43
  }
57
58
  /* recognize GL3523PLUS */
59
737
  if (!fu_input_stream_read_safe(
60
737
    stream,
61
737
    project_ic_type,
62
737
    sizeof(project_ic_type),
63
737
    0, /* dst */
64
737
    GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3523PLUS +
65
737
        FU_STRUCT_GENESYS_TS_STATIC_OFFSET_MASK_PROJECT_IC_TYPE, /* src */
66
737
    sizeof(project_ic_type),
67
737
    error))
68
31
    return FALSE;
69
70
706
  if (memcmp(project_ic_type, "3523", 4) == 0) {
71
10
    self->chip.model = ISP_MODEL_HUB_GL3523PLUS;
72
10
    self->chip.revision =
73
10
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
74
10
    return TRUE;
75
10
  }
76
77
  /* recognize GL3590 */
78
696
  if (!fu_input_stream_read_safe(
79
696
    stream,
80
696
    project_ic_type,
81
696
    sizeof(project_ic_type),
82
696
    0, /* dst */
83
696
    GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3590 +
84
696
        FU_STRUCT_GENESYS_TS_STATIC_OFFSET_MASK_PROJECT_IC_TYPE, /* src */
85
696
    sizeof(project_ic_type),
86
696
    error))
87
3
    return FALSE;
88
89
693
  if (memcmp(project_ic_type, "3590", 4) == 0) {
90
26
    self->chip.model = ISP_MODEL_HUB_GL3590;
91
26
    self->chip.revision =
92
26
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
93
26
    return TRUE;
94
26
  }
95
96
  /* recognize GL3525 first edition */
97
667
  if (!fu_input_stream_read_safe(
98
667
    stream,
99
667
    project_ic_type,
100
667
    sizeof(project_ic_type),
101
667
    0, /* dst */
102
667
    GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3525 +
103
667
        FU_STRUCT_GENESYS_TS_STATIC_OFFSET_MASK_PROJECT_IC_TYPE, /* src */
104
667
    sizeof(project_ic_type),
105
667
    error))
106
4
    return FALSE;
107
108
663
  if (memcmp(project_ic_type, "3525", 4) == 0) {
109
37
    self->chip.model = ISP_MODEL_HUB_GL3525;
110
37
    self->chip.revision =
111
37
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
112
37
    return TRUE;
113
37
  }
114
115
  /* recognize GL3525 second edition */
116
626
  if (!fu_input_stream_read_safe(
117
626
    stream,
118
626
    project_ic_type,
119
626
    sizeof(project_ic_type),
120
626
    0, /* dst */
121
626
    GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3525_V2 +
122
626
        FU_STRUCT_GENESYS_TS_STATIC_OFFSET_MASK_PROJECT_IC_TYPE, /* src */
123
626
    sizeof(project_ic_type),
124
626
    error))
125
0
    return FALSE;
126
127
626
  if (memcmp(project_ic_type, "3525", 4) == 0) {
128
623
    self->chip.model = ISP_MODEL_HUB_GL3525;
129
623
    self->chip.revision =
130
623
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
131
623
    return TRUE;
132
623
  }
133
134
3
  g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "unsupported IC");
135
3
  return FALSE;
136
626
}
137
138
gboolean
139
fu_genesys_usbhub_firmware_verify_checksum(FuInputStream *stream, GError **error)
140
0
{
141
0
  gsize streamsz = 0;
142
0
  guint16 fw_checksum = 0;
143
0
  guint16 checksum = 0;
144
0
  g_autoptr(FuInputStream) stream_tmp = NULL;
145
146
  /* get checksum */
147
0
  if (!fu_input_stream_size(stream, &streamsz, error))
148
0
    return FALSE;
149
0
  if (streamsz < sizeof(checksum)) {
150
0
    g_set_error_literal(error,
151
0
            FWUPD_ERROR,
152
0
            FWUPD_ERROR_INVALID_FILE,
153
0
            "stream was too small");
154
0
    return FALSE;
155
0
  }
156
0
  if (!fu_input_stream_read_u16(stream,
157
0
              streamsz - sizeof(checksum),
158
0
              &fw_checksum,
159
0
              G_BIG_ENDIAN,
160
0
              error)) {
161
0
    g_prefix_error_literal(error, "failed to get checksum: ");
162
0
    return FALSE;
163
0
  }
164
165
  /* calculate checksum */
166
0
  stream_tmp = fu_partial_input_stream_new(stream, 0, streamsz - sizeof(checksum), error);
167
0
  if (stream_tmp == NULL)
168
0
    return FALSE;
169
0
  if (!fu_input_stream_compute_sum16(stream_tmp, &checksum, error))
170
0
    return FALSE;
171
0
  if (checksum != fw_checksum) {
172
0
    g_set_error(error,
173
0
          FWUPD_ERROR,
174
0
          FWUPD_ERROR_INTERNAL,
175
0
          "checksum mismatch, got 0x%04x, expected 0x%04x",
176
0
          checksum,
177
0
          fw_checksum);
178
0
    return FALSE;
179
0
  }
180
181
0
  return TRUE;
182
0
}
183
184
gboolean
185
fu_genesys_usbhub_firmware_calculate_size(FuInputStream *stream, gsize *size, GError **error)
186
25.0k
{
187
25.0k
  guint8 kbs = 0;
188
25.0k
  if (!fu_input_stream_read_u8(stream, GENESYS_USBHUB_CODE_SIZE_OFFSET, &kbs, error)) {
189
0
    g_prefix_error_literal(error, "failed to get codesize: ");
190
0
    return FALSE;
191
0
  }
192
25.0k
  if (kbs == 0) {
193
29
    g_set_error_literal(error,
194
29
            FWUPD_ERROR,
195
29
            FWUPD_ERROR_INVALID_DATA,
196
29
            "invalid codesize");
197
29
    return FALSE;
198
29
  }
199
25.0k
  if (size != NULL)
200
25.0k
    *size = 1024 * kbs;
201
25.0k
  return TRUE;
202
25.0k
}
203
204
/* nocheck:name */
205
gboolean
206
fu_genesys_usbhub_firmware_ensure_version(FuFirmware *firmware, GError **error)
207
24.8k
{
208
24.8k
  guint16 version_raw = 0;
209
24.8k
  g_autoptr(GBytes) fw = NULL;
210
211
24.8k
  fw = fu_firmware_get_bytes(firmware, error);
212
24.8k
  if (fw == NULL)
213
0
    return FALSE;
214
24.8k
  if (!fu_memread_uint16_safe(g_bytes_get_data(fw, NULL),
215
24.8k
            g_bytes_get_size(fw),
216
24.8k
            GENESYS_USBHUB_VERSION_OFFSET,
217
24.8k
            &version_raw,
218
24.8k
            G_LITTLE_ENDIAN,
219
24.8k
            error)) {
220
0
    g_prefix_error_literal(error, "failed to get version: ");
221
0
    return FALSE;
222
0
  }
223
24.8k
  fu_firmware_set_version_raw(firmware, version_raw);
224
225
  /* success */
226
24.8k
  return TRUE;
227
24.8k
}
228
229
static gboolean
230
fu_genesys_usbhub_firmware_validate(FuFirmware *firmware,
231
            FuInputStream *stream,
232
            gsize offset,
233
            GError **error)
234
872
{
235
872
  return fu_struct_genesys_firmware_hdr_validate_stream(stream, offset, error);
236
872
}
237
238
static gboolean
239
fu_genesys_usbhub_firmware_parse(FuFirmware *firmware,
240
         FuInputStream *stream,
241
         FuFirmwareParseFlags flags,
242
         GError **error)
243
804
{
244
804
  FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(firmware);
245
804
  gsize code_size = 0;
246
804
  gsize offset = 0;
247
804
  gsize streamsz = 0;
248
804
  guint32 static_ts_offset = 0;
249
804
  g_autoptr(FuInputStream) stream_trunc = NULL;
250
251
  /* get chip */
252
804
  if (!fu_genesys_usbhub_firmware_get_chip(self, stream, error)) {
253
63
    g_prefix_error_literal(error, "failed to get chip: ");
254
63
    return FALSE;
255
63
  }
256
741
  fu_firmware_set_id(firmware, fu_genesys_fw_type_to_string(FU_GENESYS_FW_TYPE_HUB));
257
741
  fu_firmware_set_idx(firmware, FU_GENESYS_FW_TYPE_HUB);
258
741
  fu_firmware_set_alignment(firmware, FU_FIRMWARE_ALIGNMENT_1K);
259
260
  /* get static tool string */
261
741
  switch (self->chip.model) {
262
2
  case ISP_MODEL_HUB_GL3521:
263
2
    static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3521;
264
2
    break;
265
43
  case ISP_MODEL_HUB_GL3523:
266
43
    static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3523;
267
43
    break;
268
10
  case ISP_MODEL_HUB_GL3523PLUS:
269
10
    static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3523PLUS;
270
10
    break;
271
26
  case ISP_MODEL_HUB_GL3590:
272
26
    static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3590;
273
26
    break;
274
660
  case ISP_MODEL_HUB_GL3525: {
275
660
    guint8 configuration = 0;
276
660
    if (!fu_input_stream_read_u8(stream,
277
660
               GENESYS_USBHUB_FW_CONFIGURATION_OFFSET,
278
660
               &configuration,
279
660
               error))
280
0
      return FALSE;
281
660
    if (configuration == GENESYS_USBHUB_FW_CONFIGURATION_NEW_FORMAT ||
282
658
        configuration == GENESYS_USBHUB_FW_CONFIGURATION_NEW_FORMAT_V2)
283
3
      static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3525_V2;
284
657
    else
285
657
      static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3525;
286
660
    break;
287
660
  }
288
0
  default:
289
0
    break;
290
741
  }
291
741
  self->st_static_ts =
292
741
      fu_struct_genesys_ts_static_parse_stream(stream, static_ts_offset, error);
293
741
  if (self->st_static_ts == NULL)
294
20
    return FALSE;
295
296
  /* deduce code size */
297
721
  switch (self->chip.model) {
298
1
  case ISP_MODEL_HUB_GL3521:
299
1
    code_size = 0x5000;
300
1
    break;
301
37
  case ISP_MODEL_HUB_GL3523: {
302
37
    if (self->chip.revision == 50) {
303
17
      if (!fu_genesys_usbhub_firmware_calculate_size(stream, &code_size, error))
304
1
        return FALSE;
305
20
    } else {
306
20
      code_size = 0x6000;
307
20
    }
308
36
    break;
309
37
  }
310
36
  case ISP_MODEL_HUB_GL3523PLUS:
311
33
  case ISP_MODEL_HUB_GL3590:
312
683
  case ISP_MODEL_HUB_GL3525: {
313
683
    if (!fu_genesys_usbhub_firmware_calculate_size(stream, &code_size, error))
314
1
      return FALSE;
315
682
    break;
316
683
  }
317
682
  default:
318
0
    break;
319
721
  }
320
321
  /* truncate to correct size */
322
719
  stream_trunc = fu_partial_input_stream_new(stream, offset, code_size, error);
323
719
  if (stream_trunc == NULL)
324
55
    return FALSE;
325
664
  if (!fu_firmware_set_stream(firmware, stream_trunc, error))
326
0
    return FALSE;
327
328
  /* calculate checksum */
329
664
  if ((flags & FU_FIRMWARE_PARSE_FLAG_IGNORE_CHECKSUM) == 0) {
330
0
    if (!fu_genesys_usbhub_firmware_verify_checksum(stream_trunc, error))
331
0
      return FALSE;
332
0
  }
333
334
  /* get firmware version */
335
664
  if (!fu_genesys_usbhub_firmware_ensure_version(firmware, error))
336
0
    return FALSE;
337
338
  /* parse remaining firmware bytes */
339
664
  if (!fu_size_checked_inc(&offset, code_size, error))
340
0
    return FALSE;
341
664
  if (!fu_input_stream_size(stream, &streamsz, error))
342
0
    return FALSE;
343
24.8k
  while (offset < streamsz) {
344
24.8k
    g_autoptr(FuFirmware) firmware_sub = NULL;
345
24.8k
    firmware_sub = fu_firmware_new_from_gtypes(stream,
346
24.8k
                 offset,
347
24.8k
                 flags | FU_FIRMWARE_PARSE_FLAG_NO_SEARCH,
348
24.8k
                 error,
349
24.8k
                 FU_TYPE_GENESYS_USBHUB_DEV_FIRMWARE,
350
24.8k
                 FU_TYPE_GENESYS_USBHUB_PD_FIRMWARE,
351
24.8k
                 FU_TYPE_GENESYS_USBHUB_CODESIGN_FIRMWARE,
352
24.8k
                 G_TYPE_INVALID);
353
24.8k
    if (firmware_sub == NULL) {
354
537
      g_prefix_error_literal(error, "fw bytes have dual hub firmware: ");
355
537
      return FALSE;
356
537
    }
357
24.2k
    fu_firmware_set_offset(firmware_sub, offset);
358
24.2k
    if (!fu_firmware_add_image(firmware, firmware_sub, error))
359
46
      return FALSE;
360
24.2k
    if (!fu_size_checked_inc(&offset, fu_firmware_get_size(firmware_sub), error))
361
0
      return FALSE;
362
24.2k
  }
363
364
  /* success */
365
81
  return TRUE;
366
664
}
367
368
static GByteArray *
369
fu_genesys_usbhub_firmware_write(FuFirmware *firmware, GError **error)
370
81
{
371
81
  FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(firmware);
372
81
  g_autoptr(GByteArray) buf = g_byte_array_new();
373
81
  guint16 code_size = 0x6000;
374
81
  guint16 checksum;
375
376
  /* fixed size */
377
81
  fu_byte_array_set_size(buf, code_size, 0x00);
378
379
  /* signature */
380
81
  if (!fu_memcpy_safe(buf->data,
381
81
          buf->len,
382
81
          FU_STRUCT_GENESYS_FIRMWARE_HDR_OFFSET_MAGIC, /* dst */
383
81
          (const guint8 *)FU_STRUCT_GENESYS_FIRMWARE_HDR_DEFAULT_MAGIC,
384
81
          FU_STRUCT_GENESYS_FIRMWARE_HDR_SIZE_MAGIC,
385
81
          0x0, /* src */
386
81
          FU_STRUCT_GENESYS_FIRMWARE_HDR_SIZE_MAGIC,
387
81
          error))
388
0
    return NULL;
389
390
  /* static tool string */
391
81
  if (self->st_static_ts != NULL) {
392
81
    if (!fu_memcpy_safe(buf->data,
393
81
            buf->len,
394
81
            GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3523, /* dst */
395
81
            self->st_static_ts->buf->data,
396
81
            self->st_static_ts->buf->len,
397
81
            0x0, /* src */
398
81
            self->st_static_ts->buf->len,
399
81
            error))
400
0
      return NULL;
401
81
  }
402
403
  /* version */
404
81
  if (!fu_memwrite_uint16_safe(buf->data,
405
81
             buf->len,
406
81
             GENESYS_USBHUB_VERSION_OFFSET,
407
81
             0x1234, /* TODO: parse from firmware version string */
408
81
             G_BIG_ENDIAN,
409
81
             error))
410
0
    return NULL;
411
412
  /* checksum */
413
81
  checksum = fu_sum16(buf->data, code_size - sizeof(checksum));
414
81
  if (!fu_memwrite_uint16_safe(buf->data,
415
81
             buf->len,
416
81
             code_size - sizeof(guint16),
417
81
             checksum,
418
81
             G_BIG_ENDIAN,
419
81
             error))
420
0
    return NULL;
421
422
  /* success */
423
81
  return g_steal_pointer(&buf);
424
81
}
425
426
static void
427
fu_genesys_usbhub_firmware_export(FuFirmware *firmware,
428
          FuFirmwareExportFlags flags,
429
          XbBuilderNode *bn)
430
0
{
431
0
  FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(firmware);
432
0
  if (self->st_static_ts != NULL) {
433
0
    FuGenesysTsVersion tool_string_version =
434
0
        fu_struct_genesys_ts_static_get_tool_string_version(self->st_static_ts);
435
0
    g_autofree gchar *mask_project_code =
436
0
        fu_struct_genesys_ts_static_get_mask_project_code(self->st_static_ts);
437
0
    g_autofree gchar *mask_project_hardware =
438
0
        fu_struct_genesys_ts_static_get_mask_project_hardware(self->st_static_ts);
439
0
    g_autofree gchar *mask_project_firmware =
440
0
        fu_struct_genesys_ts_static_get_mask_project_firmware(self->st_static_ts);
441
0
    g_autofree gchar *mask_project_ic_type =
442
0
        fu_struct_genesys_ts_static_get_mask_project_ic_type(self->st_static_ts);
443
0
    g_autofree gchar *running_project_code =
444
0
        fu_struct_genesys_ts_static_get_mask_project_code(self->st_static_ts);
445
0
    g_autofree gchar *running_project_hardware =
446
0
        fu_struct_genesys_ts_static_get_running_project_hardware(self->st_static_ts);
447
0
    g_autofree gchar *running_project_firmware =
448
0
        fu_struct_genesys_ts_static_get_running_project_firmware(self->st_static_ts);
449
0
    g_autofree gchar *running_project_ic_type =
450
0
        fu_struct_genesys_ts_static_get_running_project_ic_type(self->st_static_ts);
451
452
0
    fu_xmlb_builder_insert_kv(bn,
453
0
            "tool_string_version",
454
0
            fu_genesys_ts_version_to_string(tool_string_version));
455
0
    fu_xmlb_builder_insert_kv(bn, "mask_project_code", mask_project_code);
456
0
    if (mask_project_hardware != NULL)
457
0
      mask_project_hardware[0] += 0x11; /* '0' -> 'A'... */
458
0
    fu_xmlb_builder_insert_kv(bn, "mask_project_hardware", mask_project_hardware);
459
0
    fu_xmlb_builder_insert_kv(bn, "mask_project_firmware", mask_project_firmware);
460
0
    fu_xmlb_builder_insert_kv(bn, "mask_project_ic_type", mask_project_ic_type);
461
0
    fu_xmlb_builder_insert_kv(bn, "running_project_code", running_project_code);
462
0
    if (running_project_hardware != NULL)
463
0
      running_project_hardware[0] += 0x11; /* '0' -> 'A'... */
464
0
    fu_xmlb_builder_insert_kv(bn, "running_project_hardware", running_project_hardware);
465
0
    fu_xmlb_builder_insert_kv(bn, "running_project_firmware", running_project_firmware);
466
0
    fu_xmlb_builder_insert_kv(bn, "running_project_ic_type", running_project_ic_type);
467
0
  }
468
0
}
469
470
static gboolean
471
fu_genesys_usbhub_firmware_build(FuFirmware *firmware, XbNode *n, GError **error)
472
0
{
473
0
  FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(firmware);
474
0
  const gchar *tmp;
475
476
  /* optional properties */
477
0
  self->st_static_ts = fu_struct_genesys_ts_static_new();
478
479
0
  tmp = xb_node_query_text(n, "tool_string_version", NULL);
480
0
  if (tmp == NULL) {
481
0
    g_set_error_literal(error,
482
0
            FWUPD_ERROR,
483
0
            FWUPD_ERROR_INVALID_DATA,
484
0
            "invalid tool_string_version");
485
0
    return FALSE;
486
0
  }
487
0
  fu_struct_genesys_ts_static_set_tool_string_version(self->st_static_ts, tmp[0]);
488
489
  /* mask_project_code */
490
0
  tmp = xb_node_query_text(n, "mask_project_code", NULL);
491
0
  if (tmp != NULL) {
492
0
    gsize len = strlen(tmp);
493
0
    if (len != 4) {
494
0
      g_set_error(error,
495
0
            FWUPD_ERROR,
496
0
            FWUPD_ERROR_INVALID_DATA,
497
0
            "invalid mask_project_code %s, got 0x%x length",
498
0
            tmp,
499
0
            (guint)len);
500
0
      return FALSE;
501
0
    }
502
0
    if (!fu_struct_genesys_ts_static_set_mask_project_code(self->st_static_ts,
503
0
                       tmp,
504
0
                       error))
505
0
      return FALSE;
506
0
  }
507
508
  /* mask_project_ic_type */
509
0
  tmp = xb_node_query_text(n, "mask_project_ic_type", NULL);
510
0
  if (tmp != NULL) {
511
0
    gsize len = strlen(tmp);
512
0
    if (len != 6) {
513
0
      g_set_error(error,
514
0
            FWUPD_ERROR,
515
0
            FWUPD_ERROR_INVALID_DATA,
516
0
            "invalid mask_project_ic_type %s, got 0x%x length",
517
0
            tmp,
518
0
            (guint)len);
519
0
      return FALSE;
520
0
    }
521
0
    if (!fu_struct_genesys_ts_static_set_mask_project_ic_type(self->st_static_ts,
522
0
                    tmp,
523
0
                    error))
524
0
      return FALSE;
525
0
  }
526
527
  /* success */
528
0
  return TRUE;
529
0
}
530
531
static gchar *
532
fu_genesys_usbhub_firmware_convert_version(FuFirmware *firmware, guint64 version_raw)
533
664
{
534
664
  return fu_version_from_uint16_hex(version_raw, fu_firmware_get_version_format(firmware));
535
664
}
536
537
static void
538
fu_genesys_usbhub_firmware_init(FuGenesysUsbhubFirmware *self)
539
872
{
540
872
  fu_firmware_add_flag(FU_FIRMWARE(self), FU_FIRMWARE_FLAG_HAS_CHECKSUM);
541
872
  fu_firmware_set_version_format(FU_FIRMWARE(self), FWUPD_VERSION_FORMAT_PAIR);
542
872
}
543
544
static void
545
fu_genesys_usbhub_firmware_finalize(GObject *object)
546
872
{
547
872
  FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(object);
548
872
  if (self->st_static_ts != NULL)
549
721
    fu_struct_genesys_ts_static_unref(self->st_static_ts);
550
872
  G_OBJECT_CLASS(fu_genesys_usbhub_firmware_parent_class)->finalize(object);
551
872
}
552
553
static void
554
fu_genesys_usbhub_firmware_class_init(FuGenesysUsbhubFirmwareClass *klass)
555
1
{
556
1
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
557
1
  FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass);
558
1
  fu_firmware_add_image_gtype(firmware_class, FU_TYPE_GENESYS_USBHUB_DEV_FIRMWARE);
559
1
  fu_firmware_add_image_gtype(firmware_class, FU_TYPE_GENESYS_USBHUB_PD_FIRMWARE);
560
1
  firmware_class->convert_version = fu_genesys_usbhub_firmware_convert_version;
561
1
  object_class->finalize = fu_genesys_usbhub_firmware_finalize;
562
1
  firmware_class->validate = fu_genesys_usbhub_firmware_validate;
563
1
  firmware_class->parse = fu_genesys_usbhub_firmware_parse;
564
1
  firmware_class->export = fu_genesys_usbhub_firmware_export;
565
1
  firmware_class->build = fu_genesys_usbhub_firmware_build;
566
1
  firmware_class->write = fu_genesys_usbhub_firmware_write;
567
1
  fu_firmware_set_size_max(firmware_class, 16 * FU_MB);
568
1
}