/src/fwupd/libfwupdplugin/fu-usb-hid-descriptor.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2024 Richard Hughes <richard@hughsie.com> |
3 | | * |
4 | | * SPDX-License-Identifier: LGPL-2.1-or-later |
5 | | */ |
6 | | |
7 | | /** |
8 | | * FuUsbHidDescriptor: |
9 | | * |
10 | | * This object is a placeholder for the HID descriptor, and is populated with data after the |
11 | | * device has been opened. |
12 | | */ |
13 | | |
14 | | #include "config.h" |
15 | | |
16 | | #include "fu-usb-hid-descriptor-private.h" |
17 | | |
18 | | struct _FuUsbHidDescriptor { |
19 | | FuUsbDescriptor parent_instance; |
20 | | guint8 iface_number; |
21 | | gsize descriptor_length; |
22 | | GBytes *blob; |
23 | | }; |
24 | | |
25 | | static void |
26 | | fu_usb_hid_descriptor_codec_iface_init(FwupdCodecInterface *iface); |
27 | | |
28 | 123k | G_DEFINE_TYPE_EXTENDED(FuUsbHidDescriptor, |
29 | 123k | fu_usb_hid_descriptor, |
30 | 123k | FU_TYPE_USB_DESCRIPTOR, |
31 | 123k | 0, |
32 | 123k | G_IMPLEMENT_INTERFACE(FWUPD_TYPE_CODEC, |
33 | 123k | fu_usb_hid_descriptor_codec_iface_init)); |
34 | 123k | |
35 | 123k | static gboolean |
36 | 123k | fu_usb_hid_descriptor_from_json(FwupdCodec *codec, FwupdJsonObject *json_obj, GError **error) |
37 | 123k | { |
38 | 0 | FuUsbHidDescriptor *self = FU_USB_HID_DESCRIPTOR(codec); |
39 | 0 | const gchar *tmp; |
40 | |
|
41 | 0 | tmp = fwupd_json_object_get_string(json_obj, "Data", NULL); |
42 | 0 | if (tmp != NULL) { |
43 | 0 | gsize bufsz = 0; |
44 | 0 | g_autofree guchar *buf = g_base64_decode(tmp, &bufsz); |
45 | 0 | g_autoptr(GBytes) blob = g_bytes_new_take(g_steal_pointer(&buf), bufsz); |
46 | 0 | fu_usb_hid_descriptor_set_blob(self, blob); |
47 | 0 | } |
48 | | |
49 | | /* success */ |
50 | 0 | return TRUE; |
51 | 0 | } |
52 | | |
53 | | static void |
54 | | fu_usb_hid_descriptor_add_json(FwupdCodec *codec, FwupdJsonObject *json_obj, FwupdCodecFlags flags) |
55 | 0 | { |
56 | 0 | FuUsbHidDescriptor *self = FU_USB_HID_DESCRIPTOR(codec); |
57 | 0 | g_autofree gchar *str = NULL; |
58 | |
|
59 | 0 | if (self->blob == NULL) |
60 | 0 | return; |
61 | 0 | str = g_base64_encode(g_bytes_get_data(self->blob, NULL), g_bytes_get_size(self->blob)); |
62 | 0 | fwupd_json_object_add_string(json_obj, "Data", str); |
63 | 0 | } |
64 | | |
65 | | /** |
66 | | * fu_usb_hid_descriptor_get_iface_number: |
67 | | * @self: a #FuUsbHidDescriptor |
68 | | * |
69 | | * Gets the hid descriptor interface number. |
70 | | * |
71 | | * Return value: integer |
72 | | * |
73 | | * Since: 2.0.2 |
74 | | **/ |
75 | | guint8 |
76 | | fu_usb_hid_descriptor_get_iface_number(FuUsbHidDescriptor *self) |
77 | 0 | { |
78 | 0 | g_return_val_if_fail(FU_IS_USB_HID_DESCRIPTOR(self), 0); |
79 | 0 | return self->iface_number; |
80 | 0 | } |
81 | | |
82 | | /** |
83 | | * fu_usb_hid_descriptor_set_iface_number: |
84 | | * @self: a #FuUsbHidDescriptor |
85 | | * |
86 | | * Sets the hid descriptor interface number. |
87 | | * |
88 | | * Since: 2.0.2 |
89 | | **/ |
90 | | void |
91 | | fu_usb_hid_descriptor_set_iface_number(FuUsbHidDescriptor *self, guint8 iface_number) |
92 | 28.8k | { |
93 | 28.8k | g_return_if_fail(FU_IS_USB_HID_DESCRIPTOR(self)); |
94 | 28.8k | self->iface_number = iface_number; |
95 | 28.8k | } |
96 | | |
97 | | /** |
98 | | * fu_usb_hid_descriptor_get_descriptor_length: |
99 | | * @self: a #FuUsbHidDescriptor |
100 | | * |
101 | | * Gets the HID descriptor length. |
102 | | * |
103 | | * Return value: integer |
104 | | * |
105 | | * Since: 2.0.2 |
106 | | **/ |
107 | | gsize |
108 | | fu_usb_hid_descriptor_get_descriptor_length(FuUsbHidDescriptor *self) |
109 | 0 | { |
110 | 0 | g_return_val_if_fail(FU_IS_USB_HID_DESCRIPTOR(self), 0); |
111 | 0 | return self->descriptor_length; |
112 | 0 | } |
113 | | |
114 | | /** |
115 | | * fu_usb_hid_descriptor_get_blob: |
116 | | * @self: a #FuUsbHidDescriptor |
117 | | * |
118 | | * Gets the HID descriptor binary blob. |
119 | | * |
120 | | * Return value: (transfer none): The descriptor data |
121 | | * |
122 | | * Since: 2.0.2 |
123 | | **/ |
124 | | GBytes * |
125 | | fu_usb_hid_descriptor_get_blob(FuUsbHidDescriptor *self) |
126 | 0 | { |
127 | 0 | g_return_val_if_fail(FU_IS_USB_HID_DESCRIPTOR(self), NULL); |
128 | 0 | return self->blob; |
129 | 0 | } |
130 | | |
131 | | /** |
132 | | * fu_usb_hid_descriptor_set_blob: |
133 | | * @self: a #FuUsbHidDescriptor |
134 | | * |
135 | | * Sets the HID descriptor binary blob. |
136 | | * |
137 | | * Since: 2.0.2 |
138 | | **/ |
139 | | void |
140 | | fu_usb_hid_descriptor_set_blob(FuUsbHidDescriptor *self, GBytes *blob) |
141 | 0 | { |
142 | 0 | g_return_if_fail(FU_IS_USB_HID_DESCRIPTOR(self)); |
143 | 0 | if (self->blob != NULL) |
144 | 0 | g_bytes_unref(self->blob); |
145 | 0 | self->blob = g_bytes_ref(blob); |
146 | 0 | } |
147 | | |
148 | | static gboolean |
149 | | fu_usb_hid_descriptor_parse(FuFirmware *firmware, |
150 | | GInputStream *stream, |
151 | | FuFirmwareParseFlags flags, |
152 | | GError **error) |
153 | 31.6k | { |
154 | 31.6k | FuUsbHidDescriptor *self = FU_USB_HID_DESCRIPTOR(firmware); |
155 | 31.6k | g_autoptr(FuUsbHidDescriptorHdr) st = NULL; |
156 | | |
157 | | /* parse */ |
158 | 31.6k | st = fu_usb_hid_descriptor_hdr_parse_stream(stream, 0x0, error); |
159 | 31.6k | if (st == NULL) |
160 | 16 | return FALSE; |
161 | 31.6k | self->descriptor_length = fu_usb_hid_descriptor_hdr_get_class_descriptor_length(st); |
162 | | |
163 | | /* success */ |
164 | 31.6k | return TRUE; |
165 | 31.6k | } |
166 | | |
167 | | static void |
168 | | fu_usb_hid_descriptor_codec_iface_init(FwupdCodecInterface *iface) |
169 | 1 | { |
170 | 1 | iface->add_json = fu_usb_hid_descriptor_add_json; |
171 | 1 | iface->from_json = fu_usb_hid_descriptor_from_json; |
172 | 1 | } |
173 | | |
174 | | static void |
175 | | fu_usb_hid_descriptor_init(FuUsbHidDescriptor *self) |
176 | 31.6k | { |
177 | 31.6k | } |
178 | | |
179 | | static void |
180 | | fu_usb_hid_descriptor_finalize(GObject *object) |
181 | 31.6k | { |
182 | 31.6k | FuUsbHidDescriptor *self = FU_USB_HID_DESCRIPTOR(object); |
183 | 31.6k | if (self->blob != NULL) |
184 | 0 | g_bytes_unref(self->blob); |
185 | 31.6k | G_OBJECT_CLASS(fu_usb_hid_descriptor_parent_class)->finalize(object); |
186 | 31.6k | } |
187 | | |
188 | | static void |
189 | | fu_usb_hid_descriptor_class_init(FuUsbHidDescriptorClass *klass) |
190 | 1 | { |
191 | 1 | GObjectClass *object_class = G_OBJECT_CLASS(klass); |
192 | 1 | FuFirmwareClass *firmware_class = FU_FIRMWARE_CLASS(klass); |
193 | 1 | object_class->finalize = fu_usb_hid_descriptor_finalize; |
194 | 1 | firmware_class->parse = fu_usb_hid_descriptor_parse; |
195 | 1 | } |