8 #include <api_drv_common.h>
9 #include <api_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_HandleScancode(Uint8 scancode);
24 void KB_UpdateLEDs(void);
25 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data);
28 tDevFS_Driver gKB_DevInfo = {
36 tKeybardCallback gKB_Callback = NULL;
37 Uint32 **gpKB_Map = gpKBDUS;
38 Uint8 gbaKB_States[3][256];
39 int gbKB_ShiftState = 0;
40 int gbKB_CapsState = 0;
42 int giKB_KeyLayer = 0;
44 int gbKB_MagicState = 0;
45 int giKB_MagicAddress = 0;
46 int giKB_MagicAddressPos = 0;
51 * \brief Install the keyboard driver
53 int KB_Install(char **Arguments)
55 DevFS_AddDevice( &gKB_DevInfo );
56 //Log("KB_Install: Installed");
61 * \brief Called on a keyboard IRQ
62 * \param IRQNum IRQ number (unused)
64 void KB_HandleScancode(Uint8 scancode)
68 //Log_Debug("Keyboard", "scancode = %02x", scancode);
71 if(scancode == 0xFA) {
72 // Oh man! This is anarchic (I'm leaving it here to represent
73 // the mess that Acess once was)
74 //kb_lastChar = KB_ACK;
79 if(scancode == 0xE0) {
84 if(scancode == 0xE1) {
104 ch = gpKB_Map[giKB_KeyLayer][scancode];
105 // Check for unknown key
106 if(!ch && !gbKB_KeyUp)
107 Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode);
113 gbaKB_States[giKB_KeyLayer][scancode] = 0; // Unset key state flag
116 if(ch == KEY_LCTRL) gbKB_MagicState &= ~1;
117 if(ch == KEY_LALT) gbKB_MagicState &= ~2;
120 if(ch == KEY_LSHIFT) gbKB_ShiftState &= ~1;
121 if(ch == KEY_RSHIFT) gbKB_ShiftState &= ~2;
124 if(ch != 0 && gKB_Callback)
125 gKB_Callback( ch & 0x80000000 );
132 // Set the bit relating to the key
133 gbaKB_States[giKB_KeyLayer][scancode] = 1;
134 // Set shift key bits
135 if(ch == KEY_LSHIFT) gbKB_ShiftState |= 1;
136 if(ch == KEY_RSHIFT) gbKB_ShiftState |= 2;
138 // Check for Caps Lock
139 if(ch == KEY_CAPSLOCK) {
140 gbKB_CapsState = !gbKB_CapsState;
147 // Ignore Non-Printable Characters
150 // --- Check for Kernel Magic Combos
152 if(ch == KEY_LCTRL) {
153 gbKB_MagicState |= 1;
154 //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n");
157 gbKB_MagicState |= 2;
158 //Log_Log("Keyboard", "Kernel Magic LALT Down\n");
160 if(gbKB_MagicState == 3)
164 case '0': case '1': case '2': case '3':
165 case '4': case '5': case '6': case '7':
166 case '8': case '9': case 'a': case 'b':
167 case 'c': case 'd': case 'e': case 'f':
169 char str[4] = {'0', 'x', ch, 0};
170 if(giKB_MagicAddressPos == BITS/4) return;
171 giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos;
172 giKB_MagicAddressPos ++;
176 // Instruction Tracing
178 Log("Toggle instruction tracing on %i\n", giKB_MagicAddress);
179 Threads_ToggleTrace( giKB_MagicAddress );
180 giKB_MagicAddress = 0; giKB_MagicAddressPos = 0;
184 case 'p': Threads_Dump(); return;
186 case 'h': Heap_Stats(); return;
193 // Capitals required?
194 if( (gbKB_ShiftState != 0) != (gbKB_CapsState != 0))
196 // TODO: Move this to the keyboard map header
200 case '`': ch = '~'; break;
201 case '1': ch = '!'; break;
202 case '2': ch = '@'; break;
203 case '3': ch = '#'; break;
204 case '4': ch = '$'; break;
205 case '5': ch = '%'; break;
206 case '6': ch = '^'; break;
207 case '7': ch = '&'; break;
208 case '8': ch = '*'; break;
209 case '9': ch = '('; break;
210 case '0': ch = ')'; break;
211 case '-': ch = '_'; break;
212 case '=': ch = '+'; break;
213 case '[': ch = '{'; break;
214 case ']': ch = '}'; break;
215 case '\\': ch = '|'; break;
216 case ';': ch = ':'; break;
217 case '\'': ch = '"'; break;
218 case ',': ch = '<'; break;
219 case '.': ch = '>'; break;
220 case '/': ch = '?'; break;
222 if('a' <= ch && ch <= 'z')
228 if(gKB_Callback && ch != 0) gKB_Callback(ch);
232 * \fn void KB_UpdateLEDs(void)
233 * \brief Updates the status of the keyboard LEDs
235 void KB_UpdateLEDs(void)
239 leds = (gbKB_CapsState ? 4 : 0);
242 Log_Warning("Keyboard", "TODO: Update LEDs");
245 static const char *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_KEYBAORD_IOCTLNAMES, NULL};
248 * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
249 * \brief Calls an IOCtl Command
251 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
255 BASE_IOCTLS(DRV_TYPE_KEYBOARD, "KB", 0x100, csaIOCTL_NAMES);
257 // Sets the Keyboard Callback
258 case KB_IOCTL_SETCALLBACK:
260 if((Uint)Data < KERNEL_BASE) return 0;
261 // Can only be set once
262 if(gKB_Callback != NULL) return 0;