Kernel - Removed old KEY_* enum
[tpg/acess2.git] / KernelLand / Kernel / drv / vterm_input.c
1 /*
2  * Acess2 Kernel
3  * - By John Hodge (thePowersGang)
4  *
5  * drv/vterm_input.c
6  * - Virtual Terminal - Input code
7  */
8 #include "vterm.h"
9 #include <api_drv_keyboard.h>
10 #define DEBUG   1
11
12 // === GLOBALS ===
13 // --- Key States --- (Used for VT Switching/Magic Combos)
14  int    gbVT_CtrlDown = 0;
15  int    gbVT_AltDown = 0;
16  int    gbVT_SysrqDown = 0;
17
18 // === CODE ===
19 /**
20  * \fn void VT_InitInput()
21  * \brief Initialises the input
22  */
23 void VT_InitInput()
24 {
25         giVT_InputDevHandle = VFS_Open(gsVT_InputDevice, VFS_OPENFLAG_READ);
26         if(giVT_InputDevHandle == -1) {
27                 Log_Warning("VTerm", "Can't open the input device '%s'", gsVT_InputDevice);
28                 return ;
29         }
30         VFS_IOCtl(giVT_InputDevHandle, KB_IOCTL_SETCALLBACK, VT_KBCallBack);
31         LOG("VTerm input initialised");
32 }
33
34 /**
35  * \fn void VT_KBCallBack(Uint32 Codepoint)
36  * \brief Called on keyboard interrupt
37  * \param Codepoint     Pseudo-UTF32 character
38  * 
39  * Handles a key press and sends the key code to the user's buffer.
40  * If the code creates a kernel-magic sequence, it is not passed to the
41  * user and is handled in-kernel.
42  */
43 void VT_KBCallBack(Uint32 Codepoint)
44 {
45         tVTerm  *term = gpVT_CurTerm;
46
47         // Catch VT binds
48         switch( Codepoint & KEY_ACTION_MASK )
49         {
50         case KEY_ACTION_RAWSYM:
51                 term->RawScancode = Codepoint & KEY_CODEPOINT_MASK;
52                 break;
53         case KEY_ACTION_RELEASE:
54                 switch(term->RawScancode)
55                 {
56                 case KEYSYM_LEFTALT:    gbVT_AltDown &= ~1;     break;
57                 case KEYSYM_RIGHTALT:   gbVT_AltDown &= ~2;     break;
58                 case KEYSYM_LEFTCTRL:   gbVT_CtrlDown &= ~1;    break;
59                 case KEYSYM_RIGHTCTRL:  gbVT_CtrlDown &= ~2;    break;
60                 }
61                 break;
62         
63         case KEY_ACTION_PRESS:
64                 switch(term->RawScancode)
65                 {
66                 case KEYSYM_LEFTALT:    gbVT_AltDown |= 1;      break;
67                 case KEYSYM_RIGHTALT:   gbVT_AltDown |= 2;      break;
68                 case KEYSYM_LEFTCTRL:   gbVT_CtrlDown |= 1;     break;
69                 case KEYSYM_RIGHTCTRL:  gbVT_CtrlDown |= 2;     break;
70                 }
71                 
72                 // Check if the magic keys are held
73                 if(!gbVT_AltDown || !gbVT_CtrlDown)
74                         break;
75                 
76                 switch(term->RawScancode)
77                 {
78                 case KEYSYM_F1 :        VT_SetTerminal(0);      return;
79                 case KEYSYM_F2 :        VT_SetTerminal(1);      return;
80                 case KEYSYM_F3 :        VT_SetTerminal(2);      return;
81                 case KEYSYM_F4 :        VT_SetTerminal(3);      return;
82                 case KEYSYM_F5 :        VT_SetTerminal(4);      return;
83                 case KEYSYM_F6 :        VT_SetTerminal(5);      return;
84                 case KEYSYM_F7 :        VT_SetTerminal(6);      return;
85                 case KEYSYM_F8 :        VT_SetTerminal(7);      return;
86                 case KEYSYM_F9 :        VT_SetTerminal(8);      return;
87                 case KEYSYM_F10:        VT_SetTerminal(9);      return;
88                 case KEYSYM_F11:        VT_SetTerminal(10);     return;
89                 case KEYSYM_F12:        VT_SetTerminal(11);     return;
90                 }
91                 
92                 // Scrolling is only valid in text mode
93                 if(term->Mode != TERM_MODE_TEXT)
94                         break;
95                 
96 //              Log_Debug("VTerm", "Magic Ctrl-Alt-0x%x", term->RawScancode);   
97
98                 switch(term->RawScancode)
99                 {
100                 // Scrolling
101                 case KEYSYM_PGUP:
102                         if( term->Flags & VT_FLAG_ALTBUF )
103                                 return ;
104                         term->ViewPos = MAX( 0, term->ViewPos - term->Width );
105                         VT_int_UpdateScreen(term, 1);
106                         return;
107                 case KEYSYM_PGDN:
108                         if( term->Flags & VT_FLAG_ALTBUF )
109                                 return ;
110                         term->ViewPos = MIN(
111                                 term->ViewPos + term->Width,
112                                 term->Width * term->Height * giVT_Scrollback
113                                 );
114                         VT_int_UpdateScreen(term, 1);
115                         return;
116                 }
117                 break;
118         }
119         
120         // Encode key
121         if(term->Mode == TERM_MODE_TEXT)
122         {
123                 Uint8   buf[6] = {0};
124                  int    len = 0;
125         
126                 // Ignore anything that isn't a press or refire
127                 if( (Codepoint & KEY_ACTION_MASK) != KEY_ACTION_PRESS
128                  && (Codepoint & KEY_ACTION_MASK) != KEY_ACTION_REFIRE
129                     )
130                 {
131                         return ;
132                 }
133         
134                 Codepoint &= KEY_CODEPOINT_MASK;
135
136                 // Get UTF-8/ANSI Encoding
137                 if( Codepoint == 0 )
138                 {
139                         // Non-printable keys
140                         switch(term->RawScancode)
141                         {
142                         case KEYSYM_LEFTARROW:
143                         case KEYSYM_KP4:
144                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'D';
145                                 len = 3;
146                                 break;
147                         case KEYSYM_RIGHTARROW:
148                         case KEYSYM_KP6:
149                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'C';
150                                 len = 3;
151                                 break;
152                         case KEYSYM_UPARROW:
153                         case KEYSYM_KP8:
154                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'A';
155                                 len = 3;
156                                 break;
157                         case KEYSYM_DOWNARROW:
158                         case KEYSYM_KP2:
159                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'B';
160                                 len = 3;
161                                 break;
162                         
163                         case KEYSYM_PGUP:
164                         case KEYSYM_KP9:        // If Codepoint=0, It's page up
165                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '5'; buf[3] = '~';
166                                 len = 4;
167                                 break;
168                         case KEYSYM_PGDN:
169                         case KEYSYM_KP3:        // If Codepoint=0, It's page down
170                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '6'; buf[3] = '~';
171                                 len = 4;
172                                 break;
173                         
174                         case KEYSYM_HOME:
175                         case KEYSYM_KP7:        // Codepoint==0, then it's home (not translated)
176                                 buf[0] = '\x1B'; buf[1] = 'O'; buf[2] = 'H';
177                                 len = 3;
178                                 break;
179                         case KEYSYM_END:
180                         case KEYSYM_KP1:        // You get the drill
181                                 buf[0] = '\x1B'; buf[1] = 'O'; buf[2] = 'F';
182                                 len = 3;
183                                 break;
184                         
185                         case KEYSYM_INSERT:
186                         case KEYSYM_KP0:        // See above
187                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '2'; buf[3] = '~';
188                                 len = 4;
189                                 break;
190                         case KEYSYM_DELETE:
191                         case KEYSYM_KPPERIOD:   // Are you that dumb? Look up
192                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '3'; buf[3] = '~';
193                                 len = 4;
194                                 break;
195                         }
196                 }
197                 else if( gbVT_CtrlDown )
198                 {
199                         len = 1;
200                         switch( term->RawScancode )
201                         {
202                         case KEYSYM_2:
203                                 buf[0] = '\0';
204                                 break;
205                         case KEYSYM_3 ... KEYSYM_7:
206                                 buf[0] = 0x1b + (term->RawScancode - KEYSYM_3);
207                                 break;
208                         case KEYSYM_8:
209                                 buf[0] = 0x7f;
210                                 break;
211                         // - Ctrl-A = \1, Ctrl-Z = \x1a
212                         case KEYSYM_a ... KEYSYM_z:
213                                 buf[0] = 0x01 + (term->RawScancode - KEYSYM_a);
214                                 break;
215                         default:
216                                 goto utf_encode;
217                         }
218                 }
219                 else
220                 {
221                 utf_encode:
222                         // Attempt to encode in UTF-8
223                         len = WriteUTF8( buf, Codepoint );
224                         if(len == 0) {
225                                 Warning("Codepoint (%x) is unrepresentable in UTF-8", Codepoint);
226                         }
227                 }
228                 
229                 if(len == 0) {
230                         // Unprintable / Don't Pass
231                         return;
232                 }
233
234                 // TODO: Implement Ctrl-C etc
235 #if 0
236                 // Handle meta characters
237                 if( !(term->Flags & VT_FLAG_RAWIN) )
238                 {
239                         // Implementation options for Ctrl-C -> SIGINT
240                         // - Kernel-land: here in the VT
241                         //  > Pros: No userland change needed
242                         //  > Cons: Requires process groups
243                         // - User-land, in the shell
244                         //  > Pros: Less threading changes
245                         //  > Cons: Needs the shell to get all user input before the app, worse latency
246                         //  >       Won't work with bash etc
247                         switch(buf[0])
248                         {
249                         case '\3':      // ^C
250                                 
251                                 break;
252                         }
253                 }
254 #endif
255                 
256                 // Write
257                 if( MAX_INPUT_CHARS8 - term->InputWrite >= len ) {
258                         memcpy( &term->InputBuffer[term->InputWrite], buf, len );
259                 }
260                 else {
261                         memcpy( &term->InputBuffer[term->InputWrite], buf, MAX_INPUT_CHARS8 - term->InputWrite );
262                         memcpy( &term->InputBuffer[0], buf, len - (MAX_INPUT_CHARS8 - term->InputWrite) );
263                 }
264                 // Roll the buffer over
265                 term->InputWrite += len;
266                 term->InputWrite %= MAX_INPUT_CHARS8;
267                 if( (term->InputWrite - term->InputRead + MAX_INPUT_CHARS8)%MAX_INPUT_CHARS8 < len ) {
268                         term->InputRead = term->InputWrite + 1;
269                         term->InputRead %= MAX_INPUT_CHARS8;
270                 }
271         }
272         else
273         {
274                 // Encode the raw key event
275                 Uint32  *raw_in = (void*)term->InputBuffer;
276         
277                 #if 0
278                 // Drop new keys
279                 if( term->InputWrite == term->InputRead )
280                         return ;                
281                 #endif
282
283                 raw_in[ term->InputWrite ] = Codepoint;
284                 term->InputWrite ++;
285                 if(term->InputWrite >= MAX_INPUT_CHARS32)
286                         term->InputWrite -= MAX_INPUT_CHARS32;
287                 
288                 #if 1
289                 // TODO: Should old or new be dropped?
290                 if(term->InputRead == term->InputWrite) {
291                         term->InputRead ++;
292                         if( term->InputRead >= MAX_INPUT_CHARS32 )
293                                 term->InputRead -= MAX_INPUT_CHARS32;
294                 }
295                 #endif
296         }
297         
298         VFS_MarkAvaliable(&term->Node, 1);
299 }
300

UCC git Repository :: git.ucc.asn.au