Embedded SDK
Embedded SDK
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
30 typedef struct ux_flow_step_s ux_flow_step_t;
31 
36 typedef 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 
44 typedef 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 
65 unsigned int ux_flow_is_first(void); // to hide the left tick or not
66 unsigned int ux_flow_is_last(void); // to hide the right tick or not
67 typedef enum {
73 const ux_flow_step_t *ux_flow_get_current(void); // return the current step pointer
74 void ux_flow_next_no_display(void); // prepare displaying next step when flow is relayout
75 void ux_flow_next(void); // skip to next step
76 void ux_flow_prev(void); // go back to previous step
77 void ux_flow_validate(void); // called by layout's validation
78 void ux_flow_error(unsigned int error); // called by layout's error
79 unsigned int ux_flow_button_callback(unsigned int button_mask, unsigned int button_mask_counter);
80 // retrieve the parameters of the currently displayed step
82 const void *ux_stack_get_step_params(unsigned int stack_slot);
86 unsigned 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)
102 void 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 
109 void 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)
void ux_flow_prev(void)
unsigned int ux_flow_is_first(void)
void ux_flow_error(unsigned int error)
const void * ux_stack_get_step_params(unsigned int stack_slot)
void ux_flow_next_no_display(void)
const ux_flow_step_t * ux_flow_get_current(void)
const void * ux_stack_get_current_step_params(void)
void ux_flow_uninit(unsigned int stack_slot)
unsigned int ux_flow_button_callback(unsigned int button_mask, unsigned int button_mask_counter)
unsigned int ux_flow_is_last(void)
void ux_flow_validate(void)
unsigned int ux_flow_relayout(void)