]> Git Repo - J-u-boot.git/blob - boot/expo.c
Merge patch series "Enable EFI capsule updates for PHYTEC K3 SoMs"
[J-u-boot.git] / boot / expo.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Implementation of a expo, a collection of scenes providing menu options
4  *
5  * Copyright 2022 Google LLC
6  * Written by Simon Glass <[email protected]>
7  */
8
9 #define LOG_CATEGORY    LOGC_EXPO
10
11 #include <dm.h>
12 #include <expo.h>
13 #include <malloc.h>
14 #include <video.h>
15 #include "scene_internal.h"
16
17 int expo_new(const char *name, void *priv, struct expo **expp)
18 {
19         struct expo *exp;
20
21         exp = calloc(1, sizeof(struct expo));
22         if (!exp)
23                 return log_msg_ret("expo", -ENOMEM);
24         exp->name = strdup(name);
25         if (!exp->name) {
26                 free(exp);
27                 return log_msg_ret("name", -ENOMEM);
28         }
29         exp->priv = priv;
30         INIT_LIST_HEAD(&exp->scene_head);
31         INIT_LIST_HEAD(&exp->str_head);
32         exp->next_id = EXPOID_BASE_ID;
33
34         *expp = exp;
35
36         return 0;
37 }
38
39 static void estr_destroy(struct expo_string *estr)
40 {
41         free(estr);
42 }
43
44 void expo_destroy(struct expo *exp)
45 {
46         struct scene *scn, *next;
47         struct expo_string *estr, *enext;
48
49         list_for_each_entry_safe(scn, next, &exp->scene_head, sibling)
50                 scene_destroy(scn);
51
52         list_for_each_entry_safe(estr, enext, &exp->str_head, sibling)
53                 estr_destroy(estr);
54
55         free(exp->name);
56         free(exp);
57 }
58
59 uint resolve_id(struct expo *exp, uint id)
60 {
61         log_debug("resolve id %d\n", id);
62         if (!id)
63                 id = exp->next_id++;
64         else if (id >= exp->next_id)
65                 exp->next_id = id + 1;
66
67         return id;
68 }
69
70 void expo_set_dynamic_start(struct expo *exp, uint dyn_start)
71 {
72         exp->next_id = dyn_start;
73 }
74
75 int expo_str(struct expo *exp, const char *name, uint id, const char *str)
76 {
77         struct expo_string *estr;
78
79         estr = calloc(1, sizeof(struct expo_string));
80         if (!estr)
81                 return log_msg_ret("obj", -ENOMEM);
82
83         estr->id = resolve_id(exp, id);
84         estr->str = str;
85         list_add_tail(&estr->sibling, &exp->str_head);
86
87         return estr->id;
88 }
89
90 const char *expo_get_str(struct expo *exp, uint id)
91 {
92         struct expo_string *estr;
93
94         list_for_each_entry(estr, &exp->str_head, sibling) {
95                 if (estr->id == id)
96                         return estr->str;
97         }
98
99         return NULL;
100 }
101
102 int expo_set_display(struct expo *exp, struct udevice *dev)
103 {
104         struct udevice *cons;
105         int ret;
106
107         ret = device_find_first_child_by_uclass(dev, UCLASS_VIDEO_CONSOLE,
108                                                 &cons);
109         if (ret)
110                 return log_msg_ret("con", ret);
111
112         exp->display = dev;
113         exp->cons = cons;
114
115         return 0;
116 }
117
118 int expo_calc_dims(struct expo *exp)
119 {
120         struct scene *scn;
121         int ret;
122
123         if (!exp->cons)
124                 return log_msg_ret("dim", -ENOTSUPP);
125
126         list_for_each_entry(scn, &exp->scene_head, sibling) {
127                 /*
128                  * Do the menus last so that all the menus' text objects
129                  * are dimensioned
130                  */
131                 ret = scene_calc_dims(scn, false);
132                 if (ret)
133                         return log_msg_ret("scn", ret);
134                 ret = scene_calc_dims(scn, true);
135                 if (ret)
136                         return log_msg_ret("scn", ret);
137         }
138
139         return 0;
140 }
141
142 void expo_set_text_mode(struct expo *exp, bool text_mode)
143 {
144         exp->text_mode = text_mode;
145 }
146
147 struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id)
148 {
149         struct scene *scn;
150
151         list_for_each_entry(scn, &exp->scene_head, sibling) {
152                 if (scn->id == scene_id)
153                         return scn;
154         }
155
156         return NULL;
157 }
158
159 int expo_set_scene_id(struct expo *exp, uint scene_id)
160 {
161         struct scene *scn;
162         int ret;
163
164         scn = expo_lookup_scene_id(exp, scene_id);
165         if (!scn)
166                 return log_msg_ret("id", -ENOENT);
167         ret = scene_arrange(scn);
168         if (ret)
169                 return log_msg_ret("arr", ret);
170
171         exp->scene_id = scene_id;
172
173         return 0;
174 }
175
176 int expo_first_scene_id(struct expo *exp)
177 {
178         struct scene *scn;
179
180         if (list_empty(&exp->scene_head))
181                 return -ENOENT;
182
183         scn = list_first_entry(&exp->scene_head, struct scene, sibling);
184
185         return scn->id;
186 }
187
188 int expo_render(struct expo *exp)
189 {
190         struct udevice *dev = exp->display;
191         struct video_priv *vid_priv = dev_get_uclass_priv(dev);
192         struct scene *scn = NULL;
193         enum colour_idx back;
194         u32 colour;
195         int ret;
196
197         back = CONFIG_IS_ENABLED(SYS_WHITE_ON_BLACK) ? VID_BLACK : VID_WHITE;
198         colour = video_index_to_colour(vid_priv, back);
199         ret = video_fill(dev, colour);
200         if (ret)
201                 return log_msg_ret("fill", ret);
202
203         if (exp->scene_id) {
204                 scn = expo_lookup_scene_id(exp, exp->scene_id);
205                 if (!scn)
206                         return log_msg_ret("scn", -ENOENT);
207
208                 ret = scene_render(scn);
209                 if (ret)
210                         return log_msg_ret("ren", ret);
211         }
212
213         video_sync(dev, true);
214
215         return scn ? 0 : -ECHILD;
216 }
217
218 int expo_send_key(struct expo *exp, int key)
219 {
220         struct scene *scn = NULL;
221
222         if (exp->scene_id) {
223                 int ret;
224
225                 scn = expo_lookup_scene_id(exp, exp->scene_id);
226                 if (!scn)
227                         return log_msg_ret("scn", -ENOENT);
228
229                 ret = scene_send_key(scn, key, &exp->action);
230                 if (ret)
231                         return log_msg_ret("key", ret);
232
233                 /* arrange it to get any changes */
234                 ret = scene_arrange(scn);
235                 if (ret)
236                         return log_msg_ret("arr", ret);
237         }
238
239         return scn ? 0 : -ECHILD;
240 }
241
242 int expo_action_get(struct expo *exp, struct expo_action *act)
243 {
244         *act = exp->action;
245         exp->action.type = EXPOACT_NONE;
246
247         return act->type == EXPOACT_NONE ? -EAGAIN : 0;
248 }
249
250 int expo_apply_theme(struct expo *exp, ofnode node)
251 {
252         struct scene *scn;
253         struct expo_theme *theme = &exp->theme;
254         int ret;
255
256         log_debug("Applying theme %s\n", ofnode_get_name(node));
257
258         memset(theme, '\0', sizeof(struct expo_theme));
259         ofnode_read_u32(node, "font-size", &theme->font_size);
260         ofnode_read_u32(node, "menu-inset", &theme->menu_inset);
261         ofnode_read_u32(node, "menuitem-gap-y", &theme->menuitem_gap_y);
262         ofnode_read_u32(node, "menu-title-margin-x",
263                         &theme->menu_title_margin_x);
264
265         list_for_each_entry(scn, &exp->scene_head, sibling) {
266                 ret = scene_apply_theme(scn, theme);
267                 if (ret)
268                         return log_msg_ret("app", ret);
269         }
270
271         return 0;
272 }
273
274 int expo_iter_scene_objs(struct expo *exp, expo_scene_obj_iterator iter,
275                          void *priv)
276 {
277         struct scene *scn;
278         int ret;
279
280         list_for_each_entry(scn, &exp->scene_head, sibling) {
281                 ret = scene_iter_objs(scn, iter, priv);
282                 if (ret)
283                         return log_msg_ret("wr", ret);
284         }
285
286         return 0;
287 }
This page took 0.040706 seconds and 4 git commands to generate.