8 #include <tpl_drv_common.h>
9 #include <tpl_drv_keyboard.h>
13 #define KB_BUFFER_SIZE 1024
19 int KB_Install(char **Arguments);
21 void KB_AddBuffer(char ch);
22 Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest);
24 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data);
27 MODULE_DEFINE(0, 0x0100, PS2Keyboard, KB_Install, NULL, NULL);
28 tDevFS_Driver gKB_DevInfo = {
37 tKeybardCallback gKB_Callback = NULL;
38 Uint32 **gpKB_Map = gpKBDUS;
39 Uint8 gbaKB_States[3][256];
40 int gbKB_ShiftState = 0;
41 int gbKB_CapsState = 0;
43 int giKB_KeyLayer = 0;
45 int gbKB_MagicState = 0;
47 //Uint64 giKB_ReadBase = 0;
48 //Uint32 gaKB_Buffer[KB_BUFFER_SIZE]; //!< Keyboard Ring Buffer
49 //volatile int giKB_InsertPoint = 0; //!< Writing location marker
50 //volatile int giKB_ReadPoint = 0; //!< Reading location marker
51 //volatile int giKB_InUse = 0; //!< Lock marker
55 * \fn int KB_Install(char **Arguments)
57 int KB_Install(char **Arguments)
61 // Attempt to get around a strange bug in Bochs/Qemu by toggling
62 // the controller on and off
64 outb(0x61, temp | 0x80);
65 outb(0x61, temp & 0x7F);
67 IRQ_AddHandler(1, KB_IRQHandler);
68 DevFS_AddDevice( &gKB_DevInfo );
69 //Log("KB_Install: Installed");
74 * \fn void KB_IRQHandler()
75 * \brief Called on a keyboard IRQ
83 //if( inportb(0x64) & 0x20 ) return;
85 scancode = inb(0x60); // Read from the keyboard's data buffer
87 //Log("KB_IRQHandler: scancode = 0x%02x", scancode);
90 if(scancode == 0xFA) {
91 // Oh man! This is anachic (I'm leaving it here to represent the
92 // 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 //keyNum = giKB_KeyLayer * 256 + scancode;
125 // Check for unknown key
126 if(!ch && !gbKB_KeyUp)
127 Warning("UNK %i %x", giKB_KeyLayer, scancode);
133 gbaKB_States[giKB_KeyLayer][scancode] = 0; // Unset key state flag
136 if(ch == KEY_LCTRL) gbKB_MagicState &= ~1;
137 if(ch == KEY_LALT) gbKB_MagicState &= ~2;
140 if(ch == KEY_LSHIFT) gbKB_ShiftState &= ~1;
141 if(ch == KEY_RSHIFT) gbKB_ShiftState &= ~2;
144 if(ch != 0 && gKB_Callback)
145 gKB_Callback( ch & 0x80000000 );
152 // Set the bit relating to the key
153 gbaKB_States[giKB_KeyLayer][scancode] = 1;
154 // Set shift key bits
155 if(ch == KEY_LSHIFT) gbKB_ShiftState |= 1;
156 if(ch == KEY_RSHIFT) gbKB_ShiftState |= 2;
158 // Check for Caps Lock
159 if(ch == KEY_CAPSLOCK) {
160 gbKB_CapsState = !gbKB_CapsState;
167 // Ignore Non-Printable Characters
170 // --- Check for Kernel Magic Combos
172 if(ch == KEY_LCTRL) gbKB_MagicState |= 1;
173 if(ch == KEY_LALT) gbKB_MagicState |= 2;
174 if(gbKB_MagicState == 3)
178 case 'd': __asm__ __volatile__ ("xchg %bx, %bx"); break;
179 case 'p': Threads_Dump(); break;
185 // - Darn ugly hacks !(!x) means (bool)x
186 if( !(!gbKB_ShiftState) ^ gbKB_CapsState)
191 case '`': ch = '~'; break;
192 case '1': ch = '!'; break;
193 case '2': ch = '@'; break;
194 case '3': ch = '#'; break;
195 case '4': ch = '$'; break;
196 case '5': ch = '%'; break;
197 case '6': ch = '^'; break;
198 case '7': ch = '&'; break;
199 case '8': ch = '*'; break;
200 case '9': ch = '('; break;
201 case '0': ch = ')'; break;
202 case '-': ch = '_'; break;
203 case '=': ch = '+'; break;
204 case '[': ch = '{'; break;
205 case ']': ch = '}'; break;
206 case '\\': ch = '|'; break;
207 case ';': ch = ':'; break;
208 case '\'': ch = '"'; break;
209 case ',': ch = '<'; break;
210 case '.': ch = '>'; break;
211 case '/': ch = '?'; break;
213 if('a' <= ch && ch <= 'z')
219 if(gKB_Callback && ch != 0) gKB_Callback(ch);
223 * \fn void KB_UpdateLEDs()
224 * \brief Updates the status of the keyboard LEDs
230 leds = (gbKB_CapsState ? 4 : 0);
232 while( inb(0x64) & 2 ); // Wait for bit 2 to unset
233 outb(0x60, 0xED); // Send update command
235 while( inb(0x64) & 2 ); // Wait for bit 2 to unset
240 * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
241 * \brief Calls an IOCtl Command
243 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
247 case DRV_IOCTL_TYPE: return DRV_TYPE_KEYBOARD;
248 case DRV_IOCTL_IDENT: memcpy(Data, "KB\0\0", 4); return 1;
249 case DRV_IOCTL_VERSION: return 0x100;
250 case DRV_IOCTL_LOOKUP: return 0;
252 // Sets the Keyboard Callback
253 case KB_IOCTL_SETCALLBACK:
255 if((Uint)Data < KERNEL_BASE) return 0;
256 // Can only be set once
257 if(gKB_Callback != NULL) return 0;