17#include "os_helpers.h"
23#define WITH_HORIZONTAL_CHOICES_LIST
24#define WITH_HORIZONTAL_BARS_LIST
30typedef struct ReviewContext_s {
34 const char *reviewTitle;
35 const char *reviewSubTitle;
42typedef struct ChoiceContext_s {
45 const char *subMessage;
46 const char *confirmText;
47 const char *cancelText;
51typedef struct ConfirmContext_s {
53 const char *subMessage;
54 const char *confirmText;
55 const char *cancelText;
60typedef struct ContentContext_s {
63 const char *rejectText;
68typedef struct HomeContext_s {
79typedef struct KeypadContext_s {
96 GENERIC_REVIEW_USE_CASE,
97 REVIEW_BLIND_SIGN_USE_CASE,
98 ADDRESS_REVIEW_USE_CASE,
99 STREAMING_BLIND_SIGN_START_REVIEW_USE_CASE,
100 STREAMING_START_REVIEW_USE_CASE,
101 STREAMING_CONTINUE_REVIEW_USE_CASE,
102 STREAMING_FINISH_REVIEW_USE_CASE,
114typedef struct UseCaseContext_s {
121 ReviewContext_t review;
122 ChoiceContext_t choice;
123 ConfirmContext_t confirm;
125 ContentContext_t content;
127 KeypadContext_t keypad;
135static UseCaseContext_t context;
148static void displaySpinner(
const char *text);
150static void startUseCaseHome(
void);
151static void startUseCaseInfo(
void);
152static void startUseCaseSettings(
void);
153static void startUseCaseSettingsAtPage(
uint8_t initSettingPage);
154static void startUseCaseContent(
void);
156static void statusTickerCallback(
void);
161 switch (content->
type) {
187 if (contentIdx < 0 || contentIdx >= genericContents->
nbContents) {
193 if (content == NULL) {
219 switch (context.type) {
220 case SETTINGS_USE_CASE:
222 case GENERIC_SETTINGS:
223 genericContents = context.home.settingContents;
225 case CONTENT_USE_CASE:
226 case GENERIC_REVIEW_USE_CASE:
227 genericContents = &context.content.genericContents;
232 for (
int i = 0; i < genericContents->
nbContents; i++) {
233 p_content = getContentAtIdx(genericContents, i, content);
234 elemNbPages = getContentNbElement(p_content);
235 if (nbPages + elemNbPages > elemIdx) {
236 *elemContentIdx = context.currentPage - nbPages;
239 nbPages += elemNbPages;
245static const char *getChoiceName(
uint8_t choiceIndex)
255 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
256 if (p_content == NULL) {
259 switch (p_content->
type) {
262 names = (
char **) PIC(contentChoices->
names);
267 names = (
char **) PIC(contentBars->
barTexts);
268 nbValues = contentBars->
nbBars;
274 if (choiceIndex >= nbValues) {
278 return (
const char *) PIC(names[choiceIndex]);
281static void onChoiceSelected(
uint8_t choiceIndex)
290 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
291 if (p_content == NULL) {
294 switch (p_content->
type) {
297 if (choiceIndex < contentChoices->nbChoices) {
298 token = contentChoices->
token;
303 if (choiceIndex < contentBars->nbBars) {
304 token = contentBars->
tokens[choiceIndex];
311 if ((token != 255) && (context.content.controlsCallback != NULL)) {
312 context.content.controlsCallback(token, 0);
314 else if (context.content.quitCallback != NULL) {
315 context.content.quitCallback();
326 if (tagValueList->
pairs != NULL) {
327 pair = PIC(&tagValueList->
pairs[index]);
330 pair = PIC(tagValueList->
callback(index));
333 *value = pair->
value;
336static void onReviewAccept(
void)
338 if (context.review.onChoice) {
339 context.review.onChoice(
true);
343static void onReviewReject(
void)
345 if (context.review.onChoice) {
346 context.review.onChoice(
false);
350static void onChoiceAccept(
void)
352 if (context.choice.onChoice) {
353 context.choice.onChoice(
true);
357static void onChoiceReject(
void)
359 if (context.choice.onChoice) {
360 context.choice.onChoice(
false);
364static void onConfirmAccept(
void)
366 if (context.confirm.currentStep) {
369 if (context.confirm.onConfirm) {
370 context.confirm.onConfirm();
374static void onConfirmReject(
void)
376 if (context.confirm.currentStep) {
383static void onSwitchAction(
void)
390 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
396 switch (context.type) {
397 case SETTINGS_USE_CASE:
399 case GENERIC_SETTINGS:
402 case CONTENT_USE_CASE:
403 case GENERIC_REVIEW_USE_CASE:
411 actionCallback(contentSwitch->
token, 0, context.currentPage);
413 else if (context.content.controlsCallback != NULL) {
414 context.content.controlsCallback(contentSwitch->
token, 0);
434 .tickerCallback = PIC(statusTickerCallback),
435 .tickerIntervale = 0,
441 if ((context.type == STATUS_USE_CASE) || (context.type == SPINNER_USE_CASE)) {
444 if ((context.type == CONFIRM_USE_CASE) && (context.confirm.currentStep != NULL)) {
449 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
451 switch (p_content->
type) {
473 else if (icon == NULL) {
475 pos, onActionCallback, p_ticker, txt, subTxt, BOLD_TEXT1_INFO, modal);
483 info.
style = BOLD_TEXT1_INFO;
486 if (context.type == CONFIRM_USE_CASE) {
487 context.confirm.currentStep = newStep;
500 if (context.currentPage > 0) {
501 context.currentPage--;
510 if (context.currentPage < (
int) (context.nbPages - 1)) {
511 context.currentPage++;
521 if (context.stepCallback != NULL) {
522 context.stepCallback();
524 else if ((context.type == CONTENT_USE_CASE)
525 || (context.type == GENERIC_REVIEW_USE_CASE)) {
526 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
527 if (p_content != NULL) {
528 switch (p_content->
type) {
543 index = context.currentPage;
552 else if (context.content.controlsCallback != NULL) {
553 context.content.controlsCallback(token, index);
568 if (!buttonGenericCallback(event, &pos)) {
572 displayReviewPage(pos);
582 if ((context.review.dataDirection ==
BACKWARD_DIRECTION) && (context.currentPage > 0)) {
583 context.currentPage--;
589 && (context.currentPage < (
int) (context.nbPages - 1))) {
590 context.currentPage++;
595 context.review.skipCallback();
601 displayStreamingReviewPage(pos);
610 if ((context.review.skipCallback != NULL) && (context.review.dataDisplay ==
true)) {
621 context.review.dataDisplay =
false;
625 "Press right to continue message.\nDouble-press to skip",
632 if (!buttonGenericCallback(event, &pos)) {
636 displayStreamingReviewPage(pos);
644 if (!buttonGenericCallback(event, &pos)) {
648 displaySettingsPage(pos,
false);
656 if (!buttonGenericCallback(event, &pos)) {
660 displayInfoPage(pos);
668 if (!buttonGenericCallback(event, &pos)) {
672 displayHomePage(pos);
680 if (!buttonGenericCallback(event, &pos)) {
684 displayChoicePage(pos);
692 if (!buttonGenericCallback(event, &pos)) {
703 if (context.stepCallback != NULL) {
704 context.stepCallback();
714 if (!buttonGenericCallback(event, &pos)) {
718 displayContent(pos,
false);
722static void statusTickerCallback(
void)
724 if (context.stepCallback != NULL) {
725 context.stepCallback();
735 const char *text = NULL;
736 const char *subText = NULL;
745 context.stepCallback = NULL;
748 if (context.type == REVIEW_BLIND_SIGN_USE_CASE) {
750 warnIndex = currentIndex++;
754 titleIndex = currentIndex++;
756 if (context.review.reviewSubTitle) {
758 subIndex = currentIndex++;
761 approveIndex = context.nbPages - 2;
762 rejectIndex = context.nbPages - 1;
763 finalPages = approveIndex;
766 if (context.currentPage >= finalPages) {
767 if (context.currentPage == approveIndex) {
769 icon = &C_icon_validate_14;
771 context.stepCallback = onReviewAccept;
773 else if (context.currentPage == rejectIndex) {
775 icon = &C_icon_crossmark;
777 context.stepCallback = onReviewReject;
780 else if (context.currentPage < reviewPages) {
781 if (context.currentPage == warnIndex) {
783 icon = &C_icon_warning;
784 text =
"Blind\nsigning";
786 else if (context.currentPage == titleIndex) {
788 icon = context.review.icon;
789 text = context.review.reviewTitle;
791 else if (context.currentPage == subIndex) {
793 text = context.review.reviewSubTitle;
796 else if ((context.review.address != NULL) && (context.currentPage == reviewPages)) {
799 subText = context.review.address;
802 pairIndex = context.currentPage - reviewPages;
803 if (context.review.address != NULL) {
806 getPairData(context.review.tagValueList, pairIndex, &text, &subText);
809 drawStep(pos, icon, text, subText, reviewCallback,
false);
816 const char *text = NULL;
817 const char *subText = NULL;
824 context.stepCallback = NULL;
825 context.review.dataDisplay =
false;
826 switch (context.type) {
827 case STREAMING_START_REVIEW_USE_CASE:
828 case STREAMING_BLIND_SIGN_START_REVIEW_USE_CASE:
829 if (context.type == STREAMING_START_REVIEW_USE_CASE) {
831 titleIndex = reviewPages++;
832 if (context.review.reviewSubTitle) {
834 subIndex = reviewPages++;
839 warnIndex = reviewPages++;
841 titleIndex = reviewPages++;
842 if (context.review.reviewSubTitle) {
844 subIndex = reviewPages++;
848 if (context.currentPage >= reviewPages) {
849 displaySpinner(
"Processing");
854 if (context.currentPage == warnIndex) {
856 icon = &C_icon_warning;
857 text =
"Blind\nsigning";
859 else if (context.currentPage == titleIndex) {
861 icon = context.review.icon;
862 text = context.review.reviewTitle;
864 else if (context.currentPage == subIndex) {
866 text = context.review.reviewSubTitle;
870 case STREAMING_CONTINUE_REVIEW_USE_CASE:
871 if (context.currentPage >= context.review.tagValueList->nbPairs) {
872 displaySpinner(
"Processing");
876 context.review.dataDisplay =
true;
877 getPairData(context.review.tagValueList, context.currentPage, &text, &subText);
880 case STREAMING_FINISH_REVIEW_USE_CASE:
882 if (context.currentPage == 0) {
884 icon = &C_icon_validate_14;
886 context.stepCallback = onReviewAccept;
890 icon = &C_icon_crossmark;
892 context.stepCallback = onReviewReject;
897 drawStep(pos, icon, text, subText, streamingReviewCallback,
false);
904 const char *text = NULL;
905 const char *subText = NULL;
908 context.stepCallback = NULL;
910 if (context.currentPage < (context.nbPages - 1)) {
912 ((
const char *
const *) PIC(context.home.infosList->infoTypes))[context.currentPage]);
914 ((
const char *
const *) PIC(context.home.infosList->infoContents))[context.currentPage]);
917 icon = &C_icon_back_x;
919 context.stepCallback = startUseCaseHome;
922 drawStep(pos, icon, text, subText, infoCallback,
false);
927static void getContentPage(
bool toogle_state,
929 const char **subText,
932 static char fullText[75];
938#ifdef WITH_HORIZONTAL_CHOICES_LIST
943 p_content = getContentElemAtIdx(context.currentPage, &elemIdx, &content);
944 if (p_content == NULL) {
947 switch (p_content->
type) {
963 *text = contentSwitch->
text;
969 snprintf(fullText,
sizeof(fullText),
"%s\nEnabled", contentSwitch->
subText);
972 snprintf(fullText,
sizeof(fullText),
"%s\nDisabled", contentSwitch->
subText);
974 context.stepCallback = onSwitchAction;
983#ifdef WITH_HORIZONTAL_CHOICES_LIST
984 if ((context.type == CONTENT_USE_CASE) && (context.content.title != NULL)) {
985 *text = PIC(context.content.title);
990 names = (
char **) PIC(contentChoices->
names);
991 *text = (
const char *) PIC(names[elemIdx]);
996#ifdef WITH_HORIZONTAL_BARS_LIST
997 if ((context.type == CONTENT_USE_CASE) && (context.content.title != NULL)) {
998 *text = PIC(context.content.title);
1014 const char *text = NULL;
1015 const char *subText = NULL;
1018 context.stepCallback = NULL;
1020 if (context.currentPage < (context.nbPages - 1)) {
1021 getContentPage(toogle_state, &text, &subText, &icon);
1024 icon = &C_icon_back_x;
1026 if (context.type == GENERIC_SETTINGS) {
1027 context.stepCallback = context.home.quitCallback;
1030 context.stepCallback = startUseCaseHome;
1034 drawStep(pos, icon, text, subText, settingsCallback,
false);
1038static void startUseCaseHome(
void)
1041 if (context.home.homeAction) {
1045 switch (context.type) {
1046 case SETTINGS_USE_CASE:
1048 context.currentPage = 1 + addPages;
1052 context.currentPage = 2 + addPages;
1056 context.currentPage = 0;
1060 context.type = HOME_USE_CASE;
1061 context.nbPages = 2;
1062 if (context.home.settingContents) {
1065 if (context.home.infosList) {
1068 if (context.home.homeAction) {
1069 context.nbPages += addPages;
1074static void startUseCaseInfo(
void)
1076 context.type = INFO_USE_CASE;
1077 context.nbPages = context.home.infosList->nbInfos + 1;
1078 context.currentPage = 0;
1083static void startUseCaseSettingsAtPage(
uint8_t initSettingPage)
1088 if (context.type == 0) {
1090 context.
type = SETTINGS_USE_CASE;
1092 context.nbPages = 1;
1093 for (
int i = 0; i < context.home.settingContents->nbContents; i++) {
1094 p_content = getContentAtIdx(context.home.settingContents, i, &content);
1095 context.nbPages += getContentNbElement(p_content);
1097 context.currentPage = initSettingPage;
1102static void startUseCaseSettings(
void)
1104 startUseCaseSettingsAtPage(0);
1107static void startUseCaseContent(
void)
1113 context.nbPages = 1;
1115 for (contentIdx = 0; contentIdx < context.content.genericContents.nbContents; contentIdx++) {
1116 p_content = getContentAtIdx(&context.content.genericContents, contentIdx, &content);
1117 context.nbPages += getContentNbElement(p_content);
1126 const char *text = NULL;
1127 const char *subText = NULL;
1135 context.stepCallback = NULL;
1138 homeIndex = currentIndex++;
1139 if (context.home.homeAction) {
1140 actionIndex = currentIndex++;
1142 if (context.home.settingContents) {
1143 settingsIndex = currentIndex++;
1145 if (context.home.infosList) {
1146 infoIndex = currentIndex++;
1149 if (context.currentPage == homeIndex) {
1151 icon = context.home.appIcon;
1152 if (context.home.tagline != NULL) {
1153 text = context.home.tagline;
1156 text = context.home.appName;
1157 subText =
"is ready";
1160 else if (context.currentPage == actionIndex) {
1162 icon = context.home.homeAction->icon;
1163 text = PIC(context.home.homeAction->text);
1164 context.stepCallback = context.home.homeAction->callback;
1166 else if (context.currentPage == settingsIndex) {
1168 icon = &C_icon_coggle;
1170 context.stepCallback = startUseCaseSettings;
1172 else if (context.currentPage == infoIndex) {
1174 icon = &C_icon_certificate;
1176 context.stepCallback = startUseCaseInfo;
1179 icon = &C_icon_dashboard_x;
1181 context.stepCallback = context.home.quitCallback;
1184 drawStep(pos, icon, text, subText, homeCallback,
false);
1191 const char *text = NULL;
1192 const char *subText = NULL;
1195 context.stepCallback = NULL;
1198 if (context.currentPage == 1
1199 && (context.choice.icon == NULL || context.choice.subMessage == NULL)) {
1201 context.currentPage -= 1;
1204 context.currentPage += 1;
1208 if (context.currentPage == 0) {
1209 text = context.choice.message;
1210 if (context.choice.icon != NULL) {
1211 icon = context.choice.icon;
1214 subText = context.choice.subMessage;
1217 else if (context.currentPage == 1) {
1219 text = context.choice.message;
1220 subText = context.choice.subMessage;
1222 else if (context.currentPage == 2) {
1223 icon = &C_icon_validate_14;
1224 text = context.choice.confirmText;
1225 context.stepCallback = onChoiceAccept;
1228 icon = &C_icon_crossmark;
1229 text = context.choice.cancelText;
1230 context.stepCallback = onChoiceReject;
1233 drawStep(pos, icon, text, subText, genericChoiceCallback,
false);
1240 const char *text = NULL;
1241 const char *subText = NULL;
1244 context.stepCallback = NULL;
1245 switch (context.currentPage) {
1248 text = context.confirm.message;
1249 subText = context.confirm.subMessage;
1253 icon = &C_icon_validate_14;
1254 text = context.confirm.confirmText;
1255 context.stepCallback = onConfirmAccept;
1259 icon = &C_icon_crossmark;
1260 text = context.confirm.cancelText;
1261 context.stepCallback = onConfirmReject;
1265 drawStep(pos, icon, text, subText, genericConfirmCallback,
true);
1272 const char *text = NULL;
1273 const char *subText = NULL;
1276 context.stepCallback = NULL;
1278 if (context.currentPage < (context.nbPages - 1)) {
1279 getContentPage(toogle_state, &text, &subText, &icon);
1282 if (context.content.rejectText) {
1283 text = context.content.rejectText;
1288 if (context.type == GENERIC_REVIEW_USE_CASE) {
1289 icon = &C_icon_crossmark;
1292 icon = &C_icon_back_x;
1294 context.stepCallback = context.content.quitCallback;
1297 drawStep(pos, icon, text, subText, contentCallback,
false);
1301static void displaySpinner(
const char *text)
1303 drawStep(
SINGLE_STEP, &C_icon_processing, text, NULL, NULL,
false);
1308static void useCaseReview(ContextType_t type,
1311 const char *reviewTitle,
1312 const char *reviewSubTitle,
1313 const char *finishTitle,
1316 UNUSED(finishTitle);
1318 memset(&context, 0,
sizeof(UseCaseContext_t));
1319 context.type = type;
1320 context.review.tagValueList = tagValueList;
1321 context.review.reviewTitle = reviewTitle;
1322 context.review.reviewSubTitle = reviewSubTitle;
1323 context.review.icon = icon;
1324 context.review.onChoice = choiceCallback;
1325 context.currentPage = 0;
1327 context.nbPages = tagValueList->
nbPairs + 3;
1328 if (type == REVIEW_BLIND_SIGN_USE_CASE) {
1331 if (reviewSubTitle) {
1339static void setPinCodeText(
void)
1341 bool enableValidate =
false;
1342 bool enableBackspace =
true;
1345 enableValidate = (context.keypad.pinLen >= context.keypad.pinMinDigits);
1347 enableBackspace = (context.keypad.pinLen > 0) || (context.keypad.backCallback != NULL);
1349 context.keypad.hidden,
1350 context.keypad.pinLen,
1351 (
const char *) context.keypad.pinEntry);
1353 context.keypad.layoutCtx, context.keypad.keypadIndex, enableValidate, enableBackspace);
1359static void keypadCallback(
char touchedKey)
1361 switch (touchedKey) {
1363 if (context.keypad.pinLen > 0) {
1364 context.keypad.pinLen--;
1365 context.keypad.pinEntry[context.keypad.pinLen] = 0;
1367 else if (context.keypad.backCallback != NULL) {
1368 context.keypad.backCallback();
1375 context.keypad.validatePin(context.keypad.pinEntry, context.keypad.pinLen);
1379 if ((touchedKey >= 0x30) && (touchedKey < 0x40)) {
1380 if (context.keypad.pinLen < context.keypad.pinMaxDigits) {
1381 context.keypad.pinEntry[context.keypad.pinLen] = touchedKey;
1382 context.keypad.pinLen++;
1391static void keypadGenericUseCase(
const char *title,
1403 memset(&context, 0,
sizeof(KeypadContext_t));
1404 context.type = KEYPAD_USE_CASE;
1405 context.currentPage = 0;
1406 context.nbPages = 1;
1407 context.keypad.validatePin = validatePinCallback;
1408 context.keypad.backCallback = backCallback;
1409 context.keypad.pinMinDigits = minDigits;
1410 context.keypad.pinMaxDigits = maxDigits;
1411 context.keypad.hidden = hidden;
1419 context.keypad.keypadIndex = status;
1427 if (context.keypad.backCallback != NULL) {
1453 bool *requireSpecificDisplay)
1456 UNUSED(tagValueList);
1458 *requireSpecificDisplay =
true;
1478 bool *requireSpecificDisplay)
1481 UNUSED(tagValueList);
1483 UNUSED(isSkippable);
1484 *requireSpecificDisplay =
true;
1522 UNUSED(switchesList);
1562 UNUSED(choicesList);
1582 while (i < tagValueList->nbPairs) {
1586 nbPairs -= nbPairsInPage;
1615 if (initPage >= nbPages) {
1619 if (navCallback(initPage, &pageContent) ==
false) {
1622 memset(&context, 0,
sizeof(UseCaseContext_t));
1623 context.type = CONTENT_USE_CASE;
1624 context.content.quitCallback = quitCallback;
1625 context.content.controlsCallback = controlsCallback;
1626 context.content.genericContents.callbackCallNeeded =
false;
1627 context.content.genericContents.nbContents = nbPages;
1629 contentsList.
type = pageContent.
type;
1630 switch (pageContent.
type) {
1648 context.content.title = title;
1653 context.content.title = title;
1658 context.content.genericContents.contentsList = (
const nbgl_content_t *) &contentsList;
1660 startUseCaseContent();
1679 const char *tagline,
1680 const uint8_t initSettingPage,
1686 memset(&context, 0,
sizeof(UseCaseContext_t));
1687 context.home.appName = appName;
1688 context.home.appIcon = appIcon;
1689 context.home.tagline = tagline;
1690 context.home.settingContents = PIC(settingContents);
1691 context.home.infosList = PIC(infosList);
1692 context.home.homeAction = action;
1693 context.home.quitCallback = quitCallback;
1696 startUseCaseSettingsAtPage(initSettingPage);
1721 memset(&context, 0,
sizeof(UseCaseContext_t));
1722 context.type = GENERIC_SETTINGS;
1723 context.home.appName = appName;
1724 context.home.settingContents = PIC(settingContents);
1725 context.home.infosList = PIC(infosList);
1726 context.home.quitCallback = quitCallback;
1728 startUseCaseSettingsAtPage(initPage);
1767 const char *reviewTitle,
1768 const char *reviewSubTitle,
1769 const char *finishTitle,
1772 UNUSED(operationType);
1774 useCaseReview(REVIEW_USE_CASE,
1803 const char *reviewTitle,
1804 const char *reviewSubTitle,
1805 const char *finishTitle,
1809 UNUSED(operationType);
1812 useCaseReview(REVIEW_USE_CASE,
1843 const char *reviewTitle,
1844 const char *reviewSubTitle,
1845 const char *finishTitle,
1849 UNUSED(operationType);
1852 useCaseReview(REVIEW_BLIND_SIGN_USE_CASE,
1878 const char *reviewTitle,
1879 const char *reviewSubTitle,
1880 const char *finishTitle,
1911 const char *reviewTitle,
1912 const char *reviewSubTitle,
1915 memset(&context, 0,
sizeof(UseCaseContext_t));
1916 context.type = ADDRESS_REVIEW_USE_CASE;
1917 context.review.address = address;
1918 context.review.reviewTitle = reviewTitle;
1919 context.review.reviewSubTitle = reviewSubTitle;
1920 context.review.icon = icon;
1921 context.review.onChoice = choiceCallback;
1922 context.currentPage = 0;
1924 context.nbPages = 4;
1925 if (additionalTagValueList) {
1926 context.review.tagValueList = PIC(additionalTagValueList);
1927 context.nbPages += additionalTagValueList->
nbPairs;
1942 const char *rejectText,
1945 memset(&context, 0,
sizeof(UseCaseContext_t));
1946 context.type = GENERIC_REVIEW_USE_CASE;
1947 context.content.rejectText = rejectText;
1948 context.content.quitCallback = rejectCallback;
1949 context.content.genericContents.nbContents = contents->
nbContents;
1955 context.content.genericContents.contentsList = PIC(contents->
contentsList);
1958 startUseCaseContent();
1972 memset(&context, 0,
sizeof(UseCaseContext_t));
1973 context.type = STATUS_USE_CASE;
1974 context.stepCallback = quitCallback;
1975 context.currentPage = 0;
1976 context.nbPages = 1;
1978 icon = isSuccess ? &C_icon_validate_14 : &C_icon_crossmark;
1979 drawStep(
SINGLE_STEP, icon, message, NULL, statusButtonCallback,
false);
1993 switch (reviewStatusType) {
1995 msg =
"Operation signed";
1999 msg =
"Operation rejected";
2003 msg =
"Transaction signed";
2007 msg =
"Transaction rejected";
2011 msg =
"Message signed";
2015 msg =
"Message rejected";
2019 msg =
"Address verified";
2023 msg =
"Address verification cancelled";
2046 const char *reviewTitle,
2047 const char *reviewSubTitle,
2050 UNUSED(operationType);
2052 memset(&context, 0,
sizeof(UseCaseContext_t));
2053 context.type = STREAMING_START_REVIEW_USE_CASE;
2054 context.review.reviewTitle = reviewTitle;
2055 context.review.reviewSubTitle = reviewSubTitle;
2056 context.review.icon = icon;
2057 context.review.onChoice = choiceCallback;
2058 context.currentPage = 0;
2059 context.nbPages = 2;
2079 const char *reviewTitle,
2080 const char *reviewSubTitle,
2083 UNUSED(operationType);
2085 memset(&context, 0,
sizeof(UseCaseContext_t));
2086 context.type = STREAMING_BLIND_SIGN_START_REVIEW_USE_CASE;
2087 context.review.reviewTitle = reviewTitle;
2088 context.review.reviewSubTitle = reviewSubTitle;
2089 context.review.icon = icon;
2090 context.review.onChoice = choiceCallback;
2091 context.currentPage = 0;
2092 context.nbPages = 3;
2114 memset(&context, 0,
sizeof(UseCaseContext_t));
2115 context.type = STREAMING_CONTINUE_REVIEW_USE_CASE;
2116 context.review.tagValueList = tagValueList;
2117 context.review.onChoice = choiceCallback;
2118 context.currentPage = 0;
2119 context.nbPages = tagValueList->
nbPairs + 1;
2120 context.review.skipCallback = skipCallback;
2144 UNUSED(finishTitle);
2146 memset(&context, 0,
sizeof(UseCaseContext_t));
2147 context.type = STREAMING_FINISH_REVIEW_USE_CASE;
2148 context.review.onChoice = choiceCallback;
2149 context.currentPage = 0;
2150 context.nbPages = 2;
2162 memset(&context, 0,
sizeof(UseCaseContext_t));
2163 context.type = SPINNER_USE_CASE;
2164 context.currentPage = 0;
2165 context.nbPages = 1;
2167 displaySpinner(text);
2171 const char *message,
2172 const char *subMessage,
2173 const char *confirmText,
2174 const char *cancelText,
2177 memset(&context, 0,
sizeof(UseCaseContext_t));
2178 context.type = CHOICE_USE_CASE;
2179 context.choice.icon = icon;
2180 context.choice.message = message;
2181 context.choice.subMessage = subMessage;
2182 context.choice.confirmText = confirmText;
2183 context.choice.cancelText = cancelText;
2184 context.choice.onChoice = callback;
2185 context.currentPage = 0;
2186 context.nbPages = 1 + 1 + 2;
2205 const char *subMessage,
2206 const char *confirmText,
2207 const char *cancelText,
2210 memset(&context, 0,
sizeof(UseCaseContext_t));
2211 context.type = CONFIRM_USE_CASE;
2212 context.confirm.message = message;
2213 context.confirm.subMessage = subMessage;
2214 context.confirm.confirmText = confirmText;
2215 context.confirm.cancelText = cancelText;
2216 context.confirm.onConfirm = callback;
2217 context.currentPage = 0;
2218 context.nbPages = 1 + 2;
2248 keypadGenericUseCase(
2249 title, minDigits, maxDigits, shuffled,
false, validatePinCallback, backCallback);
2277 keypadGenericUseCase(
2278 title, minDigits, maxDigits, shuffled,
true, validatePinCallback, backCallback);
@ CHOICES_LIST
list of choices through radio buttons
@ CENTERED_INFO
a centered info
@ SWITCHES_LIST
list of switches with descriptions
@ INFOS_LIST
list of infos with titles
@ TAG_VALUE_LIST
list of tag/value pairs
@ BARS_LIST
list of touchable bars (with > on the right to go to sub-pages)
@ INFO_BUTTON
a centered info and a simple black button
void(* nbgl_contentActionCallback_t)(int token, uint8_t index, int page)
prototype of function to be called when an action on a content object occurs
#define LOG_DEBUG(__logger,...)
void(* nbgl_stepCallback_t)(void)
prototype of function to be called when a step is using a callback on "double-key" action
void(* nbgl_layoutTouchCallback_t)(int token, uint8_t index)
prototype of function to be called when an object is touched
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_layoutDraw(nbgl_layout_t *layout)
Applies given layout. The screen will be redrawn.
void * nbgl_layout_t
type shared externally
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.
nbgl_layout_t * nbgl_layoutGet(const nbgl_layoutDescription_t *description)
returns a layout of the given type. The layout is reset
int nbgl_layoutAddKeypad(nbgl_layout_t *layout, keyboardCallback_t callback, bool shuffled)
Adds a keypad on bottom of the screen, with the associated callback.
void nbgl_refresh(void)
This functions refreshes the actual screen on display with what has changed since the last refresh.
@ BUTTON_BOTH_PRESSED
Sent when both buttons are released.
@ BUTTON_LEFT_PRESSED
Sent when Left button is released.
@ BUTTON_RIGHT_PRESSED
Send when Right button is released.
struct PACKED__ nbgl_screenTickerConfiguration_s nbgl_screenTickerConfiguration_t
struct to configure a screen layer
void nbgl_screenRedraw(void)
This function redraws the whole screen on top of stack and its children.
void(* nbgl_stepButtonCallback_t)(nbgl_step_t stepCtx, nbgl_buttonEvent_t event)
prototype of function to be called when buttons are touched on a screen
#define GET_POS_OF_STEP(_step, _nb_steps)
void * nbgl_step_t
type shared externally
uint8_t nbgl_stepPosition_t
this type contains nbgl_layoutNavIndication_t in its LSBs and direction in its MSB (using FORWARD_DIR...
@ NEITHER_FIRST_NOR_LAST_STEP
neither first nor last in a multiple steps flow
@ SINGLE_STEP
single step flow
nbgl_step_t nbgl_stepDrawMenuList(nbgl_stepMenuListCallback_t onActionCallback, nbgl_screenTickerConfiguration_t *ticker, nbgl_layoutMenuList_t *list, bool modal)
int nbgl_stepRelease(nbgl_step_t step)
#define FORWARD_DIRECTION
When the flow is navigated from last to first step.
nbgl_step_t nbgl_stepDrawText(nbgl_stepPosition_t pos, nbgl_stepButtonCallback_t onActionCallback, nbgl_screenTickerConfiguration_t *ticker, const char *text, const char *subText, nbgl_contentCenteredInfoStyle_t style, bool modal)
nbgl_step_t nbgl_stepDrawCenteredInfo(nbgl_stepPosition_t pos, nbgl_stepButtonCallback_t onActionCallback, nbgl_screenTickerConfiguration_t *ticker, nbgl_layoutCenteredInfo_t *info, bool modal)
#define BACKWARD_DIRECTION
nbgl_state_t
to represent a boolean state.
struct PACKED__ nbgl_icon_details_s nbgl_icon_details_t
Represents all information about an icon.
API of the Advanced BOLOS Graphical Library, for typical application use-cases.
uint8_t nbgl_useCaseGetNbTagValuesInPageExt(uint8_t nbPairs, const nbgl_contentTagValueList_t *tagValueList, uint8_t startIndex, bool isSkippable, bool *requireSpecificDisplay)
void(* nbgl_callback_t)(void)
prototype of generic callback function
void nbgl_useCaseGenericSettings(const char *appName, uint8_t initPage, const nbgl_genericContents_t *settingContents, const nbgl_contentInfoList_t *infosList, nbgl_callback_t quitCallback)
void nbgl_useCaseKeypadPIN(const char *title, uint8_t minDigits, uint8_t maxDigits, uint8_t backToken, bool shuffled, tune_index_e tuneId, nbgl_pinValidCallback_t validatePinCallback, nbgl_layoutTouchCallback_t actionCallback)
uint32_t nbgl_operationType_t
This mask is used to describe the type of operation to review with additional options It is a mask of...
void nbgl_useCaseReview(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, nbgl_choiceCallback_t choiceCallback)
uint8_t nbgl_useCaseGetNbTagValuesInPage(uint8_t nbPairs, const nbgl_contentTagValueList_t *tagValueList, uint8_t startIndex, bool *requireSpecificDisplay)
uint8_t nbgl_useCaseGetNbPagesForTagValueList(const nbgl_contentTagValueList_t *tagValueList)
void(* nbgl_pinValidCallback_t)(const uint8_t *pin, uint8_t pinLen)
prototype of pin validation callback function
void nbgl_useCaseReviewStreamingStart(nbgl_operationType_t operationType, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseHomeAndSettings(const char *appName, const nbgl_icon_details_t *appIcon, const char *tagline, const uint8_t initSettingPage, const nbgl_genericContents_t *settingContents, const nbgl_contentInfoList_t *infosList, const nbgl_homeAction_t *action, nbgl_callback_t quitCallback)
uint8_t nbgl_useCaseGetNbInfosInPage(uint8_t nbInfos, const nbgl_contentInfoList_t *infosList, uint8_t startIndex, bool withNav)
void(* nbgl_choiceCallback_t)(bool confirm)
prototype of choice callback function
uint8_t nbgl_useCaseGetNbBarsInPage(uint8_t nbBars, const nbgl_contentBarsList_t *barsList, uint8_t startIndex, bool withNav)
void nbgl_useCaseNavigableContent(const char *title, uint8_t initPage, uint8_t nbPages, nbgl_callback_t quitCallback, nbgl_navCallback_t navCallback, nbgl_layoutTouchCallback_t controlsCallback)
void nbgl_useCaseReviewStreamingFinish(const char *finishTitle, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseSpinner(const char *text)
void nbgl_useCaseConfirm(const char *message, const char *subMessage, const char *confirmText, const char *rejectText, nbgl_callback_t callback)
void nbgl_useCaseKeypadDigits(const char *title, uint8_t minDigits, uint8_t maxDigits, uint8_t backToken, bool shuffled, tune_index_e tuneId, nbgl_pinValidCallback_t validatePinCallback, nbgl_layoutTouchCallback_t actionCallback)
void nbgl_useCaseStatus(const char *message, bool isSuccess, nbgl_callback_t quitCallback)
void nbgl_useCaseGenericConfiguration(const char *title, uint8_t initPage, const nbgl_genericContents_t *contents, nbgl_callback_t quitCallback)
#define INIT_HOME_PAGE
Value to pass to nbgl_useCaseHomeAndSettings() initSettingPage parameter to initialize the use case o...
void nbgl_useCaseReviewStreamingContinueExt(const nbgl_contentTagValueList_t *tagValueList, nbgl_choiceCallback_t choiceCallback, nbgl_callback_t skipCallback)
void nbgl_useCaseReviewBlindSigning(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, const nbgl_tipBox_t *tipBox, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseChoice(const nbgl_icon_details_t *icon, const char *message, const char *subMessage, const char *confirmText, const char *rejectString, nbgl_choiceCallback_t callback)
void nbgl_useCaseGenericReview(const nbgl_genericContents_t *contents, const char *rejectText, nbgl_callback_t rejectCallback)
void nbgl_useCaseReviewStreamingBlindSigningStart(nbgl_operationType_t operationType, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseAdvancedReview(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, const nbgl_tipBox_t *tipBox, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseReviewStreamingContinue(const nbgl_contentTagValueList_t *tagValueList, nbgl_choiceCallback_t choiceCallback)
void nbgl_useCaseReviewLight(nbgl_operationType_t operationType, const nbgl_contentTagValueList_t *tagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, const char *finishTitle, nbgl_choiceCallback_t choiceCallback)
uint8_t nbgl_useCaseGetNbChoicesInPage(uint8_t nbChoices, const nbgl_contentRadioChoice_t *choicesList, uint8_t startIndex, bool withNav)
void nbgl_useCaseReviewStatus(nbgl_reviewStatusType_t reviewStatusType, nbgl_callback_t quitCallback)
nbgl_reviewStatusType_t
The different types of review status.
@ STATUS_TYPE_TRANSACTION_REJECTED
@ STATUS_TYPE_ADDRESS_REJECTED
@ STATUS_TYPE_TRANSACTION_SIGNED
@ STATUS_TYPE_OPERATION_REJECTED
@ STATUS_TYPE_OPERATION_SIGNED
@ STATUS_TYPE_ADDRESS_VERIFIED
@ STATUS_TYPE_MESSAGE_SIGNED
@ STATUS_TYPE_MESSAGE_REJECTED
bool(* nbgl_navCallback_t)(uint8_t page, nbgl_pageContent_t *content)
prototype of navigation callback function
void nbgl_useCaseAddressReview(const char *address, const nbgl_contentTagValueList_t *additionalTagValueList, const nbgl_icon_details_t *icon, const char *reviewTitle, const char *reviewSubTitle, nbgl_choiceCallback_t choiceCallback)
uint8_t nbgl_useCaseGetNbSwitchesInPage(uint8_t nbSwitches, const nbgl_contentSwitchesList_t *switchesList, uint8_t startIndex, bool withNav)
This structure contains data to build a BARS_LIST content.
const uint8_t * tokens
array of tokens, one for each bar (nbBars items)
const char *const * barTexts
array of texts for each bar (nbBars items, in black/bold)
uint8_t nbBars
number of elements in barTexts and tokens array
This structure contains info to build a centered (vertically and horizontally) area,...
const char * text2
second text (can be null)
const char * text1
first text (can be null)
bool onTop
if set to true, align only horizontally
nbgl_contentCenteredInfoStyle_t style
style to apply to this info
const nbgl_icon_details_t * icon
a buffer containing the 1BPP icon
const char * buttonText
text of the long press button
const nbgl_icon_details_t * icon
a buffer containing the 1BPP icon
const char * text
centered text in large case
This structure contains data to build a INFOS_LIST content.
uint8_t nbInfos
number of elements in infoTypes and infoContents array
const char *const * infoContents
array of contents of infos (in black)
const char *const * infoTypes
array of types of infos (in black/bold)
This structure contains a list of names to build a list of radio buttons (on the right part of screen...
uint8_t token
the token that will be used as argument of the callback
uint8_t initChoice
index of the current choice
const char *const * names
array of strings giving the choices (nbChoices)
uint8_t nbChoices
number of choices
This structure contains info to build a switch (on the right) with a description (on the left),...
const char * text
main text for the switch
uint8_t token
the token that will be used as argument of the callback
nbgl_state_t initState
initial state of the switch
const char * subText
description under main text (NULL terminated, single line, may be null)
This structure contains a list of [tag,value] pairs.
const nbgl_contentTagValue_t * pairs
array of [tag,value] pairs (nbPairs items). If NULL, callback is used instead
nbgl_contentTagValueCallback_t callback
function to call to retrieve a given pair
This structure contains a [tag,value] pair.
const char * value
string giving the value name
const char * item
string giving the tag name
This structure contains data to build a content.
nbgl_contentActionCallback_t contentActionCallback
callback to be called when an action on an object occurs
nbgl_contentType_t type
type of page content in the content union
uint8_t nbContents
number of contents
const nbgl_content_t * contentsList
array of nbgl_content_t (nbContents items).
nbgl_contentCallback_t contentGetterCallback
function to call to retrieve a given content
Structure describing the action button in Home Screen.
Structure containing all information when creating a layout. This structure must be passed as argumen...
This structure contains data to build a page in multi-pages mode (nbgl_pageDrawGenericContent)
nbgl_contentRadioChoice_t choicesList
CHOICES_LIST type
nbgl_contentSwitchesList_t switchesList
SWITCHES_LIST type
nbgl_contentBarsList_t barsList
BARS_LIST type
nbgl_contentInfoButton_t infoButton
INFO_BUTTON type
nbgl_contentInfoList_t infosList
INFOS_LIST type
nbgl_contentTagValueList_t tagValueList
TAG_VALUE_LIST type
nbgl_contentType_t type
type of page content in the following union
nbgl_contentCenteredInfo_t centeredInfo
CENTERED_INFO type
This structure contains data to build a SWITCHES_LIST content.
uint8_t nbSwitches
number of elements in switches and tokens array
const nbgl_contentSwitch_t * switches
array of switches (nbSwitches items)
The necessary parameters to build a tip-box in first review page and the modal if this tip box is tou...
nbgl_contentInfoList_t infosList
INFOS_LIST type
nbgl_contentTagValueList_t tagValueList
TAG_VALUE_LIST type
nbgl_contentCenteredInfo_t centeredInfo
CENTERED_INFO type
nbgl_contentBarsList_t barsList
BARS_LIST type
nbgl_contentSwitchesList_t switchesList
SWITCHES_LIST type
nbgl_contentInfoButton_t infoButton
INFO_BUTTON type
nbgl_contentRadioChoice_t choicesList
CHOICES_LIST type