1 // SPDX-License-Identifier: GPL-2.0+
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')
54 case 'D': /* <- key */
57 break; /* pass off to ^B handler */
58 case 'C': /* -> key */
61 break; /* pass off to ^F handler */
62 case 'H': /* Home key */
65 break; /* pass off to ^A handler */
66 case 'F': /* End key */
69 break; /* pass off to ^E handler */
70 case 'A': /* up arrow */
73 break; /* pass off to ^P handler */
74 case 'B': /* down arrow */
77 break; /* pass off to ^N handler */
84 if (cch->esc_save[1] == '[') {
85 /* see if next character is ~ */
94 switch (cch->esc_save[2]) {
95 case '3': /* Delete key */
98 break; /* pass to ^D handler */
99 case '1': /* Home key */
103 break; /* pass to ^A handler */
104 case '4': /* End key */
108 break; /* pass to ^E handler */
112 if (cch->esc_save[2] == '2')
122 break; /* bracketed paste */
126 if (ichar == '~') { /* bracketed paste */
137 int cli_ch_process(struct cli_ch_state *cch, int ichar)
140 * ichar=0x0 when error occurs in U-Boot getchar() or when the caller
141 * wants to check if there are more characters saved in the escape
146 if (cch->emit_upto < cch->esc_len)
147 return cch->esc_save[cch->emit_upto++];
149 cch->emitting = false;
153 } else if (ichar == -ETIMEDOUT) {
155 * If we are in an escape sequence but nothing has followed the
156 * Escape character, then the user probably just pressed the
157 * Escape key. Return it and clear the sequence.
164 /* Otherwise there is nothing to return */
168 if (ichar == '\n' || ichar == '\r')
171 /* handle standard linux xterm esc sequences for arrow key, etc. */
172 if (cch->esc_len != 0) {
173 enum cli_esc_state_t act;
175 ichar = cli_ch_esc(cch, ichar, &act);
179 /* save this character and return nothing */
180 cch->esc_save[cch->esc_len++] = ichar;
185 * invalid escape sequence, start returning the
188 cch->esc_save[cch->esc_len++] = ichar;
189 ichar = cch->esc_save[cch->emit_upto++];
190 cch->emitting = true;
193 /* valid escape sequence, return the resulting char */
201 cch->esc_save[cch->esc_len] = ichar;
204 puts("impossible condition #876\n");