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 void Threads_Dump(void);
18 void Heap_Stats(void);
21 int KB_Install(char **Arguments);
22 void KB_IRQHandler(int IRQNum);
23 void KB_AddBuffer(char ch);
24 Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest);
25 void KB_UpdateLEDs(void);
26 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data);
29 MODULE_DEFINE(0, 0x0100, PS2Keyboard, KB_Install, NULL, NULL);
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;
49 //Uint64 giKB_ReadBase = 0;
50 //Uint32 gaKB_Buffer[KB_BUFFER_SIZE]; //!< Keyboard Ring Buffer
51 //volatile int giKB_InsertPoint = 0; //!< Writing location marker
52 //volatile int giKB_ReadPoint = 0; //!< Reading location marker
53 //volatile int giKB_InUse = 0; //!< Lock marker
57 * \fn int KB_Install(char **Arguments)
59 int KB_Install(char **Arguments)
63 // Attempt to get around a strange bug in Bochs/Qemu by toggling
64 // the controller on and off
66 outb(0x61, temp | 0x80);
67 outb(0x61, temp & 0x7F);
68 inb(0x60); // Clear keyboard buffer
70 IRQ_AddHandler(1, KB_IRQHandler);
71 DevFS_AddDevice( &gKB_DevInfo );
72 //Log("KB_Install: Installed");
77 * \fn void KB_IRQHandler()
78 * \brief Called on a keyboard IRQ
80 void KB_IRQHandler(int IRQNum)
86 // Check port 0x64 to tell if this is from the aux port
87 //if( inb(0x64) & 0x20 ) return;
89 scancode = inb(0x60); // Read from the keyboard's data buffer
90 //Log_Debug("Keyboard", "scancode = %02x", scancode);
93 if(scancode == 0xFA) {
94 // Oh man! This is anarchic (I'm leaving it here to represent
95 // the mess that Acess once was)
96 //kb_lastChar = KB_ACK;
101 if(scancode == 0xE0) {
106 if(scancode == 0xE1) {
126 ch = gpKB_Map[giKB_KeyLayer][scancode];
127 //keyNum = giKB_KeyLayer * 256 + scancode;
128 // Check for unknown key
129 if(!ch && !gbKB_KeyUp)
130 Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode);
136 gbaKB_States[giKB_KeyLayer][scancode] = 0; // Unset key state flag
139 if(ch == KEY_LCTRL) gbKB_MagicState &= ~1;
140 if(ch == KEY_LALT) gbKB_MagicState &= ~2;
143 if(ch == KEY_LSHIFT) gbKB_ShiftState &= ~1;
144 if(ch == KEY_RSHIFT) gbKB_ShiftState &= ~2;
147 if(ch != 0 && gKB_Callback)
148 gKB_Callback( ch & 0x80000000 );
155 // Set the bit relating to the key
156 gbaKB_States[giKB_KeyLayer][scancode] = 1;
157 // Set shift key bits
158 if(ch == KEY_LSHIFT) gbKB_ShiftState |= 1;
159 if(ch == KEY_RSHIFT) gbKB_ShiftState |= 2;
161 // Check for Caps Lock
162 if(ch == KEY_CAPSLOCK) {
163 gbKB_CapsState = !gbKB_CapsState;
170 // Ignore Non-Printable Characters
173 // --- Check for Kernel Magic Combos
175 if(ch == KEY_LCTRL) {
176 gbKB_MagicState |= 1;
177 //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n");
180 gbKB_MagicState |= 2;
181 //Log_Log("Keyboard", "Kernel Magic LALT Down\n");
183 if(gbKB_MagicState == 3)
187 // Kernel Panic (Page Fault)
188 case 'q': *((int*)1) = 0; return;
189 // Bochs Magic Breakpoint
190 case 'd': __asm__ __volatile__ ("xchg %bx, %bx"); return;
192 case 'p': Threads_Dump(); return;
194 case 'h': Heap_Stats(); return;
200 // - Darn ugly hacks !!x means (bool)x
201 if( !!gbKB_ShiftState ^ gbKB_CapsState)
206 case '`': ch = '~'; break;
207 case '1': ch = '!'; break;
208 case '2': ch = '@'; break;
209 case '3': ch = '#'; break;
210 case '4': ch = '$'; break;
211 case '5': ch = '%'; break;
212 case '6': ch = '^'; break;
213 case '7': ch = '&'; break;
214 case '8': ch = '*'; break;
215 case '9': ch = '('; break;
216 case '0': ch = ')'; break;
217 case '-': ch = '_'; break;
218 case '=': ch = '+'; break;
219 case '[': ch = '{'; break;
220 case ']': ch = '}'; break;
221 case '\\': ch = '|'; break;
222 case ';': ch = ':'; break;
223 case '\'': ch = '"'; break;
224 case ',': ch = '<'; break;
225 case '.': ch = '>'; break;
226 case '/': ch = '?'; break;
228 if('a' <= ch && ch <= 'z')
234 if(gKB_Callback && ch != 0) gKB_Callback(ch);
238 * \fn void KB_UpdateLEDs(void)
239 * \brief Updates the status of the keyboard LEDs
241 void KB_UpdateLEDs(void)
245 leds = (gbKB_CapsState ? 4 : 0);
247 while( inb(0x64) & 2 ); // Wait for bit 2 to unset
248 outb(0x60, 0xED); // Send update command
250 while( inb(0x64) & 2 ); // Wait for bit 2 to unset
255 * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
256 * \brief Calls an IOCtl Command
258 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
262 case DRV_IOCTL_TYPE: return DRV_TYPE_KEYBOARD;
263 case DRV_IOCTL_IDENT: memcpy(Data, "KB\0\0", 4); return 1;
264 case DRV_IOCTL_VERSION: return 0x100;
265 case DRV_IOCTL_LOOKUP: return 0;
267 // Sets the Keyboard Callback
268 case KB_IOCTL_SETCALLBACK:
270 if((Uint)Data < KERNEL_BASE) return 0;
271 // Can only be set once
272 if(gKB_Callback != NULL) return 0;