e0571671bcc0b1699f1bf6a1dfea8d6c2845170f
[openwrt/staging/jow.git] /
1 From 5a15437610e8e8c68dc347845a83d0cbad80ca08 Mon Sep 17 00:00:00 2001
2 From: Weijie Gao <weijie.gao@mediatek.com>
3 Date: Tue, 19 Jan 2021 10:58:48 +0800
4 Subject: [PATCH 51/71] cmd: bootmenu: add ability to select item by shortkey
5
6 Add ability to use shortkey to select item for bootmenu command
7
8 Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
9 ---
10 cmd/bootmenu.c | 34 ++++++++++++++++++++++++-----
11 common/menu.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++--
12 include/menu.h | 12 +++++++----
13 3 files changed, 93 insertions(+), 11 deletions(-)
14
15 --- a/cmd/bootmenu.c
16 +++ b/cmd/bootmenu.c
17 @@ -87,16 +87,17 @@ static char *bootmenu_choice_entry(void
18 struct bootmenu_data *menu = data;
19 struct bootmenu_entry *iter;
20 enum bootmenu_key key = KEY_NONE;
21 + int choice = -1;
22 int esc = 0;
23 int i;
24
25 while (1) {
26 if (menu->delay >= 0) {
27 /* Autoboot was not stopped */
28 - bootmenu_autoboot_loop(menu, &key, &esc);
29 + bootmenu_autoboot_loop(menu, &key, &esc, &choice);
30 } else {
31 /* Some key was pressed, so autoboot was stopped */
32 - bootmenu_loop(menu, &key, &esc);
33 + bootmenu_loop(menu, &key, &esc, &choice);
34 }
35
36 switch (key) {
37 @@ -110,6 +111,12 @@ static char *bootmenu_choice_entry(void
38 ++menu->active;
39 /* no menu key selected, regenerate menu */
40 return NULL;
41 + case KEY_CHOICE:
42 + menu->active = choice;
43 + if (!menu->last_choiced) {
44 + menu->last_choiced = true;
45 + return NULL;
46 + }
47 case KEY_SELECT:
48 iter = menu->first;
49 for (i = 0; i < menu->active; ++i)
50 @@ -167,6 +174,9 @@ static int prepare_bootmenu_entry(struct
51 unsigned short int i = *index;
52 struct bootmenu_entry *entry = NULL;
53 struct bootmenu_entry *iter = *current;
54 + char *choice_option;
55 + char choice_char;
56 + int len;
57
58 while ((option = bootmenu_getoption(i))) {
59
60 @@ -181,11 +191,24 @@ static int prepare_bootmenu_entry(struct
61 if (!entry)
62 return -ENOMEM;
63
64 - entry->title = strndup(option, sep - option);
65 + /* Add KEY_CHOICE support: '%d. %s\0' : len --> len + 4 */
66 + len = sep - option + 4;
67 + choice_option = malloc(len);
68 + if (!choice_option) {
69 + free(entry->title);
70 + free(entry);
71 + return -ENOMEM;
72 + }
73 + if (!get_choice_char(i, &choice_char))
74 + len = snprintf(choice_option, len, "%c. %s", choice_char, option);
75 + else
76 + len = snprintf(choice_option, len, " %s", option);
77 + entry->title = strndup(choice_option, len);
78 if (!entry->title) {
79 free(entry);
80 return -ENOMEM;
81 }
82 + free(choice_option);
83
84 entry->command = strdup(sep + 1);
85 if (!entry->command) {
86 @@ -331,6 +354,7 @@ static struct bootmenu_data *bootmenu_cr
87 menu->delay = delay;
88 menu->active = 0;
89 menu->first = NULL;
90 + menu->last_choiced = false;
91
92 default_str = env_get("bootmenu_default");
93 if (default_str)
94 @@ -366,9 +390,9 @@ static struct bootmenu_data *bootmenu_cr
95
96 /* Add Quit entry if entering U-Boot console is disabled */
97 if (!IS_ENABLED(CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE))
98 - entry->title = strdup("U-Boot console");
99 + entry->title = strdup("0. U-Boot console");
100 else
101 - entry->title = strdup("Quit");
102 + entry->title = strdup("0. Quit");
103
104 if (!entry->title) {
105 free(entry);
106 --- a/common/menu.c
107 +++ b/common/menu.c
108 @@ -47,6 +47,33 @@ struct menu {
109 int item_cnt;
110 };
111
112 +const char choice_chars[] = {
113 + '1', '2', '3', '4', '5', '6', '7', '8', '9',
114 + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
115 + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
116 + 'u', 'v', 'w', 'x', 'y', 'z'
117 +};
118 +
119 +static int find_choice(char choice)
120 +{
121 + int i;
122 +
123 + for (i = 0; i < ARRAY_SIZE(choice_chars); i++)
124 + if (tolower(choice) == choice_chars[i])
125 + return i;
126 +
127 + return -1;
128 +}
129 +
130 +int get_choice_char(int index, char *result)
131 +{
132 + if (index < ARRAY_SIZE(choice_chars))
133 + *result = choice_chars[index];
134 + else
135 + return -1;
136 + return 0;
137 +}
138 +
139 /*
140 * An iterator function for menu items. callback will be called for each item
141 * in m, with m, a pointer to the item, and extra being passed to callback. If
142 @@ -426,7 +453,7 @@ int menu_destroy(struct menu *m)
143 }
144
145 void bootmenu_autoboot_loop(struct bootmenu_data *menu,
146 - enum bootmenu_key *key, int *esc)
147 + enum bootmenu_key *key, int *esc, int *choice)
148 {
149 int i, c;
150
151 @@ -456,6 +483,19 @@ void bootmenu_autoboot_loop(struct bootm
152 break;
153 default:
154 *key = KEY_NONE;
155 + if (*esc)
156 + break;
157 +
158 + *choice = find_choice(c);
159 + if ((*choice >= 0 &&
160 + *choice < menu->count - 1)) {
161 + *key = KEY_CHOICE;
162 + } else if (c == '0') {
163 + *choice = menu->count - 1;
164 + *key = KEY_CHOICE;
165 + } else {
166 + *key = KEY_NONE;
167 + }
168 break;
169 }
170
171 @@ -475,10 +515,16 @@ void bootmenu_autoboot_loop(struct bootm
172 }
173
174 void bootmenu_loop(struct bootmenu_data *menu,
175 - enum bootmenu_key *key, int *esc)
176 + enum bootmenu_key *key, int *esc, int *choice)
177 {
178 int c;
179
180 + if (menu->last_choiced) {
181 + menu->last_choiced = false;
182 + *key = KEY_SELECT;
183 + return;
184 + }
185 +
186 if (*esc == 1) {
187 if (tstc()) {
188 c = getchar();
189 @@ -504,6 +550,14 @@ void bootmenu_loop(struct bootmenu_data
190 if (c == '\e') {
191 *esc = 1;
192 *key = KEY_NONE;
193 + } else {
194 + *choice = find_choice(c);
195 + if ((*choice >= 0 && *choice < menu->count - 1)) {
196 + *key = KEY_CHOICE;
197 + } else if (c == '0') {
198 + *choice = menu->count - 1;
199 + *key = KEY_CHOICE;
200 + }
201 }
202 break;
203 case 1:
204 --- a/include/menu.h
205 +++ b/include/menu.h
206 @@ -6,6 +6,8 @@
207 #ifndef __MENU_H__
208 #define __MENU_H__
209
210 +#include <linux/ctype.h>
211 +
212 struct menu;
213
214 struct menu *menu_create(char *title, int timeout, int prompt,
215 @@ -18,6 +20,8 @@ int menu_get_choice(struct menu *m, void
216 int menu_item_add(struct menu *m, char *item_key, void *item_data);
217 int menu_destroy(struct menu *m);
218 int menu_default_choice(struct menu *m, void **choice);
219 +/* Add KEY_CHOICE support */
220 +int get_choice_char(int index, char *result);
221
222 /**
223 * menu_show() Show a boot menu
224 @@ -40,6 +44,7 @@ struct bootmenu_data {
225 int active; /* active menu entry */
226 int count; /* total count of menu entries */
227 struct bootmenu_entry *first; /* first menu entry */
228 + bool last_choiced;
229 };
230
231 enum bootmenu_key {
232 @@ -51,11 +56,12 @@ enum bootmenu_key {
233 KEY_PLUS,
234 KEY_MINUS,
235 KEY_SPACE,
236 + KEY_CHOICE,
237 };
238
239 void bootmenu_autoboot_loop(struct bootmenu_data *menu,
240 - enum bootmenu_key *key, int *esc);
241 + enum bootmenu_key *key, int *esc, int *choice);
242 void bootmenu_loop(struct bootmenu_data *menu,
243 - enum bootmenu_key *key, int *esc);
244 + enum bootmenu_key *key, int *esc, int *choice);
245
246 #endif /* __MENU_H__ */