expo: Add a function to poll for input

Both bootflow_menu and cedit use similar logic to poll an expo. Move
this into the expo library so the code can be shared.

Update bootflow_menu_run() to return -EPIPE when the user quits without
choosing anything, since -EAGAIN is ambiguous and elsewhere means that
there is no input yet.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2025-05-02 08:46:16 -06:00
parent 5c365ecabc
commit bf98604595
6 changed files with 66 additions and 71 deletions

View File

@@ -216,39 +216,8 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
done = false;
do {
struct expo_action act;
int ichar, key;
ret = expo_render(exp);
if (ret)
break;
ichar = cli_ch_process(&exp->cch, 0);
if (!ichar) {
while (!ichar && !tstc()) {
schedule();
mdelay(2);
ichar = cli_ch_process(&exp->cch, -ETIMEDOUT);
}
if (!ichar) {
ichar = getchar();
ichar = cli_ch_process(&exp->cch, ichar);
}
}
key = 0;
if (ichar) {
key = bootmenu_conv_key(ichar);
if (key == BKEY_NONE)
key = ichar;
}
if (!key)
continue;
ret = expo_send_key(exp, key);
if (ret)
break;
ret = expo_action_get(exp, &act);
ret = expo_poll(exp, &act);
if (!ret) {
switch (act.type) {
case EXPOACT_SELECT:
@@ -256,17 +225,15 @@ int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,
done = true;
break;
case EXPOACT_QUIT:
done = true;
break;
return -EPIPE;
default:
break;
}
} else if (ret != -EPIPE && ret != -EAGAIN) {
return log_msg_ret("bmr", ret);
}
} while (!done);
if (ret)
return log_msg_ret("end", ret);
if (sel_id) {
struct bootflow *bflow;
int i;

View File

@@ -166,39 +166,8 @@ int cedit_run(struct expo *exp)
save = false;
do {
struct expo_action act;
int ichar, key;
ret = expo_render(exp);
if (ret)
break;
ichar = cli_ch_process(&exp->cch, 0);
if (!ichar) {
while (!ichar && !tstc()) {
schedule();
mdelay(2);
ichar = cli_ch_process(&exp->cch, -ETIMEDOUT);
}
if (!ichar) {
ichar = getchar();
ichar = cli_ch_process(&exp->cch, ichar);
}
}
key = 0;
if (ichar) {
key = bootmenu_conv_key(ichar);
if (key == BKEY_NONE || key >= BKEY_FIRST_EXTRA)
key = ichar;
}
if (!key)
continue;
ret = expo_send_key(exp, key);
if (ret)
break;
ret = expo_action_get(exp, &act);
ret = expo_poll(exp, &act);
if (!ret) {
switch (act.type) {
case EXPOACT_POINT_OBJ:
@@ -233,6 +202,8 @@ int cedit_run(struct expo *exp)
default:
break;
}
} else if (ret != -EAGAIN) {
return log_msg_ret("cep", ret);
}
} while (!done);

View File

@@ -10,8 +10,12 @@
#include <dm.h>
#include <expo.h>
#include <log.h>
#include <malloc.h>
#include <menu.h>
#include <video.h>
#include <watchdog.h>
#include <linux/delay.h>
#include "scene_internal.h"
int expo_new(const char *name, void *priv, struct expo **expp)
@@ -286,3 +290,43 @@ int expo_iter_scene_objs(struct expo *exp, expo_scene_obj_iterator iter,
return 0;
}
int expo_poll(struct expo *exp, struct expo_action *act)
{
int ichar, key, ret;
ret = expo_render(exp);
if (ret)
return log_msg_ret("ere", ret);
ichar = cli_ch_process(&exp->cch, 0);
if (!ichar) {
while (!ichar && !tstc()) {
schedule();
mdelay(2);
ichar = cli_ch_process(&exp->cch, -ETIMEDOUT);
}
if (!ichar) {
ichar = getchar();
ichar = cli_ch_process(&exp->cch, ichar);
}
}
key = 0;
if (ichar) {
key = bootmenu_conv_key(ichar);
if (key == BKEY_NONE || key >= BKEY_FIRST_EXTRA)
key = ichar;
}
if (!key)
return -EAGAIN;
ret = expo_send_key(exp, key);
if (ret)
return log_msg_ret("epk", ret);
ret = expo_action_get(exp, act);
if (ret)
return log_msg_ret("eag", ret);
return 0;
}

View File

@@ -110,7 +110,7 @@ __maybe_unused static int bootflow_handle_menu(struct bootstd_priv *std,
ret = bootflow_menu_run(std, text_mode, &bflow);
if (ret) {
if (ret == -EAGAIN) {
if (ret == -EPIPE) {
printf("Nothing chosen\n");
std->cur_bootflow = NULL;
} else {

View File

@@ -508,7 +508,7 @@ int bootflow_menu_apply_theme(struct expo *exp, ofnode node);
* @std: Bootstd information
* @text_mode: Uses a text-based menu suitable for a serial port
* @bflowp: Returns chosen bootflow (set to NULL if nothing is chosen)
* @return 0 if an option was chosen, -EAGAIN if nothing was chosen, -ve on
* @return 0 if an option was chosen, -EPIPE if nothing was chosen, -ve on
* error
*/
int bootflow_menu_run(struct bootstd_priv *std, bool text_mode,

View File

@@ -772,4 +772,17 @@ int expo_build(ofnode root, struct expo **expp);
*/
int cb_expo_build(struct expo **expp);
/**
* expo_poll() - render an expo and see if the user takes an action
*
* Thsi calls expo_render() and then checks for a keypress. If there is one, it
* is processed and the resulting action returned, if any
*
* @exp: Expo to poll
* @act: Returns action on success
* Return: 0 if an action was obtained, -EAGAIN if not, other error if something
* went wrong
*/
int expo_poll(struct expo *exp, struct expo_action *act);
#endif /*__EXPO_H */