]>
Commit | Line | Data |
---|---|---|
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 | ||
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 | ||
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 | ||
37 | static void estr_destroy(struct expo_string *estr) | |
38 | { | |
39 | free(estr); | |
40 | } | |
41 | ||
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 | ||
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 | ||
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 | ||
84 | int expo_set_display(struct expo *exp, struct udevice *dev) | |
85 | { | |
86 | exp->display = dev; | |
87 | ||
88 | return 0; | |
89 | } | |
90 | ||
91 | void exp_set_text_mode(struct expo *exp, bool text_mode) | |
92 | { | |
93 | exp->text_mode = text_mode; | |
94 | } | |
95 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | } |