Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
nbgl_layout_keypad.c
Go to the documentation of this file.
1
7#ifdef HAVE_SE_TOUCH
8#ifdef NBGL_KEYPAD
9/*********************
10 * INCLUDES
11 *********************/
12#include <string.h>
13#include <stdlib.h>
14#include "nbgl_debug.h"
15#include "nbgl_front.h"
17#include "nbgl_obj.h"
18#include "nbgl_draw.h"
19#include "nbgl_screen.h"
20#include "nbgl_touch.h"
21#include "glyphs.h"
22#include "os_pic.h"
23#include "os_helpers.h"
24
25/*********************
26 * DEFINES
27 *********************/
28
29enum {
34};
35
36#if defined(TARGET_STAX)
37#define ENTRY_DIGITS_HEIGHT 50
38#define ENTRY_DIGITS_CONTAINER_HEIGHT 44
39#define INTER_ENTRY_DIGITS 10
40#elif defined(TARGET_FLEX)
41#define ENTRY_DIGITS_HEIGHT 64
42#define ENTRY_DIGITS_CONTAINER_HEIGHT 64
43#define INTER_ENTRY_DIGITS 12
44#endif // TARGETS
45
46/**********************
47 * MACROS
48 **********************/
49
50/**********************
51 * TYPEDEFS
52 **********************/
53
54/**********************
55 * VARIABLES
56 **********************/
57
58/**********************
59 * STATIC PROTOTYPES
60 **********************/
61
62/**********************
63 * GLOBAL API FUNCTIONS
64 **********************/
65
76int nbgl_layoutAddKeypad(nbgl_layout_t *layout, keyboardCallback_t callback, bool shuffled)
77{
78 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
79 nbgl_keypad_t *keypad;
80
81 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddKeypad():\n");
82 if (layout == NULL) {
83 return -1;
84 }
85 // footer must be empty
86 if (layoutInt->footerContainer != NULL) {
87 return -1;
88 }
89
90 // create keypad
91 keypad = (nbgl_keypad_t *) nbgl_objPoolGet(KEYPAD, layoutInt->layer);
92 keypad->obj.alignmentMarginY = 0;
93 keypad->obj.alignment = BOTTOM_MIDDLE;
94 keypad->obj.alignTo = NULL;
95 keypad->obj.area.width = SCREEN_WIDTH;
96 keypad->obj.area.height = 4 * KEYPAD_KEY_HEIGHT;
97 keypad->borderColor = LIGHT_GRAY;
98 keypad->callback = PIC(callback);
99 keypad->enableDigits = true;
100 keypad->enableBackspace = false;
101 keypad->enableValidate = false;
102 keypad->shuffled = shuffled;
103
104 // the keypad occupies the footer
105 layoutInt->footerContainer = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
106 layoutInt->footerContainer->obj.area.width = SCREEN_WIDTH;
107 layoutInt->footerContainer->layout = VERTICAL;
108 layoutInt->footerContainer->children
109 = (nbgl_obj_t **) nbgl_containerPoolGet(1, layoutInt->layer);
110 layoutInt->footerContainer->obj.alignment = BOTTOM_MIDDLE;
111 layoutInt->footerContainer->obj.area.height = keypad->obj.area.height;
112 layoutInt->footerContainer->children[layoutInt->footerContainer->nbChildren]
113 = (nbgl_obj_t *) keypad;
114 layoutInt->footerContainer->nbChildren++;
115
116 // add to layout children
117 layoutInt->children[FOOTER_INDEX] = (nbgl_obj_t *) layoutInt->footerContainer;
118
119 // subtract footer height from main container height
120 layoutInt->container->obj.area.height -= layoutInt->footerContainer->obj.area.height;
121
122 layoutInt->footerType = KEYPAD_FOOTER_TYPE;
123
124 return layoutInt->footerContainer->obj.area.height;
125}
126
138 uint8_t index,
139 bool enableValidate,
140 bool enableBackspace,
141 bool enableDigits)
142{
143 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
144 nbgl_keypad_t *keypad;
145
147 "nbgl_layoutUpdateKeypad(): enableValidate = %d, enableBackspace = %d\n",
148 enableValidate,
149 enableBackspace);
150 if (layout == NULL) {
151 return -1;
152 }
153 UNUSED(index);
154
155 // get existing keypad (in the footer container)
156 keypad = (nbgl_keypad_t *) layoutInt->footerContainer->children[0];
157 if ((keypad == NULL) || (keypad->obj.type != KEYPAD)) {
158 return -1;
159 }
160 // partial redraw only if only validate and backspace have changed
161 keypad->partial = (keypad->enableDigits == enableDigits);
162 keypad->enableValidate = enableValidate;
163 keypad->enableBackspace = enableBackspace;
164 keypad->enableDigits = enableDigits;
165
166 nbgl_objDraw((nbgl_obj_t *) keypad);
167
168 return 0;
169}
170
179int nbgl_layoutUpdateKeypadValidation(nbgl_layout_t *layout, bool softValidation)
180{
181 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
182 nbgl_keypad_t *keypad;
183
184 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateKeypad(): softValidation = %d,\n", softValidation);
185 if (layout == NULL) {
186 return -1;
187 }
188 UNUSED(index);
189
190 // get existing keypad (in the footer container)
191 keypad = (nbgl_keypad_t *) layoutInt->footerContainer->children[0];
192 if ((keypad == NULL) || (keypad->obj.type != KEYPAD)) {
193 return -1;
194 }
195 keypad->softValidation = softValidation;
196
197 return 0;
198}
199
214{
215 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
216 nbgl_container_t *container;
217 uint8_t space;
218
219 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddHiddenDigits():\n");
220 if (layout == NULL) {
221 return -1;
222 }
223 if (nbDigits > KEYPAD_MAX_DIGITS) {
224 return -1;
225 }
226 if (nbDigits > 8) {
227 space = 4;
228 }
229 else {
230 space = 12;
231 }
232
233 // create a container, invisible or bordered
234 container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
235 container->nbChildren = nbDigits;
236#ifdef TARGET_STAX
237 container->nbChildren++; // +1 for the line
238#endif // TARGET_STAX
239 container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer);
240 // <space> pixels between each icon (knowing that the effective round are 18px large and the
241 // icon 24px)
242 container->obj.area.width = nbDigits * DIGIT_ICON.width + (nbDigits - 1) * space;
243 container->obj.area.height = ENTRY_DIGITS_HEIGHT;
244
245 // item N-2 is the title
246 container->obj.alignTo = layoutInt->container->children[layoutInt->container->nbChildren - 2];
247 container->obj.alignment = BOTTOM_MIDDLE;
248
249 // set this new container as child of the main container
250 layoutAddObject(layoutInt, (nbgl_obj_t *) container);
251
252 // create children of the container, as images (empty circles)
253 nbgl_objPoolGetArray(IMAGE, nbDigits, layoutInt->layer, (nbgl_obj_t **) container->children);
254 for (int i = 0; i < nbDigits; i++) {
255 nbgl_image_t *image = (nbgl_image_t *) container->children[i];
256 image->buffer = &DIGIT_ICON;
257 image->foregroundColor = WHITE;
258 if (i > 0) {
259 image->obj.alignment = MID_RIGHT;
260 image->obj.alignTo = (nbgl_obj_t *) container->children[i - 1];
261 image->obj.alignmentMarginX = space;
262 }
263 else {
264 image->obj.alignment = MID_LEFT;
265 }
266 }
267#ifdef TARGET_STAX
268 nbgl_line_t *line;
269 // create gray line
270 line = (nbgl_line_t *) nbgl_objPoolGet(LINE, layoutInt->layer);
271 line->lineColor = LIGHT_GRAY;
272 line->obj.alignmentMarginY = 0;
273 line->obj.alignTo = NULL;
274 line->obj.alignment = BOTTOM_MIDDLE;
275 line->obj.area.width = container->obj.area.width;
276 line->obj.area.height = 4;
277 line->direction = HORIZONTAL;
278 line->thickness = 2;
279 line->offset = 2;
280 container->children[nbDigits] = (nbgl_obj_t *) line;
281#endif // TARGET_STAX
282
283 // return index of keypad to be modified later on
284 return (layoutInt->container->nbChildren - 1);
285}
286
297{
298 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
299 nbgl_container_t *container;
300 nbgl_image_t *image;
301
302 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateHiddenDigits(): nbActive = %d\n", nbActive);
303 if (layout == NULL) {
304 return -1;
305 }
306
307 // get container
308 container = (nbgl_container_t *) layoutInt->container->children[index];
309 // sanity check
310 if ((container == NULL) || (container->obj.type != CONTAINER)) {
311 return -1;
312 }
313 if (nbActive > container->nbChildren) {
314 return -1;
315 }
316 if (nbActive == 0) {
317 // deactivate the first digit
318 image = (nbgl_image_t *) container->children[0];
319 if ((image == NULL) || (image->obj.type != IMAGE)) {
320 return -1;
321 }
322 image->foregroundColor = WHITE;
323 }
324 else {
325 image = (nbgl_image_t *) container->children[nbActive - 1];
326 if ((image == NULL) || (image->obj.type != IMAGE)) {
327 return -1;
328 }
329 // if the last "active" is already active, it means that we are decreasing the number of
330 // active otherwise we are increasing it
331 if (image->foregroundColor == BLACK) {
332 // all digits are already active
333 if (nbActive == container->nbChildren) {
334 return 0;
335 }
336 // deactivate the next digit
337 image = (nbgl_image_t *) container->children[nbActive];
338 image->foregroundColor = WHITE;
339 }
340 else {
341 image->buffer = &DIGIT_ICON;
342 image->foregroundColor = BLACK;
343 }
344 }
345
346 nbgl_objDraw((nbgl_obj_t *) image);
347
348 return 0;
349}
350
368 const char *title,
369 bool hidden,
370 uint8_t nbDigits,
371 const char *text)
372{
373 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
374 nbgl_container_t *container;
375 nbgl_text_area_t *textArea;
376
377 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutAddKeypadContent():\n");
378 if (layout == NULL) {
379 return -1;
380 }
381 // create a container, to store both title and "digits" (and line on Stax)
382 container = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
383 container->nbChildren = NB_CHILDREN;
384 container->children = nbgl_containerPoolGet(container->nbChildren, layoutInt->layer);
385 container->obj.area.width = AVAILABLE_WIDTH;
386 container->obj.alignment = TOP_MIDDLE;
387 container->obj.alignmentMarginY = 8;
388
389 // create text area for title
390 textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
391 textArea->textColor = BLACK;
392 textArea->text = title;
393 textArea->textAlignment = CENTER;
394 textArea->fontId = SMALL_REGULAR_FONT;
395 textArea->wrapping = true;
396 textArea->obj.alignment = TOP_MIDDLE;
397 textArea->obj.area.width = AVAILABLE_WIDTH;
398 textArea->obj.area.height = nbgl_getTextHeightInWidth(
399 textArea->fontId, textArea->text, textArea->obj.area.width, textArea->wrapping);
400 container->children[TITLE_INDEX] = (nbgl_obj_t *) textArea;
401 container->obj.area.height += textArea->obj.area.height;
402
403 if (hidden) {
404 nbgl_container_t *digitsContainer;
405 uint8_t space;
406
407 if (nbDigits > KEYPAD_MAX_DIGITS) {
408 return -1;
409 }
410 // space between "digits"
411 if (nbDigits > 8) {
412 space = 4;
413 }
414 else {
415 space = INTER_ENTRY_DIGITS;
416 }
417
418 // create digits container, to store "discs"
419 digitsContainer = (nbgl_container_t *) nbgl_objPoolGet(CONTAINER, layoutInt->layer);
420 digitsContainer->nbChildren = nbDigits;
421 digitsContainer->children
422 = nbgl_containerPoolGet(digitsContainer->nbChildren, layoutInt->layer);
423 // <space> pixels between each icon (knowing that the effective round are 18px large and the
424 // icon 24px)
425 digitsContainer->obj.area.width = nbDigits * DIGIT_ICON.width + (nbDigits - 1) * space;
426 digitsContainer->obj.area.height = ENTRY_DIGITS_CONTAINER_HEIGHT;
427 // align at the bottom of title
428 digitsContainer->obj.alignTo = container->children[0];
429 digitsContainer->obj.alignment = BOTTOM_MIDDLE;
430#ifdef TARGET_STAX
431 digitsContainer->obj.alignmentMarginY = 28;
432#endif // TARGET_STAX
433 container->children[INPUT_INDEX] = (nbgl_obj_t *) digitsContainer;
434 container->obj.area.height += digitsContainer->obj.area.height;
435
436 // create children of the container, as images (empty circles)
438 IMAGE, nbDigits, layoutInt->layer, (nbgl_obj_t **) digitsContainer->children);
439 for (int i = 0; i < nbDigits; i++) {
440 nbgl_image_t *image = (nbgl_image_t *) digitsContainer->children[i];
441 image->buffer = &DIGIT_ICON;
442 image->foregroundColor = WHITE;
443 if (i > 0) {
444 image->obj.alignment = MID_RIGHT;
445 image->obj.alignTo = (nbgl_obj_t *) digitsContainer->children[i - 1];
446 image->obj.alignmentMarginX = space;
447 }
448 else {
449 image->obj.alignment = MID_LEFT;
450 }
451 }
452 }
453 else {
454 // create text area
455 textArea = (nbgl_text_area_t *) nbgl_objPoolGet(TEXT_AREA, layoutInt->layer);
456 textArea->textColor = BLACK;
457 textArea->text = text;
458 textArea->textAlignment = MID_LEFT;
459 textArea->fontId = LARGE_MEDIUM_1BPP_FONT;
460 textArea->obj.area.width = container->obj.area.width;
461 textArea->obj.area.height = nbgl_getFontLineHeight(textArea->fontId);
462 textArea->autoHideLongLine = true;
463 // align at the bottom of title
464 textArea->obj.alignTo = container->children[TITLE_INDEX];
465 textArea->obj.alignment = BOTTOM_MIDDLE;
466#ifdef TARGET_STAX
467 textArea->obj.alignmentMarginY = 24;
468#endif // TARGET_STAX
469 container->children[INPUT_INDEX] = (nbgl_obj_t *) textArea;
470 container->obj.area.height += textArea->obj.area.height;
471 }
472
473 // set this new container as child of the main container
474 layoutAddObject(layoutInt, (nbgl_obj_t *) container);
475#ifdef TARGET_STAX
476 nbgl_line_t *line;
477 // create gray line
478 line = (nbgl_line_t *) nbgl_objPoolGet(LINE, layoutInt->layer);
479 line->lineColor = LIGHT_GRAY;
480 line->obj.alignTo = container->children[INPUT_INDEX];
481 line->obj.alignment = BOTTOM_MIDDLE;
482 line->obj.area.width = 288;
483 line->obj.area.height = 4;
484 line->direction = HORIZONTAL;
485 line->thickness = 2;
486 line->offset = 2;
487 container->children[LINE_INDEX] = (nbgl_obj_t *) line;
488#endif // TARGET_STAX
489
490 // return height of the area
491 return container->obj.area.height;
492}
493
507 bool hidden,
508 uint8_t nbActiveDigits,
509 const char *text)
510{
511 nbgl_layoutInternal_t *layoutInt = (nbgl_layoutInternal_t *) layout;
512 nbgl_container_t *container;
513 nbgl_image_t *image;
514
515 LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutUpdateHiddenDigits(): nbActive = %d\n", nbActiveDigits);
516 if (layout == NULL) {
517 return -1;
518 }
519
520 UNUSED(index);
521
522 if (hidden) {
523 // get digits container (second child of the main container)
524 container = (nbgl_container_t *) ((nbgl_container_t *) layoutInt->container->children[0])
525 ->children[1];
526 // sanity check
527 if ((container == NULL) || (container->obj.type != CONTAINER)) {
528 return -1;
529 }
530 if (nbActiveDigits > container->nbChildren) {
531 return -1;
532 }
533 if (nbActiveDigits == 0) {
534 // deactivate the first digit
535 image = (nbgl_image_t *) container->children[0];
536 if ((image == NULL) || (image->obj.type != IMAGE)) {
537 return -1;
538 }
539 image->foregroundColor = WHITE;
540 }
541 else {
542 image = (nbgl_image_t *) container->children[nbActiveDigits - 1];
543 if ((image == NULL) || (image->obj.type != IMAGE)) {
544 return -1;
545 }
546 // if the last "active" is already active, it means that we are decreasing the number of
547 // active otherwise we are increasing it
548 if (image->foregroundColor == BLACK) {
549 // all digits are already active
550 if (nbActiveDigits == container->nbChildren) {
551 return 0;
552 }
553 // deactivate the next digit by turning it to white
554 image = (nbgl_image_t *) container->children[nbActiveDigits];
555 image->foregroundColor = WHITE;
556 }
557 else {
558 // activate it the last digit by turning it to black
559 image->foregroundColor = BLACK;
560 }
561 }
562
563 nbgl_objDraw((nbgl_obj_t *) image);
564 }
565 else {
566 // update main text area (second child of the main container)
567 nbgl_text_area_t *textArea
568 = (nbgl_text_area_t *) ((nbgl_container_t *) layoutInt->container->children[0])
569 ->children[1];
570 if ((textArea == NULL) || (textArea->obj.type != TEXT_AREA)) {
571 return -1;
572 }
573 textArea->text = text;
574 textArea->textColor = BLACK;
575 textArea->textAlignment = MID_LEFT;
576 nbgl_objDraw((nbgl_obj_t *) textArea);
577
578 // if the text doesn't fit, indicate it by returning 1 instead of 0, for different refresh
579 if (nbgl_getSingleLineTextWidth(textArea->fontId, text) > textArea->obj.area.width) {
580 return 1;
581 }
582 }
583
584 return 0;
585}
586#endif // NBGL_KEYPAD
587#endif // HAVE_SE_TOUCH
debug traces management
#define LOG_DEBUG(__logger,...)
Definition nbgl_debug.h:86
@ LAYOUT_LOGGER
Definition nbgl_debug.h:33
Middle Level API of the new BOLOS Graphical Library.
uint16_t nbgl_getSingleLineTextWidth(nbgl_font_id_e fontId, const char *text)
return the max width in pixels of the given text until the first or \0 is encountered
Definition nbgl_fonts.c:324
uint16_t nbgl_getTextHeightInWidth(nbgl_font_id_e fontId, const char *text, uint16_t maxWidth, bool wrapping)
return the height of the given multiline text, with the given font.
uint8_t nbgl_getFontLineHeight(nbgl_font_id_e fontId)
return the height in pixels of the line of font with the given font ID
Definition nbgl_fonts.c:400
Font screen low-Level driver API, to draw elementary forms.
void layoutAddObject(nbgl_layoutInternal_t *layout, nbgl_obj_t *obj)
adds the given obj to the main container
#define AVAILABLE_WIDTH
Definition nbgl_layout.h:84
void * nbgl_layout_t
type shared externally
Internal functions/constants of NBGL layout layer.
@ FOOTER_INDEX
#define KEYPAD_FOOTER_TYPE
int nbgl_layoutAddHiddenDigits(nbgl_layout_t *layout, uint8_t nbDigits)
Adds a placeholder for hidden digits on top of a keypad, to represent the entered digits,...
int nbgl_layoutUpdateHiddenDigits(nbgl_layout_t *layout, uint8_t index, uint8_t nbActive)
Updates an existing set of hidden digits, with the given configuration.
int nbgl_layoutUpdateKeypad(nbgl_layout_t *layout, uint8_t index, bool enableValidate, bool enableBackspace, bool enableDigits)
Updates an existing keypad on bottom of the screen, with the given configuration.
int nbgl_layoutUpdateKeypadValidation(nbgl_layout_t *layout, bool softValidation)
Updates an existing keypad on bottom of the screen, with the given configuration, without redraw.
int nbgl_layoutAddKeypadContent(nbgl_layout_t *layout, const char *title, bool hidden, uint8_t nbDigits, const char *text)
Adds an area with a title and a placeholder for hidden digits on top of a keypad, to represent the en...
int nbgl_layoutUpdateKeypadContent(nbgl_layout_t *layout, bool hidden, uint8_t nbActiveDigits, const char *text)
Updates an existing set of hidden digits, with the given configuration.
int nbgl_layoutAddKeypad(nbgl_layout_t *layout, keyboardCallback_t callback, bool shuffled)
Adds a keypad on bottom of the screen, with the associated callback.
@ LINE_INDEX
@ INPUT_INDEX
@ NB_CHILDREN
@ TITLE_INDEX
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_text_area_s nbgl_text_area_t
struct to represent a text area (TEXT_AREA type)
void nbgl_objDraw(nbgl_obj_t *obj)
This function draws or redraws the given object and its children (recursive version)
Definition nbgl_obj.c:1520
nbgl_obj_t ** nbgl_containerPoolGet(uint8_t nbObjs, uint8_t layer)
Gets a new container from the pool, with the given number of obj pointers.
struct PACKED__ nbgl_keypad_s nbgl_keypad_t
struct to represent a keypad (KEYPAD type)
nbgl_obj_t * nbgl_objPoolGet(nbgl_obj_type_t type, uint8_t layer)
Gets a new graphic object from the pool, with the given type. The type field of the object is set.
#define KEYPAD_MAX_DIGITS
Definition nbgl_obj.h:63
struct PACKED__ nbgl_image_s nbgl_image_t
struct to represent an image (IMAGE type)
int nbgl_objPoolGetArray(nbgl_obj_type_t type, uint8_t nbObjs, uint8_t layer, nbgl_obj_t **objArray)
Gets nbObjects new graphic object from the pool, with the given type, for the given layer (screen)....
void(* keyboardCallback_t)(char touchedKey)
prototype of function to be called when a valid key is pressed on keyboard Backspace is equal to 0x8 ...
Definition nbgl_obj.h:487
struct PACKED__ nbgl_container_s nbgl_container_t
struct to represent a container (CONTAINER type)
struct PACKED__ nbgl_obj_s nbgl_obj_t
Common structure for all graphical objects.
API to manage screens.
@ WHITE
Definition nbgl_types.h:124
@ LIGHT_GRAY
Definition nbgl_types.h:123
@ BLACK
Definition nbgl_types.h:121
@ VERTICAL
from top to bottom
Definition nbgl_types.h:189
@ HORIZONTAL
from left to right
Definition nbgl_types.h:190
@ TOP_MIDDLE
Definition nbgl_types.h:162
@ CENTER
Definition nbgl_types.h:165
@ MID_RIGHT
Definition nbgl_types.h:166
@ MID_LEFT
Definition nbgl_types.h:164
@ BOTTOM_MIDDLE
Definition nbgl_types.h:168
@ KEYPAD
Keypad.
Definition nbgl_types.h:147
@ IMAGE
Bitmap (y and height must be multiple of 4 on Stax)
Definition nbgl_types.h:137
@ LINE
Vertical or Horizontal line.
Definition nbgl_types.h:138
@ CONTAINER
Empty container.
Definition nbgl_types.h:136
@ TEXT_AREA
Area to contain text line(s)
Definition nbgl_types.h:139
Structure containing all information about the current layout.
nbgl_container_t * footerContainer
container used to store footer (buttons, nav....)
nbgl_container_t * container
nbgl_layoutFooterType_t footerType
type of footer
nbgl_obj_t ** children
children for main screen
unsigned char uint8_t
Definition usbd_conf.h:53