3 * - By John Hodge (thePowersGang)
6 * - Virtual Terminal - Input code
9 #include <api_drv_keyboard.h>
12 // --- Key States --- (Used for VT Switching/Magic Combos)
13 int gbVT_CtrlDown = 0;
15 int gbVT_SysrqDown = 0;
19 * \fn void VT_InitInput()
20 * \brief Initialises the input
24 giVT_InputDevHandle = VFS_Open(gsVT_InputDevice, VFS_OPENFLAG_READ);
25 if(giVT_InputDevHandle == -1) {
26 Log_Warning("VTerm", "Can't open the input device '%s'", gsVT_InputDevice);
29 VFS_IOCtl(giVT_InputDevHandle, KB_IOCTL_SETCALLBACK, VT_KBCallBack);
33 * \fn void VT_KBCallBack(Uint32 Codepoint)
34 * \brief Called on keyboard interrupt
35 * \param Codepoint Pseudo-UTF32 character
37 * Handles a key press and sends the key code to the user's buffer.
38 * If the code creates a kernel-magic sequence, it is not passed to the
39 * user and is handled in-kernel.
41 void VT_KBCallBack(Uint32 Codepoint)
43 tVTerm *term = gpVT_CurTerm;
46 switch( Codepoint & KEY_ACTION_MASK )
48 case KEY_ACTION_RAWSYM:
49 term->RawScancode = Codepoint & KEY_CODEPOINT_MASK;
51 case KEY_ACTION_RELEASE:
52 switch(term->RawScancode)
54 case KEYSYM_LEFTALT: gbVT_AltDown &= ~1; break;
55 case KEYSYM_RIGHTALT: gbVT_AltDown &= ~2; break;
56 case KEYSYM_LEFTCTRL: gbVT_CtrlDown &= ~1; break;
57 case KEYSYM_RIGHTCTRL: gbVT_CtrlDown &= ~2; break;
61 case KEY_ACTION_PRESS:
62 switch(term->RawScancode)
64 case KEYSYM_LEFTALT: gbVT_AltDown |= 1; break;
65 case KEYSYM_RIGHTALT: gbVT_AltDown |= 2; break;
66 case KEYSYM_LEFTCTRL: gbVT_CtrlDown |= 1; break;
67 case KEYSYM_RIGHTCTRL: gbVT_CtrlDown |= 2; break;
70 // Check if the magic keys are held
71 if(!gbVT_AltDown || !gbVT_CtrlDown)
74 switch(term->RawScancode)
76 case KEYSYM_F1 : VT_SetTerminal(0); return;
77 case KEYSYM_F2 : VT_SetTerminal(1); return;
78 case KEYSYM_F3 : VT_SetTerminal(2); return;
79 case KEYSYM_F4 : VT_SetTerminal(3); return;
80 case KEYSYM_F5 : VT_SetTerminal(4); return;
81 case KEYSYM_F6 : VT_SetTerminal(5); return;
82 case KEYSYM_F7 : VT_SetTerminal(6); return;
83 case KEYSYM_F8 : VT_SetTerminal(7); return;
84 case KEYSYM_F9 : VT_SetTerminal(8); return;
85 case KEYSYM_F10: VT_SetTerminal(9); return;
86 case KEYSYM_F11: VT_SetTerminal(10); return;
87 case KEYSYM_F12: VT_SetTerminal(11); return;
90 // Scrolling is only valid in text mode
91 if(term->Mode != TERM_MODE_TEXT)
94 switch(term->RawScancode)
98 if( term->Flags & VT_FLAG_ALTBUF )
100 term->ViewPos = MAX( 0, term->ViewPos - term->Width );
103 if( term->Flags & VT_FLAG_ALTBUF )
106 term->ViewPos + term->Width,
107 term->Width * term->Height * giVT_Scrollback
115 if(term->Mode == TERM_MODE_TEXT)
120 // Ignore anything that isn't a press or refire
121 if( (Codepoint & KEY_ACTION_MASK) != KEY_ACTION_PRESS
122 && (Codepoint & KEY_ACTION_MASK) != KEY_ACTION_REFIRE
128 Codepoint &= KEY_CODEPOINT_MASK;
130 // Ignore Modifer Keys
131 if(Codepoint > KEY_MODIFIERS) return;
133 // Get UTF-8/ANSI Encoding
136 // Non-printable keys
137 switch(term->RawScancode)
139 case KEYSYM_LEFTARROW:
141 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'D';
144 case KEYSYM_RIGHTARROW:
146 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'C';
151 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'A';
154 case KEYSYM_DOWNARROW:
156 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'B';
161 case KEYSYM_KP9: // If Codepoint=0, It's page up
162 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '5'; buf[3] = '~';
166 case KEYSYM_KP3: // If Codepoint=0, It's page down
167 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '6'; buf[3] = '~';
173 buf[0] = '\x1B'; buf[1] = 'O'; buf[2] = 'H';
178 buf[0] = '\x1B'; buf[1] = 'O'; buf[2] = 'F';
184 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '2'; buf[3] = '~';
188 case KEYSYM_KPPERIOD:
189 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '3'; buf[3] = '~';
196 // Attempt to encode in UTF-8
197 len = WriteUTF8( buf, Codepoint );
199 Warning("Codepoint (%x) is unrepresentable in UTF-8", Codepoint);
204 // Unprintable / Don't Pass
208 // TODO: Implement Ctrl-C etc
210 // Handle meta characters
211 if( !(term->Flags & VT_FLAG_RAWIN) )
223 if( MAX_INPUT_CHARS8 - term->InputWrite >= len )
224 memcpy( &term->InputBuffer[term->InputWrite], buf, len );
226 memcpy( &term->InputBuffer[term->InputWrite], buf, MAX_INPUT_CHARS8 - term->InputWrite );
227 memcpy( &term->InputBuffer[0], buf, len - (MAX_INPUT_CHARS8 - term->InputWrite) );
229 // Roll the buffer over
230 term->InputWrite += len;
231 term->InputWrite %= MAX_INPUT_CHARS8;
232 if( (term->InputWrite - term->InputRead + MAX_INPUT_CHARS8)%MAX_INPUT_CHARS8 < len ) {
233 term->InputRead = term->InputWrite + 1;
234 term->InputRead %= MAX_INPUT_CHARS8;
239 // Encode the raw key event
240 Uint32 *raw_in = (void*)term->InputBuffer;
244 if( term->InputWrite == term->InputRead )
248 raw_in[ term->InputWrite ] = Codepoint;
250 if(term->InputWrite >= MAX_INPUT_CHARS32)
251 term->InputWrite -= MAX_INPUT_CHARS32;
254 // TODO: Should old or new be dropped?
255 if(term->InputRead == term->InputWrite) {
257 if( term->InputRead >= MAX_INPUT_CHARS32 )
258 term->InputRead -= MAX_INPUT_CHARS32;
263 VFS_MarkAvaliable(&term->Node, 1);