]> Git Repo - J-u-boot.git/blob - common/cli_getch.c
rockchip: rk3399-gru: Include pinctrl and regulators in SPL
[J-u-boot.git] / common / cli_getch.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2000
4  * Wolfgang Denk, DENX Software Engineering, [email protected].
5  *
6  * Copyright 2022 Google LLC
7  */
8
9 #include <cli.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <linux/errno.h>
13
14 /**
15  * enum cli_esc_state_t - indicates what to do with an escape character
16  *
17  * @ESC_REJECT: Invalid escape sequence, so the esc_save[] characters are
18  *      returned from each subsequent call to cli_ch_esc()
19  * @ESC_SAVE: Character should be saved in esc_save until we have another one
20  * @ESC_CONVERTED: Escape sequence has been completed and the resulting
21  *      character is available
22  */
23 enum cli_esc_state_t {
24         ESC_REJECT,
25         ESC_SAVE,
26         ESC_CONVERTED
27 };
28
29 void cli_ch_init(struct cli_ch_state *cch)
30 {
31         memset(cch, '\0', sizeof(*cch));
32 }
33
34 /**
35  * cli_ch_esc() - Process a character in an ongoing escape sequence
36  *
37  * @cch: State information
38  * @ichar: Character to process
39  * @actp: Returns the action to take
40  * Returns: Output character if *actp is ESC_CONVERTED, else 0
41  */
42 static int cli_ch_esc(struct cli_ch_state *cch, int ichar,
43                       enum cli_esc_state_t *actp)
44 {
45         enum cli_esc_state_t act = ESC_REJECT;
46
47         switch (cch->esc_len) {
48         case 1:
49                 if (ichar == '[' || ichar == 'O')
50                         act = ESC_SAVE;
51                 else
52                         act = ESC_CONVERTED;
53                 break;
54         case 2:
55                 switch (ichar) {
56                 case 'D':       /* <- key */
57                         ichar = CTL_CH('b');
58                         act = ESC_CONVERTED;
59                         break;  /* pass off to ^B handler */
60                 case 'C':       /* -> key */
61                         ichar = CTL_CH('f');
62                         act = ESC_CONVERTED;
63                         break;  /* pass off to ^F handler */
64                 case 'H':       /* Home key */
65                         ichar = CTL_CH('a');
66                         act = ESC_CONVERTED;
67                         break;  /* pass off to ^A handler */
68                 case 'F':       /* End key */
69                         ichar = CTL_CH('e');
70                         act = ESC_CONVERTED;
71                         break;  /* pass off to ^E handler */
72                 case 'A':       /* up arrow */
73                         ichar = CTL_CH('p');
74                         act = ESC_CONVERTED;
75                         break;  /* pass off to ^P handler */
76                 case 'B':       /* down arrow */
77                         ichar = CTL_CH('n');
78                         act = ESC_CONVERTED;
79                         break;  /* pass off to ^N handler */
80                 case '1':
81                 case '2':
82                 case '3':
83                 case '4':
84                 case '7':
85                 case '8':
86                         if (cch->esc_save[1] == '[') {
87                                 /* see if next character is ~ */
88                                 act = ESC_SAVE;
89                         }
90                         break;
91                 }
92                 break;
93         case 3:
94                 switch (ichar) {
95                 case '~':
96                         switch (cch->esc_save[2]) {
97                         case '3':       /* Delete key */
98                                 ichar = CTL_CH('d');
99                                 act = ESC_CONVERTED;
100                                 break;  /* pass to ^D handler */
101                         case '1':       /* Home key */
102                         case '7':
103                                 ichar = CTL_CH('a');
104                                 act = ESC_CONVERTED;
105                                 break;  /* pass to ^A handler */
106                         case '4':       /* End key */
107                         case '8':
108                                 ichar = CTL_CH('e');
109                                 act = ESC_CONVERTED;
110                                 break;  /* pass to ^E handler */
111                         }
112                         break;
113                 case '0':
114                         if (cch->esc_save[2] == '2')
115                                 act = ESC_SAVE;
116                         break;
117                 }
118                 break;
119         case 4:
120                 switch (ichar) {
121                 case '0':
122                 case '1':
123                         act = ESC_SAVE;
124                         break;          /* bracketed paste */
125                 }
126                 break;
127         case 5:
128                 if (ichar == '~') {     /* bracketed paste */
129                         ichar = 0;
130                         act = ESC_CONVERTED;
131                 }
132         }
133
134         *actp = act;
135
136         return ichar;
137 }
138
139 int cli_ch_process(struct cli_ch_state *cch, int ichar)
140 {
141         /*
142          * ichar=0x0 when error occurs in U-Boot getchar() or when the caller
143          * wants to check if there are more characters saved in the escape
144          * sequence
145          */
146         if (!ichar) {
147                 if (cch->emitting) {
148                         if (cch->emit_upto < cch->esc_len)
149                                 return cch->esc_save[cch->emit_upto++];
150                         cch->emit_upto = 0;
151                         cch->emitting = false;
152                         cch->esc_len = 0;
153                 }
154                 return 0;
155         } else if (ichar == -ETIMEDOUT) {
156                 /*
157                  * If we are in an escape sequence but nothing has followed the
158                  * Escape character, then the user probably just pressed the
159                  * Escape key. Return it and clear the sequence.
160                  */
161                 if (cch->esc_len) {
162                         cch->esc_len = 0;
163                         return '\e';
164                 }
165
166                 /* Otherwise there is nothing to return */
167                 return 0;
168         }
169
170         if (ichar == '\n' || ichar == '\r')
171                 return '\n';
172
173         /* handle standard linux xterm esc sequences for arrow key, etc. */
174         if (cch->esc_len != 0) {
175                 enum cli_esc_state_t act;
176
177                 ichar = cli_ch_esc(cch, ichar, &act);
178
179                 switch (act) {
180                 case ESC_SAVE:
181                         /* save this character and return nothing */
182                         cch->esc_save[cch->esc_len++] = ichar;
183                         ichar = 0;
184                         break;
185                 case ESC_REJECT:
186                         /*
187                          * invalid escape sequence, start returning the
188                          * characters in it
189                          */
190                         cch->esc_save[cch->esc_len++] = ichar;
191                         ichar = cch->esc_save[cch->emit_upto++];
192                         cch->emitting = true;
193                         return ichar;
194                 case ESC_CONVERTED:
195                         /* valid escape sequence, return the resulting char */
196                         cch->esc_len = 0;
197                         break;
198                 }
199         }
200
201         if (ichar == '\e') {
202                 if (!cch->esc_len) {
203                         cch->esc_save[cch->esc_len] = ichar;
204                         cch->esc_len = 1;
205                 } else {
206                         puts("impossible condition #876\n");
207                         cch->esc_len = 0;
208                 }
209                 return 0;
210         }
211
212         return ichar;
213 }
This page took 0.037141 seconds and 4 git commands to generate.