Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
nbgl_serialize.c
Go to the documentation of this file.
1#include <stdio.h>
2#include <string.h>
3#include "nbgl_obj.h"
4#include "nbgl_serialize.h"
5#include "nbgl_image_utils.h"
6#include "os_pic.h"
7
8// Utility functions
9
10static void nbgl_appendU8(uint8_t value, uint8_t *out, size_t *w_cnt, size_t max_len)
11{
12 if (*w_cnt < max_len) {
13 out[*w_cnt] = value;
14 (*w_cnt)++;
15 }
16}
17
18static void nbgl_appendU32(uint32_t value, uint8_t *out, size_t *w_cnt, size_t max_len)
19{
20 nbgl_appendU8((uint8_t) ((value >> 24) & 0xFF), out, w_cnt, max_len);
21 nbgl_appendU8((uint8_t) ((value >> 16) & 0xFF), out, w_cnt, max_len);
22 nbgl_appendU8((uint8_t) ((value >> 8) & 0xFF), out, w_cnt, max_len);
23 nbgl_appendU8((uint8_t) (value & 0xFF), out, w_cnt, max_len);
24}
25
26static void nbgl_appendPtr(const void *value, uint8_t *out, size_t *w_cnt, size_t max_len)
27{
28 if (max_len < (*w_cnt + sizeof(void *))) {
29 return;
30 }
31 memcpy(&out[*w_cnt], &value, sizeof(void *));
32 (*w_cnt) = (*w_cnt) + sizeof(void *);
33}
34
35static void nbgl_appendU16(uint16_t value, uint8_t *out, size_t *w_cnt, size_t max_len)
36{
37 nbgl_appendU8((uint8_t) ((value >> 8) & 0xFF), out, w_cnt, max_len);
38 nbgl_appendU8((uint8_t) (value & 0xFF), out, w_cnt, max_len);
39}
40
41// serialize a nbgl_area_t structure
42static void nbgl_serializeArea(nbgl_area_t *area, uint8_t *out, size_t *w_cnt, size_t max_len)
43{
44 nbgl_appendU16(area->x0, out, w_cnt, max_len);
45 nbgl_appendU16(area->y0, out, w_cnt, max_len);
46 nbgl_appendU16(area->width, out, w_cnt, max_len);
47 nbgl_appendU16(area->height, out, w_cnt, max_len);
48 nbgl_appendU8((uint8_t) area->backgroundColor, out, w_cnt, max_len);
49 nbgl_appendU8((uint8_t) area->bpp, out, w_cnt, max_len);
50}
51
52static uint8_t getObjId(nbgl_obj_t *obj)
53{
54 if (obj->type != SCREEN) {
55 // return the internal offset + 1
56 return nbgl_objPoolGetId(obj) + 1;
57 }
58 // no ID for screen, because it's not a real object, and not taken from pool
59 return 0;
60}
61
62// serialize a nbgl_obj_t structure (including nbgl_area_t)
63static void nbgl_serializeObj(nbgl_obj_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
64{
65 // at first serialize an id
66 nbgl_appendU8(getObjId(obj), out, w_cnt, max_len);
67 // the only field to be serialized is the object type
68 nbgl_appendU8((uint8_t) obj->type, out, w_cnt, max_len);
69 // then serialize the area
70 nbgl_serializeArea((nbgl_area_t *) &obj->area, out, w_cnt, max_len);
71}
72
73// Serialization functions
74
75static void nbgl_serializeText(const char *text,
76 uint16_t text_len,
77 uint8_t *out,
78 size_t *w_cnt,
79 size_t max_len)
80{
81 if (text == NULL) {
82 nbgl_appendU8('\0', out, w_cnt, max_len);
83 return;
84 }
85 while (*w_cnt < max_len) {
86 nbgl_appendU8(*text, out, w_cnt, max_len);
87 // if the text_len is provided, use it
88 if (text_len > 0) {
89 text_len--;
90 if (text_len == 0) {
91 return;
92 }
93 }
94 if (*text == '\0') {
95 return;
96 }
97 else {
98 text++;
99 }
100 }
101}
102
107static const uint8_t NBGL_BPP_MAPPING[NB_NBGL_BPP]
108 = {[NBGL_BPP_1] = 1, [NBGL_BPP_2] = 2, [NBGL_BPP_4] = 4};
109
118static int8_t nbgl_bpp_get_number_of_bits_per_pixel(nbgl_bpp_t nbgl_bpp)
119{
120 if (nbgl_bpp >= NB_NBGL_BPP) {
121 return -1;
122 }
123
124 return NBGL_BPP_MAPPING[nbgl_bpp];
125}
126
137static int32_t nbgl_bpp_get_window_size(uint16_t width, uint16_t height, nbgl_bpp_t nbgl_bpp)
138{
139 if ((width > SCREEN_WIDTH) || (height > SCREEN_HEIGHT) || (nbgl_bpp >= NB_NBGL_BPP)) {
140 return -1;
141 }
142
143 int32_t nb_bits = (width * height * nbgl_bpp_get_number_of_bits_per_pixel(nbgl_bpp));
144 uint8_t remain = nb_bits % 8;
145
146 // Ceil division to ensure the output number of bytes contains
147 // all the bits of the window.
148 if (remain == 0) {
149 return nb_bits / 8;
150 }
151 else {
152 return (nb_bits + (8 - remain)) / 8;
153 }
154}
155
156static void nbgl_serializeIcon(const nbgl_icon_details_t *icon,
157 uint8_t *out,
158 size_t *w_cnt,
159 size_t max_len)
160{
161 int32_t size = 0;
162 if (icon == NULL) {
163 nbgl_appendU16(0, out, w_cnt, max_len);
164 nbgl_appendU16(0, out, w_cnt, max_len);
165 nbgl_appendU8(0, out, w_cnt, max_len);
166 nbgl_appendU8(0, out, w_cnt, max_len);
167 }
168 else {
169 nbgl_appendU16(icon->width, out, w_cnt, max_len);
170 nbgl_appendU16(icon->height, out, w_cnt, max_len);
171 nbgl_appendU8(icon->bpp, out, w_cnt, max_len);
172 nbgl_appendU8(icon->isFile, out, w_cnt, max_len);
173 if (!icon->isFile) {
174 size = nbgl_bpp_get_window_size(icon->width, icon->height, icon->bpp);
175 }
176 else {
177 size = GET_IMAGE_FILE_BUFFER_LEN(((const uint8_t *) PIC(icon->bitmap)))
179 }
180 }
181 nbgl_appendU32(size, out, w_cnt, max_len);
182#ifdef SERIALIZE_DATA
183 for (int32_t i = 0; i < size; i++) {
184 nbgl_appendU8(icon->bitmap[i], out, w_cnt, max_len);
185 }
186#endif // SERIALIZE_DATA
187}
188
189static void nbgl_serializeTextArea(nbgl_text_area_t *obj,
190 uint8_t *out,
191 size_t *w_cnt,
192 size_t max_len)
193{
194 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
195
196 nbgl_appendU8((uint8_t) obj->textColor, out, w_cnt, max_len);
197 nbgl_appendU8((uint8_t) obj->textAlignment, out, w_cnt, max_len);
198 nbgl_appendU8((uint8_t) obj->style, out, w_cnt, max_len);
199 nbgl_appendU8((uint8_t) obj->fontId, out, w_cnt, max_len);
200 nbgl_appendU8(0, out, w_cnt, max_len);
201 nbgl_appendU8((uint8_t) obj->autoHideLongLine, out, w_cnt, max_len);
202 nbgl_appendU16((uint16_t) obj->len, out, w_cnt, max_len);
203
204 nbgl_serializeText(PIC(obj->text), obj->len, out, w_cnt, max_len);
205}
206
207static void nbgl_serializeLine(nbgl_line_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
208{
209 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
210
211 nbgl_appendU8((uint8_t) obj->direction, out, w_cnt, max_len);
212 nbgl_appendU8((uint8_t) obj->lineColor, out, w_cnt, max_len);
213 nbgl_appendU8((uint8_t) obj->thickness, out, w_cnt, max_len);
214 nbgl_appendU8((uint8_t) obj->offset, out, w_cnt, max_len);
215}
216
217static void nbgl_serializeQrCode(nbgl_qrcode_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
218{
219 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
220
221 nbgl_appendU8((uint8_t) obj->foregroundColor, out, w_cnt, max_len);
222 nbgl_appendU8((uint8_t) obj->version, out, w_cnt, max_len);
223 nbgl_serializeText(PIC(obj->text), 0, out, w_cnt, max_len);
224}
225
226static void nbgl_serializeRadio(nbgl_radio_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
227{
228 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
229
230 nbgl_appendU8((uint8_t) obj->activeColor, out, w_cnt, max_len);
231 nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len);
232 nbgl_appendU8((uint8_t) obj->state, out, w_cnt, max_len);
233}
234
235static void nbgl_serializeSwitch(nbgl_switch_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
236{
237 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
238
239 nbgl_appendU8((uint8_t) obj->onColor, out, w_cnt, max_len);
240 nbgl_appendU8((uint8_t) obj->offColor, out, w_cnt, max_len);
241 nbgl_appendU8((uint8_t) obj->state, out, w_cnt, max_len);
242}
243
244static void nbgl_serializeProgressBar(nbgl_progress_bar_t *obj,
245 uint8_t *out,
246 size_t *w_cnt,
247 size_t max_len)
248{
249 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
250
251 nbgl_appendU8((uint8_t) obj->withBorder, out, w_cnt, max_len);
252 nbgl_appendU8((uint8_t) obj->state, out, w_cnt, max_len);
253}
254
255static void nbgl_serializePageIndicator(nbgl_page_indicator_t *obj,
256 uint8_t *out,
257 size_t *w_cnt,
258 size_t max_len)
259{
260 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
261
262 nbgl_appendU8((uint8_t) obj->activePage, out, w_cnt, max_len);
263 nbgl_appendU8((uint8_t) obj->nbPages, out, w_cnt, max_len);
264}
265
266static void nbgl_serializeButton(nbgl_button_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
267{
268 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
269
270 nbgl_appendU8((uint8_t) obj->innerColor, out, w_cnt, max_len);
271 nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len);
272 nbgl_appendU8((uint8_t) obj->foregroundColor, out, w_cnt, max_len);
273 nbgl_appendU8((uint8_t) obj->radius, out, w_cnt, max_len);
274 nbgl_appendU8((uint8_t) obj->fontId, out, w_cnt, max_len);
275 nbgl_appendU8(0, out, w_cnt, max_len);
276 nbgl_serializeText(PIC(obj->text), 0, out, w_cnt, max_len);
277 nbgl_serializeIcon(PIC(obj->icon), out, w_cnt, max_len);
278}
279
280static void nbgl_serializeImage(nbgl_image_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
281{
282 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
283 nbgl_serializeIcon(PIC(obj->buffer), out, w_cnt, max_len);
284 nbgl_appendU8((uint8_t) obj->foregroundColor, out, w_cnt, max_len);
285}
286
287static void nbgl_serializeSpinner(nbgl_spinner_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
288{
289 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
290 nbgl_appendU8(obj->position, out, w_cnt, max_len);
291}
292
293static void nbgl_serializeKeyboard(nbgl_keyboard_t *obj,
294 uint8_t *out,
295 size_t *w_cnt,
296 size_t max_len)
297{
298 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
299
300 nbgl_appendU8((uint8_t) obj->textColor, out, w_cnt, max_len);
301 nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len);
302 nbgl_appendU8((uint8_t) obj->lettersOnly, out, w_cnt, max_len);
303#ifdef HAVE_SE_TOUCH
304 nbgl_appendU8((uint8_t) obj->casing, out, w_cnt, max_len);
305#else // HAVE_SE_TOUCH
306 nbgl_appendU8((uint8_t) obj->selectedCharIndex, out, w_cnt, max_len);
307#endif // HAVE_SE_TOUCH
308 nbgl_appendU8((uint8_t) obj->mode, out, w_cnt, max_len);
309 nbgl_appendU32(obj->keyMask, out, w_cnt, max_len);
310}
311
312static void nbgl_serializeKeypad(nbgl_keypad_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
313{
314 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
315
316#ifdef HAVE_SE_TOUCH
317 nbgl_appendU8((uint8_t) obj->softValidation, out, w_cnt, max_len);
318 nbgl_appendU8((uint8_t) obj->borderColor, out, w_cnt, max_len);
319#endif // HAVE_SE_TOUCH
320 nbgl_appendU8((uint8_t) obj->enableBackspace, out, w_cnt, max_len);
321 nbgl_appendU8((uint8_t) obj->enableValidate, out, w_cnt, max_len);
322#ifdef HAVE_SE_TOUCH
323 nbgl_appendU8((uint8_t) obj->enableDigits, out, w_cnt, max_len);
324#endif // HAVE_SE_TOUCH
325 nbgl_appendU8((uint8_t) obj->shuffled, out, w_cnt, max_len);
326#ifdef HAVE_SE_TOUCH
327 nbgl_appendU8((uint8_t) obj->digitIndexes[0], out, w_cnt, max_len);
328 nbgl_appendU8((uint8_t) obj->digitIndexes[1], out, w_cnt, max_len);
329 nbgl_appendU8((uint8_t) obj->digitIndexes[2], out, w_cnt, max_len);
330 nbgl_appendU8((uint8_t) obj->digitIndexes[3], out, w_cnt, max_len);
331 nbgl_appendU8((uint8_t) obj->digitIndexes[4], out, w_cnt, max_len);
332#else // HAVE_SE_TOUCH
333 nbgl_appendU8((uint8_t) obj->selectedKey, out, w_cnt, max_len);
334#endif // HAVE_SE_TOUCH
335}
336
337static void nbgl_serializeImageFile(nbgl_image_file_t *obj,
338 uint8_t *out,
339 size_t *w_cnt,
340 size_t max_len)
341{
342 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
343 nbgl_appendPtr((const void *) obj->buffer, out, w_cnt, max_len);
344}
345
346static void nbgl_serializeContainer(nbgl_container_t *obj,
347 uint8_t *out,
348 size_t *w_cnt,
349 size_t max_len)
350{
351 nbgl_serializeObj((nbgl_obj_t *) &obj->obj, out, w_cnt, max_len);
352
353 nbgl_appendU8((uint8_t) obj->layout, out, w_cnt, max_len);
354 nbgl_appendU8((uint8_t) obj->nbChildren, out, w_cnt, max_len);
355 nbgl_appendU8((uint8_t) obj->forceClean, out, w_cnt, max_len);
356}
357
358static uint8_t nbgl_serializeObject(nbgl_obj_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
359{
360 switch (obj->type) {
361 case SCREEN:
362 nbgl_serializeObj((nbgl_obj_t *) obj, out, w_cnt, max_len);
363 break;
364 case CONTAINER:
365 nbgl_serializeContainer((nbgl_container_t *) obj, out, w_cnt, max_len);
366 break;
367 case IMAGE:
368 nbgl_serializeImage((nbgl_image_t *) obj, out, w_cnt, max_len);
369 break;
370 case LINE:
371 nbgl_serializeLine((nbgl_line_t *) obj, out, w_cnt, max_len);
372 break;
373 case TEXT_AREA:
374 nbgl_serializeTextArea((nbgl_text_area_t *) obj, out, w_cnt, max_len);
375 break;
376 case BUTTON:
377 nbgl_serializeButton((nbgl_button_t *) obj, out, w_cnt, max_len);
378 break;
379 case SWITCH:
380 nbgl_serializeSwitch((nbgl_switch_t *) obj, out, w_cnt, max_len);
381 break;
382 case PAGE_INDICATOR:
383 nbgl_serializePageIndicator((nbgl_page_indicator_t *) obj, out, w_cnt, max_len);
384 break;
385 case PROGRESS_BAR:
386 nbgl_serializeProgressBar((nbgl_progress_bar_t *) obj, out, w_cnt, max_len);
387 break;
388 case RADIO_BUTTON:
389 nbgl_serializeRadio((nbgl_radio_t *) obj, out, w_cnt, max_len);
390 break;
391 case QR_CODE:
392 nbgl_serializeQrCode((nbgl_qrcode_t *) obj, out, w_cnt, max_len);
393 break;
394 case KEYBOARD:
395 nbgl_serializeKeyboard((nbgl_keyboard_t *) obj, out, w_cnt, max_len);
396 break;
397 case KEYPAD:
398 nbgl_serializeKeypad((nbgl_keypad_t *) obj, out, w_cnt, max_len);
399 break;
400 case SPINNER:
401 nbgl_serializeSpinner((nbgl_spinner_t *) obj, out, w_cnt, max_len);
402 break;
403 case IMAGE_FILE:
404 nbgl_serializeImageFile((nbgl_image_file_t *) obj, out, w_cnt, max_len);
405 break;
406 default:
408 }
409 return NBGL_SERIALIZE_OK;
410}
411
412static uint8_t nbgl_serializeRefreshEvent(nbgl_area_t *obj,
413 uint8_t *out,
414 size_t *w_cnt,
415 size_t max_len)
416{
417 nbgl_serializeArea(obj, out, w_cnt, max_len);
418 return NBGL_SERIALIZE_OK;
419}
420
422 nbgl_obj_t *obj,
423 uint8_t *out,
424 size_t *w_cnt,
425 size_t max_len)
426{
427 // Write type
428 nbgl_appendU8((uint8_t) type, out, w_cnt, max_len);
429
430 // Write content
431 switch (type) {
432 case NBGL_DRAW_OBJ:
433 return nbgl_serializeObject(obj, out, w_cnt, max_len);
435 return nbgl_serializeRefreshEvent((nbgl_area_t *) obj, out, w_cnt, max_len);
436 default:
438 }
439
440 return NBGL_SERIALIZE_OK;
441}
Utilities for Ledger image files processing.
#define IMAGE_FILE_HEADER_SIZE
#define GET_IMAGE_FILE_BUFFER_LEN(image_file)
macro to get the buffer len of the image file
API to draw all basic graphic objects.
struct PACKED__ nbgl_line_s nbgl_line_t
struct to represent a vertical or horizontal line
struct PACKED__ nbgl_navigation_bar_s nbgl_page_indicator_t
struct to represent a navigation bar (PAGE_INDICATOR type) There can be up to 5 page indicators,...
struct PACKED__ nbgl_radio_s nbgl_radio_t
struct to represent a radio button (RADIO_BUTTON type)
struct PACKED__ nbgl_text_area_s nbgl_text_area_t
struct to represent a text area (TEXT_AREA type)
struct PACKED__ nbgl_progress_bar_s nbgl_progress_bar_t
struct to represent a progress bar (PROGRESS_BAR type)
struct PACKED__ nbgl_keypad_s nbgl_keypad_t
struct to represent a keypad (KEYPAD type)
struct PACKED__ nbgl_keyboard_s nbgl_keyboard_t
struct to represent a keyboard (KEYBOARD type)
struct PACKED__ nbgl_image_s nbgl_image_t
struct to represent an image (IMAGE type)
uint8_t nbgl_objPoolGetId(nbgl_obj_t *obj)
Gets a unique index for the given object, in the pool.
struct PACKED__ nbgl_button_s nbgl_button_t
struct to represent a button (BUTTON type) that can contain a text and/or an icon
struct PACKED__ nbgl_container_s nbgl_container_t
struct to represent a container (CONTAINER type)
struct PACKED__ nbgl_switch_s nbgl_switch_t
struct to represent a switch (size is fixed) (SWITCH type)
struct PACKED__ nbgl_obj_s nbgl_obj_t
Common structure for all graphical objects.
struct PACKED__ nbgl_spinner_s nbgl_spinner_t
struct to represent a "spinner", represented by the Ledger corners, in gray, with one of the corners ...
struct PACKED__ nbgl_image_file_s nbgl_image_file_t
struct to represent an image file object (IMAGE_FILE type) The source of the data is an image file wi...
struct PACKED__ nbgl_qrcode_s nbgl_qrcode_t
struct to represent a QR code (QR_CODE type), whose size is fixed
uint8_t nbgl_serializeNbglEvent(nbgl_serialized_event_type_e type, nbgl_obj_t *obj, uint8_t *out, size_t *w_cnt, size_t max_len)
nbgl_serialized_event_type_e
@ NBGL_DRAW_OBJ
@ NBGL_REFRESH_AREA
#define NBGL_SERIALIZE_OK
#define NBGL_SERIALIZE_ERROR
struct PACKED__ nbgl_icon_details_s nbgl_icon_details_t
Represents all information about an icon.
@ KEYPAD
Keypad.
Definition nbgl_types.h:147
@ IMAGE
Bitmap (y and height must be multiple of 4 on Stax)
Definition nbgl_types.h:137
@ IMAGE_FILE
Image file (with Ledger compression)
Definition nbgl_types.h:149
@ SWITCH
Switch to turn on/off something.
Definition nbgl_types.h:141
@ RADIO_BUTTON
Indicator to inform whether something is on or off.
Definition nbgl_types.h:144
@ SPINNER
Spinner.
Definition nbgl_types.h:148
@ BUTTON
Rounded rectangle button with icon and/or text.
Definition nbgl_types.h:140
@ PROGRESS_BAR
horizontal bar to indicate progression of something (between 0% and 100%)
Definition nbgl_types.h:143
@ QR_CODE
QR Code.
Definition nbgl_types.h:145
@ PAGE_INDICATOR
horizontal bar to indicate position within pages
Definition nbgl_types.h:142
@ LINE
Vertical or Horizontal line.
Definition nbgl_types.h:138
@ KEYBOARD
Keyboard.
Definition nbgl_types.h:146
@ CONTAINER
Empty container.
Definition nbgl_types.h:136
@ TEXT_AREA
Area to contain text line(s)
Definition nbgl_types.h:139
@ SCREEN
Main screen.
Definition nbgl_types.h:135
nbgl_bpp_t
Enum to represent the number of bits per pixel (BPP)
Definition nbgl_types.h:263
@ NB_NBGL_BPP
Number of NBGL_BPP enums.
Definition nbgl_types.h:267
@ NBGL_BPP_1
1 bit per pixel
Definition nbgl_types.h:264
@ NBGL_BPP_4
4 bits per pixel
Definition nbgl_types.h:266
@ NBGL_BPP_2
2 bits per pixel
Definition nbgl_types.h:265
struct PACKED__ nbgl_area_s nbgl_area_t
Represents a rectangle area of the screen.
unsigned short uint16_t
Definition usbd_conf.h:54
unsigned char uint8_t
Definition usbd_conf.h:53
signed char int8_t
Definition usbd_conf.h:49