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