8 #include <tpl_drv_common.h>
9 #include <tpl_drv_keyboard.h>
13 #define KB_BUFFER_SIZE 1024
14 #define USE_KERNEL_MAGIC 1
17 extern void Threads_ToggleTrace(int TID);
18 extern void Threads_Dump(void);
19 extern void Heap_Stats(void);
22 int KB_Install(char **Arguments);
23 void KB_IRQHandler(int IRQNum);
24 void KB_AddBuffer(char ch);
25 Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest);
26 void KB_UpdateLEDs(void);
27 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data);
30 tDevFS_Driver gKB_DevInfo = {
39 tKeybardCallback gKB_Callback = NULL;
40 Uint32 **gpKB_Map = gpKBDUS;
41 Uint8 gbaKB_States[3][256];
42 int gbKB_ShiftState = 0;
43 int gbKB_CapsState = 0;
45 int giKB_KeyLayer = 0;
47 int gbKB_MagicState = 0;
48 int giKB_MagicAddress = 0;
49 int giKB_MagicAddressPos = 0;
54 * \brief Install the keyboard driver
56 int KB_Install(char **Arguments)
60 // Attempt to get around a strange bug in Bochs/Qemu by toggling
61 // the controller on and off
63 outb(0x61, temp | 0x80);
64 outb(0x61, temp & 0x7F);
65 inb(0x60); // Clear keyboard buffer
67 IRQ_AddHandler(1, KB_IRQHandler);
68 DevFS_AddDevice( &gKB_DevInfo );
69 //Log("KB_Install: Installed");
74 * \brief Called on a keyboard IRQ
75 * \param IRQNum IRQ number (unused)
77 void KB_IRQHandler(int IRQNum)
83 // Check port 0x64 to tell if this is from the aux port
84 //if( inb(0x64) & 0x20 ) return;
86 scancode = inb(0x60); // Read from the keyboard's data buffer
87 //Log_Debug("Keyboard", "scancode = %02x", scancode);
90 if(scancode == 0xFA) {
91 // Oh man! This is anarchic (I'm leaving it here to represent
92 // the mess that Acess once was)
93 //kb_lastChar = KB_ACK;
98 if(scancode == 0xE0) {
103 if(scancode == 0xE1) {
123 ch = gpKB_Map[giKB_KeyLayer][scancode];
124 // Check for unknown key
125 if(!ch && !gbKB_KeyUp)
126 Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode);
132 gbaKB_States[giKB_KeyLayer][scancode] = 0; // Unset key state flag
135 if(ch == KEY_LCTRL) gbKB_MagicState &= ~1;
136 if(ch == KEY_LALT) gbKB_MagicState &= ~2;
139 if(ch == KEY_LSHIFT) gbKB_ShiftState &= ~1;
140 if(ch == KEY_RSHIFT) gbKB_ShiftState &= ~2;
143 if(ch != 0 && gKB_Callback)
144 gKB_Callback( ch & 0x80000000 );
151 // Set the bit relating to the key
152 gbaKB_States[giKB_KeyLayer][scancode] = 1;
153 // Set shift key bits
154 if(ch == KEY_LSHIFT) gbKB_ShiftState |= 1;
155 if(ch == KEY_RSHIFT) gbKB_ShiftState |= 2;
157 // Check for Caps Lock
158 if(ch == KEY_CAPSLOCK) {
159 gbKB_CapsState = !gbKB_CapsState;
166 // Ignore Non-Printable Characters
169 // --- Check for Kernel Magic Combos
171 if(ch == KEY_LCTRL) {
172 gbKB_MagicState |= 1;
173 //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n");
176 gbKB_MagicState |= 2;
177 //Log_Log("Keyboard", "Kernel Magic LALT Down\n");
179 if(gbKB_MagicState == 3)
183 case '0': case '1': case '2': case '3':
184 case '4': case '5': case '6': case '7':
185 case '8': case '9': case 'a': case 'b':
186 case 'c': case 'd': case 'e': case 'f':
188 char str[4] = {'0', 'x', ch, 0};
189 if(giKB_MagicAddressPos == BITS/4) return;
190 giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos;
191 giKB_MagicAddressPos ++;
195 // Instruction Tracing
197 Log("Toggle instruction tracing on %i\n", giKB_MagicAddress);
198 Threads_ToggleTrace( giKB_MagicAddress );
199 giKB_MagicAddress = 0; giKB_MagicAddressPos = 0;
203 case 'p': Threads_Dump(); return;
205 case 'h': Heap_Stats(); return;
212 // Capitals required?
213 if( (gbKB_ShiftState != 0) != (gbKB_CapsState != 0))
215 // TODO: Move this to the keyboard map header
219 case '`': ch = '~'; break;
220 case '1': ch = '!'; break;
221 case '2': ch = '@'; break;
222 case '3': ch = '#'; break;
223 case '4': ch = '$'; break;
224 case '5': ch = '%'; break;
225 case '6': ch = '^'; break;
226 case '7': ch = '&'; break;
227 case '8': ch = '*'; break;
228 case '9': ch = '('; break;
229 case '0': ch = ')'; break;
230 case '-': ch = '_'; break;
231 case '=': ch = '+'; break;
232 case '[': ch = '{'; break;
233 case ']': ch = '}'; break;
234 case '\\': ch = '|'; break;
235 case ';': ch = ':'; break;
236 case '\'': ch = '"'; break;
237 case ',': ch = '<'; break;
238 case '.': ch = '>'; break;
239 case '/': ch = '?'; break;
241 if('a' <= ch && ch <= 'z')
247 if(gKB_Callback && ch != 0) gKB_Callback(ch);
251 * \fn void KB_UpdateLEDs(void)
252 * \brief Updates the status of the keyboard LEDs
254 void KB_UpdateLEDs(void)
258 leds = (gbKB_CapsState ? 4 : 0);
260 while( inb(0x64) & 2 ); // Wait for bit 2 to unset
261 outb(0x60, 0xED); // Send update command
263 while( inb(0x64) & 2 ); // Wait for bit 2 to unset
268 * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
269 * \brief Calls an IOCtl Command
271 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
275 case DRV_IOCTL_TYPE: return DRV_TYPE_KEYBOARD;
276 case DRV_IOCTL_IDENT: memcpy(Data, "KB\0\0", 4); return 1;
277 case DRV_IOCTL_VERSION: return 0x100;
278 case DRV_IOCTL_LOOKUP: return 0;
280 // Sets the Keyboard Callback
281 case KB_IOCTL_SETCALLBACK:
283 if((Uint)Data < KERNEL_BASE) return 0;
284 // Can only be set once
285 if(gKB_Callback != NULL) return 0;