Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
ux_flow_engine.h
Go to the documentation of this file.
1
2/*******************************************************************************
3 * Ledger Nano S - Secure firmware
4 * (c) 2022 Ledger
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 ********************************************************************************/
18
19#pragma once
20
21#include "os_seed.h"
22#include "os_helpers.h"
23
24#define STEPSPIC(x) ((const ux_flow_step_t *const *) PIC(x))
25#define STEPPIC(x) ((const ux_flow_step_t *) PIC(x))
26#define INITPIC(x) ((ux_flow_step_init_t) PIC(x))
27#define STRPIC(x) ((const char *) PIC(x))
28
29// forward definition
31
36typedef struct {
37 const ux_flow_step_t *const *steps;
38 unsigned short index;
39 unsigned short prev_index; // to know the direction the user is browsing the flow
40 unsigned short length;
41
43
44typedef void (*ux_flow_step_init_t)(unsigned int stack_slot);
45
47 // when NULL, cast flow_step structure as a ux_flow_step_jump_t and switch to the referenced
48 // flow
50
51 // this field is the one used by layouts to retrieve data to display.
52 const void *params;
53
54 // when NULL and more step in the flow, ux_flow_validate act as ux_flow_next
55 const ux_flow_step_t *const
56 *validate_flow; // for both button actions to jump onto a new flow, use init of first step
57 // of the flow to trigger a custom function upon validate. that is quite
58 // compact.
59 // when NULL, error are ignored
60 const ux_flow_step_t *const
61 *error_flow; // for both button actions to jump onto a new flow, use init of first step of
62 // the flow to trigger a custom function upon validate. that is quite compact.
63};
64
65unsigned int ux_flow_is_first(void); // to hide the left tick or not
66unsigned int ux_flow_is_last(void); // to hide the right tick or not
73const ux_flow_step_t *ux_flow_get_current(void); // return the current step pointer
74void ux_flow_next_no_display(void); // prepare displaying next step when flow is relayout
75void ux_flow_next(void); // skip to next step
76void ux_flow_prev(void); // go back to previous step
77void ux_flow_validate(void); // called by layout's validation
78void ux_flow_error(unsigned int error); // called by layout's error
79unsigned int ux_flow_button_callback(unsigned int button_mask, unsigned int button_mask_counter);
80// retrieve the parameters of the currently displayed step
82const void *ux_stack_get_step_params(unsigned int stack_slot);
86unsigned int ux_flow_relayout(void); // ask for a redisplay of the current displayed step (calling
87 // step init function again (recomputing layout if required))
88
92#define FLOW_END_STEP ((const ux_flow_step_t *) 0xFFFFFFFFUL)
96#define FLOW_BARRIER ((const ux_flow_step_t *) 0xFFFFFFFEUL)
101#define FLOW_LOOP ((const ux_flow_step_t *) 0xFFFFFFFDUL)
102void ux_flow_init(unsigned int stack_slot,
103 const ux_flow_step_t *const *steps,
104 const ux_flow_step_t *const start_step);
105
109void ux_flow_uninit(unsigned int stack_slot);
110
114#define UX_STEP_FLOWS(stepname, layoutkind, preinit, timeout_ms, validate_flow, error_flow, ...) \
115 void stepname##_init(unsigned int stack_slot) \
116 { \
117 preinit; \
118 ux_layout_##layoutkind##_init(stack_slot); \
119 ux_layout_set_timeout(stack_slot, timeout_ms); \
120 } \
121 const ux_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \
122 const ux_flow_step_t stepname = { \
123 stepname##_init, \
124 &stepname##_val, \
125 validate_flow, \
126 error_flow, \
127 }
128
129#define UX_STEP(stepname, layoutkind, preinit, timeout_ms, validate_cb, error_flow, ...) \
130 UX_FLOW_CALL(stepname##_validate, { validate_cb; }) \
131 void stepname##_init(unsigned int stack_slot) \
132 { \
133 preinit; \
134 ux_layout_##layoutkind##_init(stack_slot); \
135 ux_layout_set_timeout(stack_slot, timeout_ms); \
136 } \
137 const ux_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \
138 const ux_flow_step_t stepname = { \
139 stepname##_init, \
140 &stepname##_val, \
141 stepname##_validate, \
142 error_flow, \
143 }
144
148#define UX_STEP_INIT(stepname, validate_flow, error_flow, ...) \
149 void stepname##_init(unsigned int stack_slot) \
150 { \
151 UNUSED(stack_slot); \
152 __VA_ARGS__; \
153 } \
154 const ux_flow_step_t stepname = { \
155 stepname##_init, \
156 NULL, \
157 validate_flow, \
158 error_flow, \
159 }
160// deprecated
161#define UX_FLOW_DEF_INIT UX_STEP_INIT
162
166#define UX_STEP_CB(stepname, layoutkind, validate_cb, ...) \
167 UX_FLOW_CALL(stepname##_validate, { validate_cb; }) \
168 const ux_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \
169 const ux_flow_step_t stepname = { \
170 ux_layout_##layoutkind##_init, \
171 &stepname##_val, \
172 stepname##_validate, \
173 NULL, \
174 }
175// deprecated
176#define UX_FLOW_DEF_VALID UX_STEP_VALID
177// deprecated
178#define UX_STEP_VALID UX_STEP_CB
179
183#define UX_STEP_FLOWCB(stepname, layoutkind, validate_flow, error_flow, ...) \
184 const ux_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \
185 const ux_flow_step_t stepname = { \
186 ux_layout_##layoutkind##_init, \
187 &stepname##_val, \
188 validate_flow, \
189 error_flow, \
190 }
191
196#define UX_STEP_CB_INIT(stepname, layoutkind, preinit, validate_cb, ...) \
197 UX_FLOW_CALL(stepname##_validate, { validate_cb; }) \
198 void stepname##_init(unsigned int stack_slot) \
199 { \
200 preinit; \
201 ux_layout_##layoutkind##_init(stack_slot); \
202 } \
203 const ux_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \
204 const ux_flow_step_t stepname = { \
205 stepname##_init, \
206 &stepname##_val, \
207 stepname##_validate, \
208 NULL, \
209 }
210
214#define UX_STEP_TIMEOUT(stepname, layoutkind, timeout_ms, validate_flow, ...) \
215 void stepname##_init(unsigned int stack_slot) \
216 { \
217 ux_layout_##layoutkind##_init(stack_slot); \
218 ux_layout_set_timeout(stack_slot, timeout_ms); \
219 } \
220 const ux_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \
221 const ux_flow_step_t stepname = { \
222 stepname##_init, \
223 &stepname##_val, \
224 validate_flow, \
225 NULL, \
226 }
227
231#define UX_STEP_NOCB(stepname, layoutkind, ...) \
232 const ux_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \
233 const ux_flow_step_t stepname = { \
234 ux_layout_##layoutkind##_init, \
235 &stepname##_val, \
236 NULL, \
237 NULL, \
238 }
239// deprecated
240#define UX_FLOW_DEF_NOCB UX_STEP_NOCB
241
246#define UX_STEP_NOCB_INIT(stepname, layoutkind, preinit, ...) \
247 void stepname##_init(unsigned int stack_slot) \
248 { \
249 preinit; \
250 ux_layout_##layoutkind##_init(stack_slot); \
251 } \
252 const ux_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \
253 const ux_flow_step_t stepname = { \
254 stepname##_init, \
255 &stepname##_val, \
256 NULL, \
257 NULL, \
258 }
259
264#define UX_STEP_NOCB_POSTINIT(stepname, layoutkind, postinit, ...) \
265 void stepname##_init(unsigned int stack_slot) \
266 { \
267 ux_layout_##layoutkind##_init(stack_slot); \
268 postinit; \
269 } \
270 const ux_layout_##layoutkind##_params_t stepname##_val = __VA_ARGS__; \
271 const ux_flow_step_t stepname = { \
272 stepname##_init, \
273 &stepname##_val, \
274 NULL, \
275 NULL, \
276 }
277
282#define UX_FLOW_CALL(flow_name, code) \
283 void flow_name##init(unsigned int stack_slot) \
284 { \
285 UNUSED(stack_slot); \
286 code; \
287 } \
288 const ux_flow_step_t flow_name##_step = {flow_name##init, NULL, NULL, NULL}; \
289 const ux_flow_step_t *const flow_name[] = { \
290 &flow_name##_step, \
291 FLOW_END_STEP, \
292 };
293
297#define UX_FLOW(flow_name, ...) \
298 const ux_flow_step_t *const flow_name[] = {__VA_ARGS__, FLOW_END_STEP}
299// deprecated
300#define UX_DEF UX_FLOW
301
302#define UX_STEP_AFTER_PIN(stepname, stackslot, callback) \
303 /* step ask pin */ \
304 UX_STEP_INIT(stepname##__askpin, NULL, NULL, { \
305 if (os_perso_isonboarded() == BOLOS_UX_OK) { \
306 /* prepare skipping to current step */ \
307 ux_flow_next_no_display(); \
308 /* invalidate pin and display pin lock */ \
309 screen_modal_validate_pin_init(); \
310 } \
311 else { \
312 callback(0); \
313 } \
314 }); \
315 /* step callback */ \
316 UX_STEP_INIT(stepname##__pincallback, NULL, NULL, { callback(0); }); \
317 /* flow new 2 steps */ \
318 UX_FLOW(stepname##__pinflow, &stepname##__askpin, &stepname##__pincallback); \
319 /* run new flow */ \
320 UX_STEP_INIT(stepname, NULL, NULL, { ux_flow_init(stackslot, stepname##__pinflow, NULL); });
321
322#include "ux.h"
const ux_flow_step_t *const * steps
unsigned short prev_index
unsigned short index
unsigned short length
const void * params
const ux_flow_step_t *const * error_flow
const ux_flow_step_t *const * validate_flow
ux_flow_step_init_t init
void ux_flow_init(unsigned int stack_slot, const ux_flow_step_t *const *steps, const ux_flow_step_t *const start_step)
ux_flow_direction_t
@ FLOW_DIRECTION_BACKWARD
@ FLOW_DIRECTION_FORWARD
@ FLOW_DIRECTION_START
ux_flow_direction_t ux_flow_direction(void)
void ux_flow_next(void)
void(* ux_flow_step_init_t)(unsigned int stack_slot)
const ux_flow_step_t * ux_flow_get_current(void)
void ux_flow_prev(void)
unsigned int ux_flow_is_first(void)
void ux_flow_error(unsigned int error)
void ux_flow_next_no_display(void)
void ux_flow_uninit(unsigned int stack_slot)
unsigned int ux_flow_button_callback(unsigned int button_mask, unsigned int button_mask_counter)
const void * ux_stack_get_step_params(unsigned int stack_slot)
unsigned int ux_flow_is_last(void)
void ux_flow_validate(void)
const void * ux_stack_get_current_step_params(void)
unsigned int ux_flow_relayout(void)