1 // SPDX-License-Identifier: GPL-2.0+
4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
6 * Copyright 2022 Google LLC
13 * enum cli_esc_state_t - indicates what to do with an escape character
15 * @ESC_REJECT: Invalid escape sequence, so the esc_save[] characters are
16 * returned from each subsequent call to cli_ch_esc()
17 * @ESC_SAVE: Character should be saved in esc_save until we have another one
18 * @ESC_CONVERTED: Escape sequence has been completed and the resulting
19 * character is available
21 enum cli_esc_state_t {
27 void cli_ch_init(struct cli_ch_state *cch)
29 memset(cch, '\0', sizeof(*cch));
33 * cli_ch_esc() - Process a character in an ongoing escape sequence
35 * @cch: State information
36 * @ichar: Character to process
37 * @actp: Returns the action to take
38 * Returns: Output character if *actp is ESC_CONVERTED, else 0
40 static int cli_ch_esc(struct cli_ch_state *cch, int ichar,
41 enum cli_esc_state_t *actp)
43 enum cli_esc_state_t act = ESC_REJECT;
45 switch (cch->esc_len) {
47 if (ichar == '[' || ichar == 'O')
52 case 'D': /* <- key */
55 break; /* pass off to ^B handler */
56 case 'C': /* -> key */
59 break; /* pass off to ^F handler */
60 case 'H': /* Home key */
63 break; /* pass off to ^A handler */
64 case 'F': /* End key */
67 break; /* pass off to ^E handler */
68 case 'A': /* up arrow */
71 break; /* pass off to ^P handler */
72 case 'B': /* down arrow */
75 break; /* pass off to ^N handler */
82 if (cch->esc_save[1] == '[') {
83 /* see if next character is ~ */
92 switch (cch->esc_save[2]) {
93 case '3': /* Delete key */
96 break; /* pass to ^D handler */
97 case '1': /* Home key */
101 break; /* pass to ^A handler */
102 case '4': /* End key */
106 break; /* pass to ^E handler */
110 if (cch->esc_save[2] == '2')
120 break; /* bracketed paste */
124 if (ichar == '~') { /* bracketed paste */
132 return act == ESC_CONVERTED ? ichar : 0;
135 int cli_ch_process(struct cli_ch_state *cch, int ichar)
138 * ichar=0x0 when error occurs in U-Boot getchar() or when the caller
139 * wants to check if there are more characters saved in the escape
144 if (cch->emit_upto < cch->esc_len)
145 return cch->esc_save[cch->emit_upto++];
147 cch->emitting = false;
150 } else if (ichar == -ETIMEDOUT) {
152 * If we are in an escape sequence but nothing has followed the
153 * Escape character, then the user probably just pressed the
154 * Escape key. Return it and clear the sequence.
161 /* Otherwise there is nothing to return */
165 if (ichar == '\n' || ichar == '\r')
168 /* handle standard linux xterm esc sequences for arrow key, etc. */
169 if (cch->esc_len != 0) {
170 enum cli_esc_state_t act;
172 ichar = cli_ch_esc(cch, ichar, &act);
176 /* save this character and return nothing */
177 cch->esc_save[cch->esc_len++] = ichar;
182 * invalid escape sequence, start returning the
185 cch->esc_save[cch->esc_len++] = ichar;
186 ichar = cch->esc_save[cch->emit_upto++];
187 cch->emitting = true;
190 /* valid escape sequence, return the resulting char */
198 cch->esc_save[cch->esc_len] = ichar;
201 puts("impossible condition #876\n");