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 <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
expo_new(const char * name,void * priv,struct expo ** expp)16 int 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
estr_destroy(struct expo_string * estr)37 static void estr_destroy(struct expo_string *estr)
38 {
39 free(estr);
40 }
41
expo_destroy(struct expo * exp)42 void 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
expo_str(struct expo * exp,const char * name,uint id,const char * str)57 int 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
expo_get_str(struct expo * exp,uint id)72 const 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
expo_set_display(struct expo * exp,struct udevice * dev)84 int expo_set_display(struct expo *exp, struct udevice *dev)
85 {
86 exp->display = dev;
87
88 return 0;
89 }
90
exp_set_text_mode(struct expo * exp,bool text_mode)91 void exp_set_text_mode(struct expo *exp, bool text_mode)
92 {
93 exp->text_mode = text_mode;
94 }
95
expo_lookup_scene_id(struct expo * exp,uint scene_id)96 struct scene *expo_lookup_scene_id(struct expo *exp, uint scene_id)
97 {
98 struct scene *scn;
99
100 list_for_each_entry(scn, &exp->scene_head, sibling) {
101 if (scn->id == scene_id)
102 return scn;
103 }
104
105 return NULL;
106 }
107
expo_set_scene_id(struct expo * exp,uint scene_id)108 int expo_set_scene_id(struct expo *exp, uint scene_id)
109 {
110 if (!expo_lookup_scene_id(exp, scene_id))
111 return log_msg_ret("id", -ENOENT);
112 exp->scene_id = scene_id;
113
114 return 0;
115 }
116
expo_render(struct expo * exp)117 int expo_render(struct expo *exp)
118 {
119 struct udevice *dev = exp->display;
120 struct video_priv *vid_priv = dev_get_uclass_priv(dev);
121 struct scene *scn = NULL;
122 u32 colour;
123 int ret;
124
125 colour = video_index_to_colour(vid_priv, VID_WHITE);
126 ret = video_fill(dev, colour);
127 if (ret)
128 return log_msg_ret("fill", ret);
129
130 if (exp->scene_id) {
131 scn = expo_lookup_scene_id(exp, exp->scene_id);
132 if (!scn)
133 return log_msg_ret("scn", -ENOENT);
134
135 ret = scene_render(scn);
136 if (ret)
137 return log_msg_ret("ren", ret);
138 }
139
140 video_sync(dev, true);
141
142 return scn ? 0 : -ECHILD;
143 }
144
expo_send_key(struct expo * exp,int key)145 int expo_send_key(struct expo *exp, int key)
146 {
147 struct scene *scn = NULL;
148
149 if (exp->scene_id) {
150 int ret;
151
152 scn = expo_lookup_scene_id(exp, exp->scene_id);
153 if (!scn)
154 return log_msg_ret("scn", -ENOENT);
155
156 ret = scene_send_key(scn, key, &exp->action);
157 if (ret)
158 return log_msg_ret("key", ret);
159 }
160
161 return scn ? 0 : -ECHILD;
162 }
163
expo_action_get(struct expo * exp,struct expo_action * act)164 int expo_action_get(struct expo *exp, struct expo_action *act)
165 {
166 *act = exp->action;
167 exp->action.type = EXPOACT_NONE;
168
169 return act->type == EXPOACT_NONE ? -EAGAIN : 0;
170 }
171