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, PS2Keybard, KB_Install, NULL, NULL);
28 tDevFS_Driver gKB_DevInfo = {
37 tKeybardCallback gKB_Callback = NULL;
38 Uint8 **gpKB_Map = gpKBDUS;
39 Uint8 gbaKB_States[256];
40 int gbKB_ShiftState = 0;
41 int gbKB_CapsState = 0;
43 int giKB_KeyLayer = 0;
44 //Uint64 giKB_ReadBase = 0;
45 Uint8 gaKB_Buffer[KB_BUFFER_SIZE]; //!< Keyboard Ring Buffer
46 volatile int giKB_InsertPoint = 0; //!< Writing location marker
47 volatile int giKB_ReadPoint = 0; //!< Reading location marker
48 volatile int giKB_InUse = 0; //!< Lock marker
52 * \fn int KB_Install(char **Arguments)
54 int KB_Install(char **Arguments)
56 IRQ_AddHandler(1, KB_IRQHandler);
57 DevFS_AddDevice( &gKB_DevInfo );
62 * \fn void KB_IRQHandler()
63 * \brief Called on a keyboard IRQ
71 //if( inportb(0x64) & 0x20 ) return;
73 scancode = inb(0x60); // Read from the keyboard's data buffer
76 if(scancode == 0xFA) {
77 //kb_lastChar = KB_ACK;
82 if(scancode == 0xE0) {
87 if(scancode == 0xE1) {
107 ch = gpKB_Map[giKB_KeyLayer][scancode];
108 keyNum = giKB_KeyLayer * 256 + scancode;
109 // Check for unknown key
110 if(!ch && !gbKB_KeyUp)
111 Warning("UNK %i %x", giKB_KeyLayer, scancode);
114 Log("keyNum = %i\n", keyNum);
123 gbaKB_States[ keyNum ] = 0; // Unset key state flag
125 if( !gbaKB_States[KEY_LSHIFT] && !gbaKB_States[KEY_RSHIFT] )
128 KB_AddBuffer(KEY_KEYUP);
134 // Set the bit relating to the key
135 gbaKB_States[keyNum] = 1;
136 if(ch == KEY_LSHIFT || ch == KEY_RSHIFT)
139 // Check for Caps Lock
140 if(ch == KEY_CAPSLOCK) {
141 gbKB_CapsState = !gbKB_CapsState;
145 // Ignore Non-Printable Characters
146 if(ch == 0 || ch & 0x80) return;
148 // --- Check for Kernel Magic Combos
149 if(gbaKB_States[KEY_LCTRL])// && gbaKB_States[KEY_LALT])
151 LOG("ch = 0x%02x", ch);
154 case 'd': __asm__ __volatile__ ("xchg %bx, %bx"); break;
155 case 'p': Threads_Dump(); break;
160 if(gbKB_ShiftState ^ gbKB_CapsState)
164 case '`': ch = '~'; break;
165 case '1': ch = '!'; break;
166 case '2': ch = '@'; break;
167 case '3': ch = '#'; break;
168 case '4': ch = '$'; break;
169 case '5': ch = '%'; break;
170 case '6': ch = '^'; break;
171 case '7': ch = '&'; break;
172 case '8': ch = '*'; break;
173 case '9': ch = '('; break;
174 case '0': ch = ')'; break;
175 case '-': ch = '_'; break;
176 case '=': ch = '+'; break;
177 case '[': ch = '{'; break;
178 case ']': ch = '}'; break;
179 case '\\': ch = '|'; break;
180 case ';': ch = ':'; break;
181 case '\'': ch = '"'; break;
182 case ',': ch = '<'; break;
183 case '.': ch = '>'; break;
184 case '/': ch = '?'; break;
186 if('a' <= ch && ch <= 'z')
192 if(gKB_Callback) gKB_Callback(ch);
196 * \fn void KB_AddBuffer(char ch)
197 * \brief Add to the keyboard ring buffer
199 void KB_AddBuffer(char ch)
202 gaKB_Buffer[ giKB_InsertPoint++ ] = ch;
204 if( giKB_InsertPoint == KB_BUFFER_SIZE ) giKB_InsertPoint = 0;
205 // - Force increment read pointer
206 if( giKB_InsertPoint == giKB_ReadPoint ) giKB_ReadPoint ++;
210 * \fn Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest)
211 * \brief Read from the ring buffer
213 * \param Offset Unused (Character Device)
214 * \param Length Number of bytes to read
215 * \param Dest Destination
217 Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest)
222 if(giKB_InUse) return -1;
225 while(giKB_ReadPoint != giKB_InsertPoint && pos < Length)
227 dstbuf[pos++] = gaKB_Buffer[ giKB_ReadPoint++ ];
228 if( giKB_ReadPoint == KB_BUFFER_SIZE ) giKB_InsertPoint = 0;
237 * \fn void KB_UpdateLEDs()
238 * \brief Updates the status of the keyboard LEDs
244 leds = (gbKB_CapsState ? 4 : 0);
246 while( inb(0x64) & 2 ); // Wait for bit 2 to unset
247 outb(0x60, 0xED); // Send update command
249 while( inb(0x64) & 2 ); // Wait for bit 2 to unset
254 * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
255 * \brief Calls an IOCtl Command
257 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
261 case DRV_IOCTL_TYPE: return DRV_TYPE_KEYBOARD;
262 case DRV_IOCTL_IDENT: memcpy(Data, "KB\0\0", 4); return 1;
263 case DRV_IOCTL_VERSION: return 0x100;
264 case DRV_IOCTL_LOOKUP: return 0;
266 // Sets the Keyboard Callback
267 case KB_IOCTL_SETCALLBACK:
269 if((Uint)Data < KERNEL_BASE) return 0;
270 // Can only be set once
271 if(gKB_Callback != NULL) return 0;