/src/fwupd/plugins/ebitdo/fu-ebitdo-firmware.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2016 Richard Hughes <richard@hughsie.com> |
3 | | * |
4 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
5 | | */ |
6 | | |
7 | | #include "config.h" |
8 | | |
9 | | #include "fu-ebitdo-firmware.h" |
10 | | #include "fu-ebitdo-struct.h" |
11 | | |
12 | | struct _FuEbitdoFirmware { |
13 | | FuFirmwareClass parent_instance; |
14 | | }; |
15 | | |
16 | | G_DEFINE_TYPE(FuEbitdoFirmware, fu_ebitdo_firmware, FU_TYPE_FIRMWARE) |
17 | | |
18 | | static gboolean |
19 | | fu_ebitdo_firmware_parse(FuFirmware *firmware, |
20 | | GInputStream *stream, |
21 | | FuFirmwareParseFlags flags, |
22 | | GError **error) |
23 | 339 | { |
24 | 339 | guint32 payload_len; |
25 | 339 | guint32 version; |
26 | 339 | gsize streamsz = 0; |
27 | 339 | g_autoptr(FuFirmware) img_hdr = fu_firmware_new(); |
28 | 339 | g_autoptr(GByteArray) st = NULL; |
29 | 339 | g_autoptr(GInputStream) stream_hdr = NULL; |
30 | 339 | g_autoptr(GInputStream) stream_payload = NULL; |
31 | | |
32 | | /* check the file size */ |
33 | 339 | st = fu_struct_ebitdo_hdr_parse_stream(stream, 0x0, error); |
34 | 339 | if (st == NULL) |
35 | 25 | return FALSE; |
36 | 314 | if (!fu_input_stream_size(stream, &streamsz, error)) |
37 | 0 | return FALSE; |
38 | 314 | payload_len = (guint32)(streamsz - st->len); |
39 | 314 | if (payload_len != fu_struct_ebitdo_hdr_get_destination_len(st)) { |
40 | 83 | g_set_error(error, |
41 | 83 | FWUPD_ERROR, |
42 | 83 | FWUPD_ERROR_INVALID_DATA, |
43 | 83 | "file size incorrect, expected 0x%04x got 0x%04x", |
44 | 83 | (guint)fu_struct_ebitdo_hdr_get_destination_len(st), |
45 | 83 | (guint)payload_len); |
46 | 83 | return FALSE; |
47 | 83 | } |
48 | | |
49 | | /* parse version */ |
50 | 231 | version = fu_struct_ebitdo_hdr_get_version(st); |
51 | 231 | fu_firmware_set_version_raw(firmware, version); |
52 | | |
53 | | /* add header */ |
54 | 231 | stream_hdr = fu_partial_input_stream_new(stream, 0x0, st->len, error); |
55 | 231 | if (stream_hdr == NULL) |
56 | 0 | return FALSE; |
57 | 231 | if (!fu_firmware_parse_stream(img_hdr, stream_hdr, 0x0, flags, error)) |
58 | 0 | return FALSE; |
59 | 231 | fu_firmware_set_id(img_hdr, FU_FIRMWARE_ID_HEADER); |
60 | 231 | fu_firmware_add_image(firmware, img_hdr); |
61 | | |
62 | | /* add payload */ |
63 | 231 | stream_payload = fu_partial_input_stream_new(stream, st->len, payload_len, error); |
64 | 231 | if (stream_payload == NULL) |
65 | 0 | return FALSE; |
66 | 231 | if (!fu_firmware_set_stream(firmware, stream_payload, error)) |
67 | 0 | return FALSE; |
68 | 231 | fu_firmware_set_id(firmware, FU_FIRMWARE_ID_PAYLOAD); |
69 | 231 | fu_firmware_set_addr(firmware, fu_struct_ebitdo_hdr_get_destination_addr(st)); |
70 | 231 | return TRUE; |
71 | 231 | } |
72 | | |
73 | | static GByteArray * |
74 | | fu_ebitdo_firmware_write(FuFirmware *firmware, GError **error) |
75 | 231 | { |
76 | 231 | g_autoptr(GByteArray) st = fu_struct_ebitdo_hdr_new(); |
77 | 231 | g_autoptr(GBytes) blob = NULL; |
78 | | |
79 | | /* header then payload */ |
80 | 231 | blob = fu_firmware_get_bytes_with_patches(firmware, error); |
81 | 231 | if (blob == NULL) |
82 | 73 | return NULL; |
83 | 158 | fu_struct_ebitdo_hdr_set_version(st, fu_firmware_get_version_raw(firmware)); |
84 | 158 | fu_struct_ebitdo_hdr_set_destination_addr(st, fu_firmware_get_addr(firmware)); |
85 | 158 | fu_struct_ebitdo_hdr_set_destination_len(st, g_bytes_get_size(blob)); |
86 | 158 | fu_byte_array_append_bytes(st, blob); |
87 | 158 | return g_steal_pointer(&st); |
88 | 231 | } |
89 | | |
90 | | static gchar * |
91 | | fu_ebitdo_firmware_convert_version(FuFirmware *firmware, guint64 version_raw) |
92 | 231 | { |
93 | 231 | return g_strdup_printf("%.2f", version_raw / 100.f); |
94 | 231 | } |
95 | | |
96 | | static void |
97 | | fu_ebitdo_firmware_init(FuEbitdoFirmware *self) |
98 | 339 | { |
99 | 339 | fu_firmware_set_version_format(FU_FIRMWARE(self), FWUPD_VERSION_FORMAT_PAIR); |
100 | 339 | } |
101 | | |
102 | | static void |
103 | | fu_ebitdo_firmware_class_init(FuEbitdoFirmwareClass *klass) |
104 | 1 | { |
105 | 1 | FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass); |
106 | 1 | firmware_class->convert_version = fu_ebitdo_firmware_convert_version; |
107 | 1 | firmware_class->parse = fu_ebitdo_firmware_parse; |
108 | 1 | firmware_class->write = fu_ebitdo_firmware_write; |
109 | 1 | } |