47
47
/* max number of char for reduced QR Code address */
48
48
#define QRCODE_REDUCED_ADDR_LEN 128
49
49
50
+ // macros to ease access to shared contexts
51
+ #define keypadContext sharedContext.keypad
52
+ #define addressConfirmationContext sharedContext.addressConfirmation
53
+ #define blindSigningContext sharedContext.blindSigning
54
+
50
55
/**********************
51
56
* TYPEDEFS
52
57
**********************/
@@ -100,6 +105,29 @@ typedef struct KeypadContext_s {
100
105
} KeypadContext_t ;
101
106
#endif
102
107
108
+ typedef struct BlindSigningContext_s {
109
+ bool isStreaming ;
110
+ nbgl_operationType_t operationType ;
111
+ const nbgl_contentTagValueList_t * tagValueList ;
112
+ const nbgl_icon_details_t * icon ;
113
+ const char * reviewTitle ;
114
+ const char * reviewSubTitle ;
115
+ const char * finishTitle ;
116
+ const nbgl_tipBox_t * tipBox ;
117
+ nbgl_choiceCallback_t choiceCallback ;
118
+ nbgl_layout_t * layoutCtx ;
119
+ } BlindSigningContext_t ;
120
+
121
+ // this union is intended to save RAM for context storage
122
+ // indeed, these three contexts cannot happen simultaneously
123
+ typedef union {
124
+ #ifdef NBGL_KEYPAD
125
+ KeypadContext_t keypad ;
126
+ #endif
127
+ AddressConfirmationContext_t addressConfirmation ;
128
+ BlindSigningContext_t blindSigning ;
129
+ } SharedContext_t ;
130
+
103
131
typedef struct {
104
132
nbgl_genericContents_t genericContents ;
105
133
int8_t currentContentIdx ;
@@ -187,11 +215,8 @@ static NavType_t navType;
187
215
188
216
static DetailsContext_t detailsContext ;
189
217
190
- static AddressConfirmationContext_t addressConfirmationContext ;
191
-
192
- #ifdef NBGL_KEYPAD
193
- static KeypadContext_t keypadContext ;
194
- #endif
218
+ // multi-purpose context shared for non-concurrent usages
219
+ static SharedContext_t sharedContext ;
195
220
196
221
// contexts for generic navigation
197
222
static GenericContext_t genericContext ;
@@ -245,6 +270,23 @@ static void bundleNavStartSettingsAtPage(uint8_t initSettingPage);
245
270
static void bundleNavStartSettings (void );
246
271
247
272
static void bundleNavReviewStreamingChoice (bool confirm );
273
+ static void blindSigningWarning (void );
274
+ static void useCaseReview (nbgl_operationType_t operationType ,
275
+ const nbgl_contentTagValueList_t * tagValueList ,
276
+ const nbgl_icon_details_t * icon ,
277
+ const char * reviewTitle ,
278
+ const char * reviewSubTitle ,
279
+ const char * finishTitle ,
280
+ const nbgl_tipBox_t * tipBox ,
281
+ nbgl_choiceCallback_t choiceCallback ,
282
+ bool isLight ,
283
+ bool playNotifSound );
284
+ static void useCaseReviewStreamingStart (nbgl_operationType_t operationType ,
285
+ const nbgl_icon_details_t * icon ,
286
+ const char * reviewTitle ,
287
+ const char * reviewSubTitle ,
288
+ nbgl_choiceCallback_t choiceCallback ,
289
+ bool playNotifSound );
248
290
249
291
static void reset_callbacks (void )
250
292
{
@@ -914,7 +956,8 @@ static bool genericContextPreparePageContent(const nbgl_content_t *p_content,
914
956
}
915
957
916
958
bool isFirstOrLastPage
917
- = (p_content -> type == CENTERED_INFO ) || (p_content -> type == INFO_LONG_PRESS );
959
+ = ((p_content -> type == CENTERED_INFO ) || (p_content -> type == EXTENDED_CENTER ))
960
+ || (p_content -> type == INFO_LONG_PRESS );
918
961
bool isStreamingNavAndBlindOperation
919
962
= (navType == STREAMING_NAV )
920
963
&& (bundleNavContext .reviewStreaming .operationType & BLIND_OPERATION );
@@ -1646,6 +1689,54 @@ static void bundleNavReviewStreamingChoice(bool confirm)
1646
1689
}
1647
1690
}
1648
1691
1692
+ // function called when the warning page of Blind Signing review buttons are pressed
1693
+ static void blindSigningWarningCallback (bool confirm )
1694
+ {
1695
+ if (confirm ) { // top button to exit
1696
+ blindSigningContext .choiceCallback (false);
1697
+ }
1698
+ else { // bottom button to continue to review
1699
+ if (blindSigningContext .isStreaming ) {
1700
+ useCaseReviewStreamingStart (blindSigningContext .operationType ,
1701
+ blindSigningContext .icon ,
1702
+ blindSigningContext .reviewTitle ,
1703
+ blindSigningContext .reviewSubTitle ,
1704
+ blindSigningContext .choiceCallback ,
1705
+ false);
1706
+ }
1707
+ else {
1708
+ useCaseReview (blindSigningContext .operationType ,
1709
+ blindSigningContext .tagValueList ,
1710
+ blindSigningContext .icon ,
1711
+ blindSigningContext .reviewTitle ,
1712
+ blindSigningContext .reviewSubTitle ,
1713
+ blindSigningContext .finishTitle ,
1714
+ blindSigningContext .tipBox ,
1715
+ blindSigningContext .choiceCallback ,
1716
+ false,
1717
+ false);
1718
+ }
1719
+ }
1720
+ }
1721
+
1722
+ // function used to display the warning page when starting a Bling Signing review
1723
+ static void blindSigningWarning (void )
1724
+ {
1725
+ // Play notification sound
1726
+ #ifdef HAVE_PIEZO_SOUND
1727
+ io_seproxyhal_play_tune (TUNE_LOOK_AT_ME );
1728
+ #endif // HAVE_PIEZO_SOUND
1729
+ nbgl_useCaseChoice (
1730
+ & C_Warning_64px ,
1731
+ "Blind signing ahead" ,
1732
+ "This transaction's details are not fully verifiable. If you sign it, you could lose all "
1733
+ "your assets." ,
1734
+ "Back to safety" ,
1735
+ "Continue anyway" ,
1736
+ blindSigningWarningCallback );
1737
+ }
1738
+
1739
+ // function to factorize code for all simple reviews
1649
1740
static void useCaseReview (nbgl_operationType_t operationType ,
1650
1741
const nbgl_contentTagValueList_t * tagValueList ,
1651
1742
const nbgl_icon_details_t * icon ,
@@ -1654,7 +1745,8 @@ static void useCaseReview(nbgl_operationType_t operationType,
1654
1745
const char * finishTitle ,
1655
1746
const nbgl_tipBox_t * tipBox ,
1656
1747
nbgl_choiceCallback_t choiceCallback ,
1657
- bool isLight )
1748
+ bool isLight ,
1749
+ bool playNotifSound )
1658
1750
{
1659
1751
reset_callbacks ();
1660
1752
memset (& genericContext , 0 , sizeof (genericContext ));
@@ -1708,10 +1800,58 @@ static void useCaseReview(nbgl_operationType_t operationType,
1708
1800
uint8_t nbPages = nbgl_useCaseGetNbPagesForGenericContents (& genericContext .genericContents , 0 );
1709
1801
prepareNavInfo (true, nbPages , getRejectReviewText (operationType ));
1710
1802
1803
+ // Play notification sound if required
1804
+ if (playNotifSound ) {
1711
1805
#ifdef HAVE_PIEZO_SOUND
1712
- // Play notification sound
1713
- io_seproxyhal_play_tune (TUNE_LOOK_AT_ME );
1806
+ io_seproxyhal_play_tune (TUNE_LOOK_AT_ME );
1807
+ #endif // HAVE_PIEZO_SOUND
1808
+ }
1809
+
1810
+ displayGenericContextPage (0 , true);
1811
+ }
1812
+
1813
+ // function to factorize code for all streaming reviews
1814
+ static void useCaseReviewStreamingStart (nbgl_operationType_t operationType ,
1815
+ const nbgl_icon_details_t * icon ,
1816
+ const char * reviewTitle ,
1817
+ const char * reviewSubTitle ,
1818
+ nbgl_choiceCallback_t choiceCallback ,
1819
+ bool playNotifSound )
1820
+ {
1821
+ reset_callbacks ();
1822
+ memset (& genericContext , 0 , sizeof (genericContext ));
1823
+
1824
+ bundleNavContext .reviewStreaming .operationType = operationType ;
1825
+ bundleNavContext .reviewStreaming .choiceCallback = choiceCallback ;
1826
+ bundleNavContext .reviewStreaming .icon = icon ;
1827
+
1828
+ // memorize context
1829
+ onChoice = bundleNavReviewStreamingChoice ;
1830
+ navType = STREAMING_NAV ;
1831
+ pageTitle = NULL ;
1832
+
1833
+ genericContext .genericContents .contentsList = localContentsList ;
1834
+ genericContext .genericContents .nbContents = 1 ;
1835
+ memset (localContentsList , 0 , 1 * sizeof (nbgl_content_t ));
1836
+
1837
+ // First a centered info
1838
+ STARTING_CONTENT .type = EXTENDED_CENTER ;
1839
+ prepareReviewFirstPage (
1840
+ & STARTING_CONTENT .content .extendedCenter .contentCenter , icon , reviewTitle , reviewSubTitle );
1841
+
1842
+ // compute number of pages & fill navigation structure
1843
+ bundleNavContext .reviewStreaming .stepPageNb
1844
+ = nbgl_useCaseGetNbPagesForGenericContents (& genericContext .genericContents , 0 );
1845
+ prepareNavInfo (true, NBGL_NO_PROGRESS_INDICATOR , getRejectReviewText (operationType ));
1846
+ // no back button on first page
1847
+ navInfo .navWithButtons .backButton = false;
1848
+
1849
+ // Play notification sound if required
1850
+ if (playNotifSound ) {
1851
+ #ifdef HAVE_PIEZO_SOUND
1852
+ io_seproxyhal_play_tune (TUNE_LOOK_AT_ME );
1714
1853
#endif // HAVE_PIEZO_SOUND
1854
+ }
1715
1855
1716
1856
displayGenericContextPage (0 , true);
1717
1857
}
@@ -2833,7 +2973,8 @@ void nbgl_useCaseReview(nbgl_operationType_t operationType,
2833
2973
finishTitle ,
2834
2974
NULL ,
2835
2975
choiceCallback ,
2836
- false);
2976
+ false,
2977
+ true);
2837
2978
}
2838
2979
2839
2980
/**
@@ -2870,9 +3011,52 @@ void nbgl_useCaseAdvancedReview(nbgl_operationType_t operationType,
2870
3011
finishTitle ,
2871
3012
tipBox ,
2872
3013
choiceCallback ,
2873
- false);
3014
+ false,
3015
+ true);
2874
3016
}
2875
3017
3018
+ /**
3019
+ * @brief Draws a flow of pages of a blind-signing review. The review is preceded by a warning page
3020
+ *
3021
+ * Navigation operates with either swipe or navigation
3022
+ * keys at bottom right. The last page contains a long-press button with the given finishTitle and
3023
+ * the given icon.
3024
+ * @note All tag/value pairs are provided in the API and the number of pages is automatically
3025
+ * computed, the last page being a long press one
3026
+ *
3027
+ * @param operationType type of operation (Operation, Transaction, Message)
3028
+ * @param tagValueList list of tag/value pairs
3029
+ * @param icon icon used on first and last review page
3030
+ * @param reviewTitle string used in the first review page
3031
+ * @param reviewSubTitle string to set under reviewTitle (can be NULL)
3032
+ * @param finishTitle string used in the last review page
3033
+ * @param tipBox parameter to build a tip-box and necessary modal (can be NULL)
3034
+ * @param choiceCallback callback called when operation is accepted (param is true) or rejected
3035
+ * (param is false)
3036
+ */
3037
+ void nbgl_useCaseReviewBlindSigning (nbgl_operationType_t operationType ,
3038
+ const nbgl_contentTagValueList_t * tagValueList ,
3039
+ const nbgl_icon_details_t * icon ,
3040
+ const char * reviewTitle ,
3041
+ const char * reviewSubTitle ,
3042
+ const char * finishTitle ,
3043
+ const nbgl_tipBox_t * tipBox ,
3044
+ nbgl_choiceCallback_t choiceCallback )
3045
+ {
3046
+ memset (& blindSigningContext , 0 , sizeof (blindSigningContext ));
3047
+
3048
+ blindSigningContext .isStreaming = false;
3049
+ blindSigningContext .operationType = operationType | BLIND_OPERATION ;
3050
+ blindSigningContext .tagValueList = tagValueList ;
3051
+ blindSigningContext .icon = icon ;
3052
+ blindSigningContext .reviewTitle = reviewTitle ;
3053
+ blindSigningContext .reviewSubTitle = reviewSubTitle ;
3054
+ blindSigningContext .finishTitle = finishTitle ;
3055
+ blindSigningContext .tipBox = tipBox ;
3056
+ blindSigningContext .choiceCallback = choiceCallback ;
3057
+
3058
+ blindSigningWarning ();
3059
+ }
2876
3060
/**
2877
3061
* @brief Draws a flow of pages of a light review. Navigation operates with either swipe or
2878
3062
* navigation keys at bottom right. The last page contains a button/footer with the given
@@ -2905,6 +3089,7 @@ void nbgl_useCaseReviewLight(nbgl_operationType_t operationType,
2905
3089
finishTitle ,
2906
3090
NULL ,
2907
3091
choiceCallback ,
3092
+ true,
2908
3093
true);
2909
3094
}
2910
3095
@@ -2962,40 +3147,39 @@ void nbgl_useCaseReviewStreamingStart(nbgl_operationType_t operationType,
2962
3147
const char * reviewSubTitle ,
2963
3148
nbgl_choiceCallback_t choiceCallback )
2964
3149
{
2965
- reset_callbacks ();
2966
- memset (& genericContext , 0 , sizeof (genericContext ));
2967
-
2968
- bundleNavContext .reviewStreaming .operationType = operationType ;
2969
- bundleNavContext .reviewStreaming .choiceCallback = choiceCallback ;
2970
- bundleNavContext .reviewStreaming .icon = icon ;
2971
-
2972
- // memorize context
2973
- onChoice = bundleNavReviewStreamingChoice ;
2974
- navType = STREAMING_NAV ;
2975
- pageTitle = NULL ;
2976
-
2977
- genericContext .genericContents .contentsList = localContentsList ;
2978
- genericContext .genericContents .nbContents = 1 ;
2979
- memset (localContentsList , 0 , 1 * sizeof (nbgl_content_t ));
2980
-
2981
- // First a centered info
2982
- STARTING_CONTENT .type = EXTENDED_CENTER ;
2983
- prepareReviewFirstPage (
2984
- & STARTING_CONTENT .content .extendedCenter .contentCenter , icon , reviewTitle , reviewSubTitle );
2985
-
2986
- // compute number of pages & fill navigation structure
2987
- bundleNavContext .reviewStreaming .stepPageNb
2988
- = nbgl_useCaseGetNbPagesForGenericContents (& genericContext .genericContents , 0 );
2989
- prepareNavInfo (true, NBGL_NO_PROGRESS_INDICATOR , getRejectReviewText (operationType ));
2990
- // no back button on first page
2991
- navInfo .navWithButtons .backButton = false;
2992
-
2993
- #ifdef HAVE_PIEZO_SOUND
2994
- // Play notification sound
2995
- io_seproxyhal_play_tune (TUNE_LOOK_AT_ME );
2996
- #endif // HAVE_PIEZO_SOUND
3150
+ useCaseReviewStreamingStart (
3151
+ operationType , icon , reviewTitle , reviewSubTitle , choiceCallback , true);
3152
+ }
2997
3153
2998
- displayGenericContextPage (0 , true);
3154
+ /**
3155
+ * @brief Start drawing the flow of pages of a blind-signing review. The review is preceded by a
3156
+ * warning page
3157
+ * @note This should be followed by calls to nbgl_useCaseReviewStreamingContinue and finally to
3158
+ * nbgl_useCaseReviewStreamingFinish.
3159
+ *
3160
+ * @param operationType type of operation (Operation, Transaction, Message)
3161
+ * @param icon icon used on first and last review page
3162
+ * @param reviewTitle string used in the first review page
3163
+ * @param reviewSubTitle string to set under reviewTitle (can be NULL)
3164
+ * @param choiceCallback callback called when more operation data are needed (param is true) or
3165
+ * operation is rejected (param is false)
3166
+ */
3167
+ void nbgl_useCaseReviewStreamingBlindSigningStart (nbgl_operationType_t operationType ,
3168
+ const nbgl_icon_details_t * icon ,
3169
+ const char * reviewTitle ,
3170
+ const char * reviewSubTitle ,
3171
+ nbgl_choiceCallback_t choiceCallback )
3172
+ {
3173
+ memset (& blindSigningContext , 0 , sizeof (blindSigningContext ));
3174
+
3175
+ blindSigningContext .isStreaming = true;
3176
+ blindSigningContext .operationType = operationType | BLIND_OPERATION ;
3177
+ blindSigningContext .icon = icon ;
3178
+ blindSigningContext .reviewTitle = reviewTitle ;
3179
+ blindSigningContext .reviewSubTitle = reviewSubTitle ;
3180
+ blindSigningContext .choiceCallback = choiceCallback ;
3181
+
3182
+ blindSigningWarning ();
2999
3183
}
3000
3184
3001
3185
/**
0 commit comments