[PATCH v2 08/25] menu: Make use of CLI character processing

Simon Glass sjg at chromium.org
Fri Nov 4 23:48:26 CET 2022


Avoid duplicating some of the escape-sequence processing here and use the
CLI function instead.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v2:
- Rebase to master

 cmd/bootmenu.c     |  9 +++--
 cmd/eficonfig.c    | 12 ++++--
 common/cli_getch.c | 12 ++++--
 common/menu.c      | 92 +++++++++++++---------------------------------
 include/cli.h      |  4 +-
 include/menu.h     |  7 +++-
 6 files changed, 56 insertions(+), 80 deletions(-)

diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c
index 573afe16609..52d8c2f266d 100644
--- a/cmd/bootmenu.c
+++ b/cmd/bootmenu.c
@@ -4,6 +4,7 @@
  */
 
 #include <charset.h>
+#include <cli.h>
 #include <common.h>
 #include <command.h>
 #include <ansi.h>
@@ -84,19 +85,21 @@ static void bootmenu_print_entry(void *data)
 
 static char *bootmenu_choice_entry(void *data)
 {
+	struct cli_ch_state s_cch, *cch = &s_cch;
 	struct bootmenu_data *menu = data;
 	struct bootmenu_entry *iter;
 	enum bootmenu_key key = BKEY_NONE;
-	int esc = 0;
 	int i;
 
+	cli_ch_init(cch);
+
 	while (1) {
 		if (menu->delay >= 0) {
 			/* Autoboot was not stopped */
-			key = bootmenu_autoboot_loop(menu, &esc);
+			key = bootmenu_autoboot_loop(menu, cch);
 		} else {
 			/* Some key was pressed, so autoboot was stopped */
-			key = bootmenu_loop(menu, &esc);
+			key = bootmenu_loop(menu, cch);
 		}
 
 		switch (key) {
diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index 18f173e33ab..5922891efc9 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -6,6 +6,7 @@
  */
 
 #include <ansi.h>
+#include <cli.h>
 #include <common.h>
 #include <charset.h>
 #include <efi_loader.h>
@@ -190,14 +191,16 @@ static void eficonfig_display_statusline(struct menu *m)
  */
 static char *eficonfig_choice_entry(void *data)
 {
-	int esc = 0;
+	struct cli_ch_state s_cch, *cch = &s_cch;
 	struct list_head *pos, *n;
 	struct eficonfig_entry *entry;
 	enum bootmenu_key key = BKEY_NONE;
 	struct efimenu *efi_menu = data;
 
+	cli_ch_init(cch);
+
 	while (1) {
-		key = bootmenu_loop((struct bootmenu_data *)efi_menu, &esc);
+		key = bootmenu_loop((struct bootmenu_data *)efi_menu, cch);
 
 		switch (key) {
 		case BKEY_UP:
@@ -1861,14 +1864,15 @@ static void eficonfig_display_change_boot_order(struct efimenu *efi_menu)
  */
 static efi_status_t eficonfig_choice_change_boot_order(struct efimenu *efi_menu)
 {
-	int esc = 0;
+	struct cli_ch_state s_cch, *cch = &s_cch;
 	struct list_head *pos, *n;
 	struct eficonfig_boot_order *tmp;
 	enum bootmenu_key key = BKEY_NONE;
 	struct eficonfig_boot_order *entry;
 
+	cli_ch_init(cch);
 	while (1) {
-		key = bootmenu_loop(NULL, &esc);
+		key = bootmenu_loop(NULL, cch);
 
 		switch (key) {
 		case BKEY_PLUS:
diff --git a/common/cli_getch.c b/common/cli_getch.c
index 9eeea7fef29..87c23edcf4b 100644
--- a/common/cli_getch.c
+++ b/common/cli_getch.c
@@ -140,10 +140,11 @@ int cli_ch_process(struct cli_ch_state *cch, int ichar)
 	 * sequence
 	 */
 	if (!ichar) {
-		if (cch->emit_upto) {
+		if (cch->emitting) {
 			if (cch->emit_upto < cch->esc_len)
 				return cch->esc_save[cch->emit_upto++];
 			cch->emit_upto = 0;
+			cch->emitting = false;
 		}
 		return 0;
 	} else if (ichar == -ETIMEDOUT) {
@@ -174,18 +175,21 @@ int cli_ch_process(struct cli_ch_state *cch, int ichar)
 		case ESC_SAVE:
 			/* save this character and return nothing */
 			cch->esc_save[cch->esc_len++] = ichar;
-			return 0;
+			ichar = 0;
+			break;
 		case ESC_REJECT:
 			/*
 			 * invalid escape sequence, start returning the
 			 * characters in it
 			 */
 			cch->esc_save[cch->esc_len++] = ichar;
-			return cch->esc_save[cch->emit_upto++];
+			ichar = cch->esc_save[cch->emit_upto++];
+			cch->emitting = true;
+			break;
 		case ESC_CONVERTED:
 			/* valid escape sequence, return the resulting char */
 			cch->esc_len = 0;
-			return ichar;
+			break;
 		}
 	}
 
diff --git a/common/menu.c b/common/menu.c
index 7db98942a61..45f36ae3ede 100644
--- a/common/menu.c
+++ b/common/menu.c
@@ -15,6 +15,8 @@
 
 #include "menu.h"
 
+#define ansi 0
+
 /*
  * Internally, each item in a menu is represented by a struct menu_item.
  *
@@ -425,15 +427,19 @@ int menu_destroy(struct menu *m)
 	return 1;
 }
 
-enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu, int *esc)
+enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu,
+					 struct cli_ch_state *cch)
 {
 	enum bootmenu_key key = BKEY_NONE;
 	int i, c;
 
 	while (menu->delay > 0) {
-		printf(ANSI_CURSOR_POSITION, menu->count + 5, 3);
+		if (ansi)
+			printf(ANSI_CURSOR_POSITION, menu->count + 5, 3);
 		printf("Hit any key to stop autoboot: %d ", menu->delay);
 		for (i = 0; i < 100; ++i) {
+			int ichar;
+
 			if (!tstc()) {
 				schedule();
 				mdelay(10);
@@ -443,12 +449,13 @@ enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu, int *esc)
 			menu->delay = -1;
 			c = getchar();
 
-			switch (c) {
-			case '\e':
-				*esc = 1;
+			ichar = cli_ch_process(cch, c);
+
+			switch (ichar) {
+			case '\0':
 				key = BKEY_NONE;
 				break;
-			case '\r':
+			case '\n':
 				key = BKEY_SELECT;
 				break;
 			case 0x3: /* ^C */
@@ -458,7 +465,6 @@ enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu, int *esc)
 				key = BKEY_NONE;
 				break;
 			}
-
 			break;
 		}
 
@@ -468,7 +474,8 @@ enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu, int *esc)
 		--menu->delay;
 	}
 
-	printf(ANSI_CURSOR_POSITION ANSI_CLEAR_LINE, menu->count + 5, 1);
+	if (ansi)
+		printf(ANSI_CURSOR_POSITION ANSI_CLEAR_LINE, menu->count + 5, 1);
 
 	if (menu->delay == 0)
 		key = BKEY_SELECT;
@@ -476,79 +483,32 @@ enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu, int *esc)
 	return key;
 }
 
-enum bootmenu_key bootmenu_loop(struct bootmenu_data *menu, int *esc)
+enum bootmenu_key bootmenu_loop(struct bootmenu_data *menu,
+				struct cli_ch_state *cch)
 {
 	enum bootmenu_key key = BKEY_NONE;
 	int c;
 
-	if (*esc == 1) {
-		if (tstc()) {
-			c = getchar();
-		} else {
+	c = cli_ch_process(cch, 0);
+	if (!c) {
+		while (!c && !tstc()) {
 			schedule();
 			mdelay(10);
-			if (tstc())
-				c = getchar();
-			else
-				c = '\e';
+			c = cli_ch_process(cch, -ETIMEDOUT);
 		}
-	} else {
-		while (!tstc()) {
-			schedule();
-			mdelay(10);
-		}
-		c = getchar();
-	}
-
-	switch (*esc) {
-	case 0:
-		/* First char of ANSI escape sequence '\e' */
-		if (c == '\e') {
-			*esc = 1;
-			key = BKEY_NONE;
-		}
-		break;
-	case 1:
-		/* Second char of ANSI '[' */
-		if (c == '[') {
-			*esc = 2;
-			key = BKEY_NONE;
-		} else {
-		/* Alone ESC key was pressed */
-			key = BKEY_QUIT;
-			*esc = (c == '\e') ? 1 : 0;
-		}
-		break;
-	case 2:
-	case 3:
-		/* Third char of ANSI (number '1') - optional */
-		if (*esc == 2 && c == '1') {
-			*esc = 3;
-			key = BKEY_NONE;
-			break;
+		if (!c) {
+			c = getchar();
+			c = cli_ch_process(cch, c);
 		}
-
-		*esc = 0;
-
-		/* ANSI 'A' - key up was pressed */
-		if (c == 'A')
-			key = BKEY_UP;
-		/* ANSI 'B' - key down was pressed */
-		else if (c == 'B')
-			key = BKEY_DOWN;
-		/* other key was pressed */
-		else
-			key = BKEY_NONE;
-
-		break;
 	}
 
 	switch (c) {
-	case '\r':
+	case '\n':
 		/* enter key was pressed */
 		key = BKEY_SELECT;
 		break;
 	case CTL_CH('c'):
+	case '\e':
 		/* ^C was pressed */
 		key = BKEY_QUIT;
 		break;
diff --git a/include/cli.h b/include/cli.h
index 863519e4b13..c777c90313f 100644
--- a/include/cli.h
+++ b/include/cli.h
@@ -14,12 +14,14 @@
  *
  * @esc_len: Number of escape characters read so far
  * @esc_save: Escape characters collected so far
- * @emit_upto: Next character to emit from esc_save (0 if not emitting)
+ * @emit_upto: Next index to emit from esc_save
+ * @emitting: true if emitting from esc_save
  */
 struct cli_ch_state {
 	int esc_len;
 	char esc_save[8];
 	int emit_upto;
+	bool emitting;
 };
 
 /**
diff --git a/include/menu.h b/include/menu.h
index 8b9b36214f7..3996075a337 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -6,6 +6,7 @@
 #ifndef __MENU_H__
 #define __MENU_H__
 
+struct cli_ch_state;
 struct menu;
 
 struct menu *menu_create(char *title, int timeout, int prompt,
@@ -71,7 +72,8 @@ enum bootmenu_key {
  *	Ctrl-C: KEY_QUIT
  *	anything else: KEY_NONE
  */
-enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu, int *esc);
+enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu,
+					 struct cli_ch_state *cch);
 
 /**
  * bootmenu_loop() - handle waiting for a keypress when autoboot is disabled
@@ -96,6 +98,7 @@ enum bootmenu_key bootmenu_autoboot_loop(struct bootmenu_data *menu, int *esc);
  *	Minus: BKEY_MINUS
  *	Space: BKEY_SPACE
  */
-enum bootmenu_key bootmenu_loop(struct bootmenu_data *menu, int *esc);
+enum bootmenu_key bootmenu_loop(struct bootmenu_data *menu,
+				struct cli_ch_state *cch);
 
 #endif /* __MENU_H__ */
-- 
2.38.1.431.g37b22c650d-goog



More information about the U-Boot mailing list