X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FModules%2FInput%2FPS2KbMouse%2Fkb.c;fp=KernelLand%2FModules%2FInput%2FPS2KbMouse%2Fkb.c;h=a121b611c027c840d60e0598f04ec9d33b45390e;hb=51ab5f489bc356940c95cc936fd0508e8f07ea97;hp=0000000000000000000000000000000000000000;hpb=c43646fe791455ca711ed79167c4b7fbd4346669;p=tpg%2Facess2.git diff --git a/KernelLand/Modules/Input/PS2KbMouse/kb.c b/KernelLand/Modules/Input/PS2KbMouse/kb.c new file mode 100644 index 00000000..a121b611 --- /dev/null +++ b/KernelLand/Modules/Input/PS2KbMouse/kb.c @@ -0,0 +1,251 @@ +/* + * Acess2 + * PS2 Keyboard Driver + */ +#include +#include +#include +#include +#include +#include "kb_kbdus.h" + +// === CONSTANTS === +#define KB_BUFFER_SIZE 1024 +#define USE_KERNEL_MAGIC 1 + +// === IMPORTS === +extern void Threads_ToggleTrace(int TID); +extern void Threads_Dump(void); +extern void Heap_Stats(void); + +// === PROTOTYPES === + int KB_Install(char **Arguments); +void KB_HandleScancode(Uint8 scancode); +void KB_UpdateLEDs(void); + int KB_IOCtl(tVFS_Node *Node, int Id, void *Data); + +// === GLOBALS === +tVFS_NodeType gKB_NodeType = { + .IOCtl = KB_IOCtl +}; +tDevFS_Driver gKB_DevInfo = { + NULL, "PS2Keyboard", + { .Type = &gKB_NodeType } +}; +tKeybardCallback gKB_Callback = NULL; +Uint32 **gpKB_Map = gpKBDUS; +Uint8 gbaKB_States[3][256]; + int gbKB_ShiftState = 0; + int gbKB_CapsState = 0; + int gbKB_KeyUp = 0; + int giKB_KeyLayer = 0; +#if USE_KERNEL_MAGIC + int gbKB_MagicState = 0; + int giKB_MagicAddress = 0; + int giKB_MagicAddressPos = 0; +#endif + +// === CODE === +/** + * \brief Install the keyboard driver + */ +int KB_Install(char **Arguments) +{ + DevFS_AddDevice( &gKB_DevInfo ); + //Log("KB_Install: Installed"); + return MODULE_ERR_OK; +} + +/** + * \brief Called on a keyboard IRQ + * \param IRQNum IRQ number (unused) + */ +void KB_HandleScancode(Uint8 scancode) +{ + Uint32 ch; + int bCaseSwitch = (gbKB_ShiftState != 0) != (gbKB_CapsState != 0); + + //Log_Debug("Keyboard", "scancode = %02x", scancode); + + // Ignore ACKs + if(scancode == 0xFA) { + // Oh man! This is anarchic (I'm leaving it here to represent + // the mess that Acess once was) + //kb_lastChar = KB_ACK; + return; + } + + // Layer +1 + if(scancode == 0xE0) { + giKB_KeyLayer = 1; + return; + } + // Layer +2 + if(scancode == 0xE1) { + giKB_KeyLayer = 2; + return; + } + + #if KB_ALT_SCANCODES + if(scancode == 0xF0) + { + gbKB_KeyUp = 1; + return; + } + #else + if(scancode & 0x80) + { + scancode &= 0x7F; + gbKB_KeyUp = 1; + } + #endif + + if( gKB_Callback ) + gKB_Callback( (giKB_KeyLayer << 8) | scancode | KEY_ACTION_RAWSYM ); + + // Translate + ch = gpKB_Map[giKB_KeyLayer*2+bCaseSwitch][scancode]; + // - Unknown characters in the shift layer fall through to lower + if(bCaseSwitch && ch == 0) + ch = gpKB_Map[giKB_KeyLayer*2][scancode]; + // Check for unknown key + if(!ch) + { + if(!gbKB_KeyUp) + Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode); +// return ; + // Can pass through to ensure each raw message has a up/down with it + } + + // Key Up? + if (gbKB_KeyUp) + { + gbKB_KeyUp = 0; + gbaKB_States[giKB_KeyLayer][scancode] = 0; // Unset key state flag + + #if USE_KERNEL_MAGIC + if(ch == KEY_LCTRL) gbKB_MagicState &= ~1; + if(ch == KEY_LALT) gbKB_MagicState &= ~2; + #endif + + if(ch == KEY_LSHIFT) gbKB_ShiftState &= ~1; + if(ch == KEY_RSHIFT) gbKB_ShiftState &= ~2; + + // Call callback + if(gKB_Callback) gKB_Callback( ch | KEY_ACTION_RELEASE ); + + // Reset Layer + giKB_KeyLayer = 0; + return; + } + + // Refire? + if( gbaKB_States[giKB_KeyLayer][scancode] == 1 ) + { + if(gKB_Callback) gKB_Callback(ch | KEY_ACTION_REFIRE); + giKB_KeyLayer = 0; + return ; + } + + // Set the bit relating to the key + gbaKB_States[giKB_KeyLayer][scancode] = 1; + // Set shift key bits + if(ch == KEY_LSHIFT) gbKB_ShiftState |= 1; + if(ch == KEY_RSHIFT) gbKB_ShiftState |= 2; + + // Check for Caps Lock + if(ch == KEY_CAPSLOCK) { + gbKB_CapsState = !gbKB_CapsState; + KB_UpdateLEDs(); + } + + // --- Check for Kernel Magic Combos + #if USE_KERNEL_MAGIC + if(ch == KEY_LCTRL) { + gbKB_MagicState |= 1; + //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n"); + } + if(ch == KEY_LALT) { + gbKB_MagicState |= 2; + //Log_Log("Keyboard", "Kernel Magic LALT Down\n"); + } + if(gbKB_MagicState == 3) + { + switch(ch) + { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': case 'a': case 'b': + case 'c': case 'd': case 'e': case 'f': + { + char str[4] = {'0', 'x', ch, 0}; + if(giKB_MagicAddressPos == BITS/4) return; + giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos; + giKB_MagicAddressPos ++; + } + return; + + // Instruction Tracing + case 't': + Log("Toggle instruction tracing on %i\n", giKB_MagicAddress); + Threads_ToggleTrace( giKB_MagicAddress ); + giKB_MagicAddress = 0; giKB_MagicAddressPos = 0; + return; + + // Thread List Dump + case 'p': Threads_Dump(); return; + // Heap Statistics + case 'h': Heap_Stats(); return; + // Dump Structure + case 's': return; + } + } + #endif + + if(gKB_Callback) + gKB_Callback(ch | KEY_ACTION_PRESS); + + // Reset Layer + giKB_KeyLayer = 0; +} + +/** + * \fn void KB_UpdateLEDs(void) + * \brief Updates the status of the keyboard LEDs + */ +void KB_UpdateLEDs(void) +{ + Uint8 leds; + + leds = (gbKB_CapsState ? 4 : 0); + + // TODO: Update LEDS + Log_Warning("Keyboard", "TODO: Update LEDs"); +} + +static const char *csaIOCTL_NAMES[] = {DRV_IOCTLNAMES, DRV_KEYBAORD_IOCTLNAMES, NULL}; + +/** + * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data) + * \brief Calls an IOCtl Command + */ +int KB_IOCtl(tVFS_Node *Node, int Id, void *Data) +{ + switch(Id) + { + BASE_IOCTLS(DRV_TYPE_KEYBOARD, "KB", 0x100, csaIOCTL_NAMES); + + // Sets the Keyboard Callback + case KB_IOCTL_SETCALLBACK: + // Sanity Check + if((Uint)Data < KERNEL_BASE) return 0; + // Can only be set once + if(gKB_Callback != NULL) return 0; + // Set Callback + gKB_Callback = Data; + return 1; + + default: + return 0; + } +}