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 tVFS_NodeType gKB_NodeType = {
31 tDevFS_Driver gKB_DevInfo = {
33 { .Type = &gKB_NodeType }
35 tKeybardCallback gKB_Callback = NULL;
36 Uint32 **gpKB_Map = gpKBDUS;
37 Uint8 gbaKB_States[3][256];
38 int gbKB_ShiftState = 0;
39 int gbKB_CapsState = 0;
41 int giKB_KeyLayer = 0;
43 int gbKB_MagicState = 0;
44 int giKB_MagicAddress = 0;
45 int giKB_MagicAddressPos = 0;
50 * \brief Install the keyboard driver
52 int KB_Install(char **Arguments)
54 DevFS_AddDevice( &gKB_DevInfo );
55 //Log("KB_Install: Installed");
60 * \brief Called on a keyboard IRQ
61 * \param IRQNum IRQ number (unused)
63 void KB_HandleScancode(Uint8 scancode)
66 int bCaseSwitch = (gbKB_ShiftState != 0) != (gbKB_CapsState != 0);
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 gKB_Callback( (giKB_KeyLayer << 8) | scancode | KEY_ACTION_RAWSYM );
107 ch = gpKB_Map[giKB_KeyLayer*2+bCaseSwitch][scancode];
108 // - Unknown characters in the shift layer fall through to lower
109 if(bCaseSwitch && ch == 0)
110 ch = gpKB_Map[giKB_KeyLayer*2][scancode];
111 // Check for unknown key
115 Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode);
117 // Can pass through to ensure each raw message has a up/down with it
124 gbaKB_States[giKB_KeyLayer][scancode] = 0; // Unset key state flag
127 if(ch == KEY_LCTRL) gbKB_MagicState &= ~1;
128 if(ch == KEY_LALT) gbKB_MagicState &= ~2;
131 if(ch == KEY_LSHIFT) gbKB_ShiftState &= ~1;
132 if(ch == KEY_RSHIFT) gbKB_ShiftState &= ~2;
135 if(gKB_Callback) gKB_Callback( ch | KEY_ACTION_RELEASE );
143 if( gbaKB_States[giKB_KeyLayer][scancode] == 1 )
145 if(gKB_Callback) gKB_Callback(ch | KEY_ACTION_REFIRE);
150 // Set the bit relating to the key
151 gbaKB_States[giKB_KeyLayer][scancode] = 1;
152 // Set shift key bits
153 if(ch == KEY_LSHIFT) gbKB_ShiftState |= 1;
154 if(ch == KEY_RSHIFT) gbKB_ShiftState |= 2;
156 // Check for Caps Lock
157 if(ch == KEY_CAPSLOCK) {
158 gbKB_CapsState = !gbKB_CapsState;
162 // --- Check for Kernel Magic Combos
164 if(ch == KEY_LCTRL) {
165 gbKB_MagicState |= 1;
166 //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n");
169 gbKB_MagicState |= 2;
170 //Log_Log("Keyboard", "Kernel Magic LALT Down\n");
172 if(gbKB_MagicState == 3)
176 case '0': case '1': case '2': case '3':
177 case '4': case '5': case '6': case '7':
178 case '8': case '9': case 'a': case 'b':
179 case 'c': case 'd': case 'e': case 'f':
181 char str[4] = {'0', 'x', ch, 0};
182 if(giKB_MagicAddressPos == BITS/4) return;
183 giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos;
184 giKB_MagicAddressPos ++;
188 // Instruction Tracing
190 Log("Toggle instruction tracing on %i\n", giKB_MagicAddress);
191 Threads_ToggleTrace( giKB_MagicAddress );
192 giKB_MagicAddress = 0; giKB_MagicAddressPos = 0;
196 case 'p': Threads_Dump(); return;
198 case 'h': Heap_Stats(); return;
206 gKB_Callback(ch | KEY_ACTION_PRESS);
213 * \fn void KB_UpdateLEDs(void)
214 * \brief Updates the status of the keyboard LEDs
216 void KB_UpdateLEDs(void)
220 leds = (gbKB_CapsState ? 4 : 0);
223 Log_Warning("Keyboard", "TODO: Update LEDs");
226 static const char *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_KEYBAORD_IOCTLNAMES, NULL};
229 * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
230 * \brief Calls an IOCtl Command
232 int KB_IOCtl(tVFS_Node *Node, int Id, void *Data)
236 BASE_IOCTLS(DRV_TYPE_KEYBOARD, "KB", 0x100, csaIOCTL_NAMES);
238 // Sets the Keyboard Callback
239 case KB_IOCTL_SETCALLBACK:
241 if((Uint)Data < KERNEL_BASE) return 0;
242 // Can only be set once
243 if(gKB_Callback != NULL) return 0;