blob: cd1b1a3de50c0a487b7e5bcc0cd6b7d4ceda92bb [file] [log] [blame]
Simon Glass87c6f8a2023-01-06 08:52:36 -06001// 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 <sjg@chromium.org>
7 */
8
9#include <common.h>
10#include <dm.h>
11#include <expo.h>
12#include <malloc.h>
13#include <video.h>
14#include "scene_internal.h"
15
16int expo_new(const char *name, void *priv, struct expo **expp)
17{
18 struct expo *exp;
19
20 exp = calloc(1, sizeof(struct expo));
21 if (!exp)
22 return log_msg_ret("expo", -ENOMEM);
23 exp->name = strdup(name);
24 if (!exp->name) {
25 free(exp);
26 return log_msg_ret("name", -ENOMEM);
27 }
28 exp->priv = priv;
29 INIT_LIST_HEAD(&exp->scene_head);
30 INIT_LIST_HEAD(&exp->str_head);
31
32 *expp = exp;
33
34 return 0;
35}
36
37static void estr_destroy(struct expo_string *estr)
38{
39 free(estr);
40}
41
42void expo_destroy(struct expo *exp)
43{
44 struct scene *scn, *next;
45 struct expo_string *estr, *enext;
46
47 list_for_each_entry_safe(scn, next, &exp->scene_head, sibling)
48 scene_destroy(scn);
49
50 list_for_each_entry_safe(estr, enext, &exp->str_head, sibling)
51 estr_destroy(estr);
52
53 free(exp->name);
54 free(exp);
55}
56
57int expo_str(struct expo *exp, const char *name, uint id, const char *str)
58{
59 struct expo_string *estr;
60
61 estr = calloc(1, sizeof(struct expo_string));
62 if (!estr)
63 return log_msg_ret("obj", -ENOMEM);
64
65 estr->id = resolve_id(exp, id);
66 estr->str = str;
67 list_add_tail(&estr->sibling, &exp->str_head);
68
69 return estr->id;
70}
71
72const char *expo_get_str(struct expo *exp, uint id)
73{
74 struct expo_string *estr;
75
76 list_for_each_entry(estr, &exp->str_head, sibling) {
77 if (estr->id == id)
78 return estr->str;
79 }
80
81 return NULL;
82}
83
84int expo_set_display(struct expo *exp, struct udevice *dev)
85{
Simon Glass42b18492023-06-01 10:22:34 -060086 struct udevice *cons;
87 int ret;
88
89 ret = device_find_first_child_by_uclass(dev, UCLASS_VIDEO_CONSOLE,
90 &cons);
91 if (ret)
92 return log_msg_ret("con", ret);
93
Simon Glass87c6f8a2023-01-06 08:52:36 -060094 exp->display = dev;
Simon Glass42b18492023-06-01 10:22:34 -060095 exp->cons = cons;
Simon Glass87c6f8a2023-01-06 08:52:36 -060096
97 return 0;
98}
99
100void exp_set_text_mode(struct expo *exp, bool text_mode)
101{
102 exp->text_mode = text_mode;
103}
104
105struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id)
106{
107 struct scene *scn;
108
109 list_for_each_entry(scn, &exp->scene_head, sibling) {
110 if (scn->id == scene_id)
111 return scn;
112 }
113
114 return NULL;
115}
116
117int expo_set_scene_id(struct expo *exp, uint scene_id)
118{
119 if (!expo_lookup_scene_id(exp, scene_id))
120 return log_msg_ret("id", -ENOENT);
121 exp->scene_id = scene_id;
122
123 return 0;
124}
125
126int expo_render(struct expo *exp)
127{
128 struct udevice *dev = exp->display;
129 struct video_priv *vid_priv = dev_get_uclass_priv(dev);
130 struct scene *scn = NULL;
131 u32 colour;
132 int ret;
133
134 colour = video_index_to_colour(vid_priv, VID_WHITE);
135 ret = video_fill(dev, colour);
136 if (ret)
137 return log_msg_ret("fill", ret);
138
139 if (exp->scene_id) {
140 scn = expo_lookup_scene_id(exp, exp->scene_id);
141 if (!scn)
142 return log_msg_ret("scn", -ENOENT);
143
144 ret = scene_render(scn);
145 if (ret)
146 return log_msg_ret("ren", ret);
147 }
148
149 video_sync(dev, true);
150
151 return scn ? 0 : -ECHILD;
152}
153
154int expo_send_key(struct expo *exp, int key)
155{
156 struct scene *scn = NULL;
157
158 if (exp->scene_id) {
159 int ret;
160
161 scn = expo_lookup_scene_id(exp, exp->scene_id);
162 if (!scn)
163 return log_msg_ret("scn", -ENOENT);
164
165 ret = scene_send_key(scn, key, &exp->action);
166 if (ret)
167 return log_msg_ret("key", ret);
168 }
169
170 return scn ? 0 : -ECHILD;
171}
172
173int expo_action_get(struct expo *exp, struct expo_action *act)
174{
175 *act = exp->action;
176 exp->action.type = EXPOACT_NONE;
177
178 return act->type == EXPOACT_NONE ? -EAGAIN : 0;
179}