Coverage Report

Created: 2026-10-17 07:48

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
837
G_DEFINE_TYPE(FuGenesysUsbhubFirmware, fu_genesys_usbhub_firmware, FU_TYPE_FIRMWARE)
24
837
25
837
static gboolean
26
837
fu_genesys_usbhub_firmware_get_chip(FuGenesysUsbhubFirmware *self,
27
837
            FuInputStream *stream,
28
837
            GError **error)
29
837
{
30
766
  guint8 project_ic_type[6] = {0};
31
32
  /* recognize GL3523 code base product */
33
766
  if (!fu_input_stream_read_safe(
34
766
    stream,
35
766
    project_ic_type,
36
766
    sizeof(project_ic_type),
37
766
    0, /* dst */
38
766
    GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3523 +
39
766
        FU_STRUCT_GENESYS_TS_STATIC_OFFSET_MASK_PROJECT_IC_TYPE, /* src */
40
766
    sizeof(project_ic_type),
41
766
    error))
42
16
    return FALSE;
43
44
750
  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
748
  if (memcmp(project_ic_type, "3523", 4) == 0) {
52
42
    self->chip.model = ISP_MODEL_HUB_GL3523;
53
42
    self->chip.revision =
54
42
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
55
42
    return TRUE;
56
42
  }
57
58
  /* recognize GL3523PLUS */
59
706
  if (!fu_input_stream_read_safe(
60
706
    stream,
61
706
    project_ic_type,
62
706
    sizeof(project_ic_type),
63
706
    0, /* dst */
64
706
    GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3523PLUS +
65
706
        FU_STRUCT_GENESYS_TS_STATIC_OFFSET_MASK_PROJECT_IC_TYPE, /* src */
66
706
    sizeof(project_ic_type),
67
706
    error))
68
29
    return FALSE;
69
70
677
  if (memcmp(project_ic_type, "3523", 4) == 0) {
71
18
    self->chip.model = ISP_MODEL_HUB_GL3523PLUS;
72
18
    self->chip.revision =
73
18
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
74
18
    return TRUE;
75
18
  }
76
77
  /* recognize GL3590 */
78
659
  if (!fu_input_stream_read_safe(
79
659
    stream,
80
659
    project_ic_type,
81
659
    sizeof(project_ic_type),
82
659
    0, /* dst */
83
659
    GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3590 +
84
659
        FU_STRUCT_GENESYS_TS_STATIC_OFFSET_MASK_PROJECT_IC_TYPE, /* src */
85
659
    sizeof(project_ic_type),
86
659
    error))
87
2
    return FALSE;
88
89
657
  if (memcmp(project_ic_type, "3590", 4) == 0) {
90
14
    self->chip.model = ISP_MODEL_HUB_GL3590;
91
14
    self->chip.revision =
92
14
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
93
14
    return TRUE;
94
14
  }
95
96
  /* recognize GL3525 first edition */
97
643
  if (!fu_input_stream_read_safe(
98
643
    stream,
99
643
    project_ic_type,
100
643
    sizeof(project_ic_type),
101
643
    0, /* dst */
102
643
    GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3525 +
103
643
        FU_STRUCT_GENESYS_TS_STATIC_OFFSET_MASK_PROJECT_IC_TYPE, /* src */
104
643
    sizeof(project_ic_type),
105
643
    error))
106
2
    return FALSE;
107
108
641
  if (memcmp(project_ic_type, "3525", 4) == 0) {
109
45
    self->chip.model = ISP_MODEL_HUB_GL3525;
110
45
    self->chip.revision =
111
45
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
112
45
    return TRUE;
113
45
  }
114
115
  /* recognize GL3525 second edition */
116
596
  if (!fu_input_stream_read_safe(
117
596
    stream,
118
596
    project_ic_type,
119
596
    sizeof(project_ic_type),
120
596
    0, /* dst */
121
596
    GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3525_V2 +
122
596
        FU_STRUCT_GENESYS_TS_STATIC_OFFSET_MASK_PROJECT_IC_TYPE, /* src */
123
596
    sizeof(project_ic_type),
124
596
    error))
125
0
    return FALSE;
126
127
596
  if (memcmp(project_ic_type, "3525", 4) == 0) {
128
593
    self->chip.model = ISP_MODEL_HUB_GL3525;
129
593
    self->chip.revision =
130
593
        (10 * (project_ic_type[4] - '0')) + (project_ic_type[5] - '0');
131
593
    return TRUE;
132
593
  }
133
134
3
  g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED, "unsupported IC");
135
3
  return FALSE;
136
596
}
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
21.9k
{
187
21.9k
  guint8 kbs = 0;
188
21.9k
  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
21.9k
  if (kbs == 0) {
193
46
    g_set_error_literal(error,
194
46
            FWUPD_ERROR,
195
46
            FWUPD_ERROR_INVALID_DATA,
196
46
            "invalid codesize");
197
46
    return FALSE;
198
46
  }
199
21.8k
  if (size != NULL)
200
21.8k
    *size = 1024 * kbs;
201
21.8k
  return TRUE;
202
21.9k
}
203
204
/* nocheck:name */
205
gboolean
206
fu_genesys_usbhub_firmware_ensure_version(FuFirmware *firmware, GError **error)
207
21.7k
{
208
21.7k
  guint16 version_raw = 0;
209
21.7k
  g_autoptr(GBytes) fw = NULL;
210
211
21.7k
  fw = fu_firmware_get_bytes(firmware, error);
212
21.7k
  if (fw == NULL)
213
0
    return FALSE;
214
21.7k
  if (!fu_memread_uint16_safe(g_bytes_get_data(fw, NULL),
215
21.7k
            g_bytes_get_size(fw),
216
21.7k
            GENESYS_USBHUB_VERSION_OFFSET,
217
21.7k
            &version_raw,
218
21.7k
            G_LITTLE_ENDIAN,
219
21.7k
            error)) {
220
0
    g_prefix_error_literal(error, "failed to get version: ");
221
0
    return FALSE;
222
0
  }
223
21.7k
  fu_firmware_set_version_raw(firmware, version_raw);
224
225
  /* success */
226
21.7k
  return TRUE;
227
21.7k
}
228
229
static gboolean
230
fu_genesys_usbhub_firmware_validate(FuFirmware *firmware,
231
            FuInputStream *stream,
232
            gsize offset,
233
            GError **error)
234
835
{
235
835
  return fu_struct_genesys_firmware_hdr_validate_stream(stream, offset, error);
236
835
}
237
238
static gboolean
239
fu_genesys_usbhub_firmware_parse(FuFirmware *firmware,
240
         FuInputStream *stream,
241
         FuFirmwareParseFlags flags,
242
         GError **error)
243
766
{
244
766
  FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(firmware);
245
766
  gsize code_size = 0;
246
766
  gsize offset = 0;
247
766
  gsize streamsz = 0;
248
766
  guint32 static_ts_offset = 0;
249
766
  g_autoptr(FuInputStream) stream_trunc = NULL;
250
251
  /* get chip */
252
766
  if (!fu_genesys_usbhub_firmware_get_chip(self, stream, error)) {
253
52
    g_prefix_error_literal(error, "failed to get chip: ");
254
52
    return FALSE;
255
52
  }
256
714
  fu_firmware_set_id(firmware, fu_genesys_fw_type_to_string(FU_GENESYS_FW_TYPE_HUB));
257
714
  fu_firmware_set_idx(firmware, FU_GENESYS_FW_TYPE_HUB);
258
714
  fu_firmware_set_alignment(firmware, FU_FIRMWARE_ALIGNMENT_1K);
259
260
  /* get static tool string */
261
714
  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
42
  case ISP_MODEL_HUB_GL3523:
266
42
    static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3523;
267
42
    break;
268
18
  case ISP_MODEL_HUB_GL3523PLUS:
269
18
    static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3523PLUS;
270
18
    break;
271
14
  case ISP_MODEL_HUB_GL3590:
272
14
    static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3590;
273
14
    break;
274
638
  case ISP_MODEL_HUB_GL3525: {
275
638
    guint8 configuration = 0;
276
638
    if (!fu_input_stream_read_u8(stream,
277
638
               GENESYS_USBHUB_FW_CONFIGURATION_OFFSET,
278
638
               &configuration,
279
638
               error))
280
0
      return FALSE;
281
638
    if (configuration == GENESYS_USBHUB_FW_CONFIGURATION_NEW_FORMAT ||
282
637
        configuration == GENESYS_USBHUB_FW_CONFIGURATION_NEW_FORMAT_V2)
283
2
      static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3525_V2;
284
636
    else
285
636
      static_ts_offset = GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3525;
286
638
    break;
287
638
  }
288
0
  default:
289
0
    break;
290
714
  }
291
714
  self->st_static_ts =
292
714
      fu_struct_genesys_ts_static_parse_stream(stream, static_ts_offset, error);
293
714
  if (self->st_static_ts == NULL)
294
19
    return FALSE;
295
296
  /* deduce code size */
297
695
  switch (self->chip.model) {
298
1
  case ISP_MODEL_HUB_GL3521:
299
1
    code_size = 0x5000;
300
1
    break;
301
36
  case ISP_MODEL_HUB_GL3523: {
302
36
    if (self->chip.revision == 50) {
303
15
      if (!fu_genesys_usbhub_firmware_calculate_size(stream, &code_size, error))
304
1
        return FALSE;
305
21
    } else {
306
21
      code_size = 0x6000;
307
21
    }
308
35
    break;
309
36
  }
310
35
  case ISP_MODEL_HUB_GL3523PLUS:
311
30
  case ISP_MODEL_HUB_GL3590:
312
658
  case ISP_MODEL_HUB_GL3525: {
313
658
    if (!fu_genesys_usbhub_firmware_calculate_size(stream, &code_size, error))
314
1
      return FALSE;
315
657
    break;
316
658
  }
317
657
  default:
318
0
    break;
319
695
  }
320
321
  /* truncate to correct size */
322
693
  stream_trunc = fu_partial_input_stream_new(stream, offset, code_size, error);
323
693
  if (stream_trunc == NULL)
324
52
    return FALSE;
325
641
  if (!fu_firmware_set_stream(firmware, stream_trunc, error))
326
0
    return FALSE;
327
328
  /* calculate checksum */
329
641
  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
641
  if (!fu_genesys_usbhub_firmware_ensure_version(firmware, error))
336
0
    return FALSE;
337
338
  /* parse remaining firmware bytes */
339
641
  if (!fu_size_checked_inc(&offset, code_size, error))
340
0
    return FALSE;
341
641
  if (!fu_input_stream_size(stream, &streamsz, error))
342
0
    return FALSE;
343
21.7k
  while (offset < streamsz) {
344
21.6k
    g_autoptr(FuFirmware) firmware_sub = NULL;
345
21.6k
    firmware_sub = fu_firmware_new_from_gtypes(stream,
346
21.6k
                 offset,
347
21.6k
                 flags | FU_FIRMWARE_PARSE_FLAG_NO_SEARCH,
348
21.6k
                 error,
349
21.6k
                 FU_TYPE_GENESYS_USBHUB_DEV_FIRMWARE,
350
21.6k
                 FU_TYPE_GENESYS_USBHUB_PD_FIRMWARE,
351
21.6k
                 FU_TYPE_GENESYS_USBHUB_CODESIGN_FIRMWARE,
352
21.6k
                 G_TYPE_INVALID);
353
21.6k
    if (firmware_sub == NULL) {
354
549
      g_prefix_error_literal(error, "fw bytes have dual hub firmware: ");
355
549
      return FALSE;
356
549
    }
357
21.1k
    fu_firmware_set_offset(firmware_sub, offset);
358
21.1k
    if (!fu_firmware_add_image(firmware, firmware_sub, error))
359
36
      return FALSE;
360
21.0k
    if (!fu_size_checked_inc(&offset, fu_firmware_get_size(firmware_sub), error))
361
0
      return FALSE;
362
21.0k
  }
363
364
  /* success */
365
56
  return TRUE;
366
641
}
367
368
static GByteArray *
369
fu_genesys_usbhub_firmware_write(FuFirmware *firmware, GError **error)
370
56
{
371
56
  FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(firmware);
372
56
  g_autoptr(GByteArray) buf = g_byte_array_new();
373
56
  guint16 code_size = 0x6000;
374
56
  guint16 checksum;
375
376
  /* fixed size */
377
56
  fu_byte_array_set_size(buf, code_size, 0x00);
378
379
  /* signature */
380
56
  if (!fu_memcpy_safe(buf->data,
381
56
          buf->len,
382
56
          FU_STRUCT_GENESYS_FIRMWARE_HDR_OFFSET_MAGIC, /* dst */
383
56
          (const guint8 *)FU_STRUCT_GENESYS_FIRMWARE_HDR_DEFAULT_MAGIC,
384
56
          FU_STRUCT_GENESYS_FIRMWARE_HDR_SIZE_MAGIC,
385
56
          0x0, /* src */
386
56
          FU_STRUCT_GENESYS_FIRMWARE_HDR_SIZE_MAGIC,
387
56
          error))
388
0
    return NULL;
389
390
  /* static tool string */
391
56
  if (self->st_static_ts != NULL) {
392
56
    if (!fu_memcpy_safe(buf->data,
393
56
            buf->len,
394
56
            GENESYS_USBHUB_STATIC_TOOL_STRING_OFFSET_GL3523, /* dst */
395
56
            self->st_static_ts->buf->data,
396
56
            self->st_static_ts->buf->len,
397
56
            0x0, /* src */
398
56
            self->st_static_ts->buf->len,
399
56
            error))
400
0
      return NULL;
401
56
  }
402
403
  /* version */
404
56
  if (!fu_memwrite_uint16_safe(buf->data,
405
56
             buf->len,
406
56
             GENESYS_USBHUB_VERSION_OFFSET,
407
56
             0x1234, /* TODO: parse from firmware version string */
408
56
             G_BIG_ENDIAN,
409
56
             error))
410
0
    return NULL;
411
412
  /* checksum */
413
56
  checksum = fu_sum16(buf->data, code_size - sizeof(checksum));
414
56
  if (!fu_memwrite_uint16_safe(buf->data,
415
56
             buf->len,
416
56
             code_size - sizeof(guint16),
417
56
             checksum,
418
56
             G_BIG_ENDIAN,
419
56
             error))
420
0
    return NULL;
421
422
  /* success */
423
56
  return g_steal_pointer(&buf);
424
56
}
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
641
{
534
641
  return fu_version_from_uint16_hex(version_raw, fu_firmware_get_version_format(firmware));
535
641
}
536
537
static void
538
fu_genesys_usbhub_firmware_init(FuGenesysUsbhubFirmware *self)
539
835
{
540
835
  fu_firmware_add_flag(FU_FIRMWARE(self), FU_FIRMWARE_FLAG_HAS_CHECKSUM);
541
835
  fu_firmware_set_version_format(FU_FIRMWARE(self), FWUPD_VERSION_FORMAT_PAIR);
542
835
}
543
544
static void
545
fu_genesys_usbhub_firmware_finalize(GObject *object)
546
835
{
547
835
  FuGenesysUsbhubFirmware *self = FU_GENESYS_USBHUB_FIRMWARE(object);
548
835
  if (self->st_static_ts != NULL)
549
695
    fu_struct_genesys_ts_static_unref(self->st_static_ts);
550
835
  G_OBJECT_CLASS(fu_genesys_usbhub_firmware_parent_class)->finalize(object);
551
835
}
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
}