#include "Kbd.ns.h"
#include <DeviceManager/Dev.ns.h>
#include <Vector.class.h>
#include <Devices/Keyboard/Keyboard.proto.h>
#include <VTManager/VirtualTerminal.proto.h>
#include <Ressources/Keymaps/Keymap.h>
#include <VFS/File.class.h>
#include <Core/Log.ns.h>
namespace Kbd {
//These are arbitrarily decided codes given to each scancode
u8int ctrlkeys[] = {
/* 0x00 */ 0, KBDC_ESCAPE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KBDC_BACKSPACE, KBDC_TAB,
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KBDC_ENTER, KBDC_LEFTCTRL, 0, 0,
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KBDC_LEFTSHIFT, 0, 0, 0, 0, 0,
/* 0x30 */ 0, 0, 0, 0, 0, 0, KBDC_RIGHTSHIFT, 0, KBDC_ALT, 0, KBDC_CAPSLOCK, KBDC_F1, KBDC_F2, KBDC_F3, KBDC_F4, KBDC_F5,
/* 0x40 */ KBDC_F6, KBDC_F7, KBDC_F8, KBDC_F9, KBDC_F10, KBDC_NUMLOCK, KBDC_SCRLLOCK, KBDC_KPHOME, KBDC_KPUP, KBDC_KPPGUP, 0, KBDC_KPLEFT, KBDC_KP5, KBDC_KPRIGHT, 0, KBDC_KPEND,
/* 0x50 */ KBDC_KPDOWN, KBDC_KPPGDOWN, KBDC_KPINSERT, KBDC_KPDEL, KBDC_SYSREQ, 0, 0, KBDC_F11, KBDC_F12, 0, 0, 0, 0, 0, 0, 0,
/* 0x60 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x90 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KBDC_ENTER, KBDC_RIGHTCTRL, 0, 0,
/* 0xA0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xB0 */ 0, 0, 0, 0, 0, KBDC_KPSLASH, 0, KBDC_PRTSCN, KBDC_ALTGR, 0, 0, 0, 0, 0, 0, 0,
/* 0xC0 */ 0, 0, 0, 0, 0, 0, 0, KBDC_HOME, KBDC_UP, KBDC_PGUP, 0, KBDC_LEFT, 0, KBDC_RIGHT, 0, KBDC_END,
/* 0xD0 */ KBDC_DOWN, KBDC_PGDOWN, KBDC_INSERT, KBDC_DEL, 0, 0, 0, 0, 0, 0, 0, KBDC_LEFTSUP, KBDC_RIGHTSUP, KBDC_MENU, 0, 0,
/* 0xE0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0xF0 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
melon_keymap_t km;
WChar *keymapNormal = NULL, *keymapShift = NULL, *keymapCaps = NULL, *keymapAltgr = NULL, *keymapShiftAltgr = NULL;
u8int kbdstatus = 0;
VirtualTerminal *focusedVT = NULL; //This is the VT that must receive the character
void process(keypress_t kp) { //This routine sends the information of a keypress to someone
/* String r("Key press ");
String n = String::number(kp.pressed);
r += n;
r += ", hascmd=";
n = String::number(kp.hascmd);
r += n;
r += ", cmd=";
n = String::number(kp.command);
r += n;
r += ", haschar=";
n = String::number(kp.haschar);
r += n;
r += ", char='";
r += kp.character;
r += "'";
DEBUG(r); */
if (focusedVT != NULL) {
if (((kp.haschar and kp.character != 0) or (kp.hascmd and kp.command < 100)) and kp.pressed) {
focusedVT->keyPress(kp);
}
}
}
void setFocus(VirtualTerminal* vt) {
focusedVT = vt;
}
bool loadKeymap(String lang) {
String file = "/System/Keymaps/";
file += lang;
file += ".mkm";
File f(file, FM_READ);
if (!f.valid()) return false;
if (!f.read<melon_keymap_t> (&km)) {
Log::log(KL_WARNING, String("Kbd.ns : keymap badly loaded : ") += file);
}
keymapNormal = km.normal;
if (km.shift[0x10] != 0) keymapShift = km.shift; else keymapShift = keymapNormal;
if (km.caps[0x10] != 0) keymapCaps = km.caps; else keymapShift = keymapShift;
if (km.altgr[0x10] != 0) keymapAltgr = km.altgr; else keymapShift = keymapNormal;
if (km.shiftaltgr[0x10] != 0) keymapShiftAltgr = km.shiftaltgr; else keymapShift = keymapAltgr;
Log::log(KL_STATUS, String("Kbd.ns : loaded keymap : ") += file);
return true;
}
void updateLeds() {
Vector<Device*> kbds = Dev::findDevices("keyboard");
for (u32int i = 0; i < kbds.size(); i++) {
((Keyboard*)(kbds[i]))->updateLeds(kbdstatus);
}
}
void keyPress(u8int scancode) {
keypress_t kp;
kp.pressed = true;
kp.modifiers = kbdstatus & 0x0F;
u8int cmd = ctrlkeys[scancode];
scancode &= 0x7F;
if (cmd == 0) cmd = ctrlkeys[scancode];
if (cmd == 0) {
kp.haschar = true;
kp.character = 0;
if ((kbdstatus & STATUS_ALT) or (kbdstatus & STATUS_CTRL)) {
kp.hascmd = true;
}
if (((kbdstatus & STATUS_SHIFT) != 0) xor ((kbdstatus & STATUS_CAPS) != 0)) {
if (kbdstatus & STATUS_ALTGR) {
if (keymapShiftAltgr != NULL) kp.character = keymapShiftAltgr[scancode];
} else {
if (keymapCaps != NULL and (kbdstatus & STATUS_CAPS))
kp.character = keymapCaps[scancode];
else if (keymapShift != NULL)
kp.character = keymapShift[scancode];
}
} else {
if (kbdstatus & STATUS_ALTGR) {
if (keymapAltgr != NULL) kp.character = keymapAltgr[scancode];
} else {
if (keymapNormal != NULL) kp.character = keymapNormal[scancode];
}
}
} else if (cmd >= KBDC_KPINSERT and cmd <= KBDC_KPDEL and (kbdstatus & STATUS_NUM)) {
kp.haschar = true;
if ((kbdstatus & STATUS_ALT) or (kbdstatus & STATUS_CTRL)) {
kp.hascmd = true;
}
if (cmd == KBDC_KPDEL) {
kp.character = (u32int)'.';
} else {
kp.character = (u32int)'0' + (cmd - KBDC_KPINSERT);
}
} else if (cmd == KBDC_KPSLASH) {
kp.haschar = true;
if ((kbdstatus & STATUS_ALT) or (kbdstatus & STATUS_CTRL)) {
kp.hascmd = true;
}
kp.character = (u32int)'/';
} else if (cmd == KBDC_ALT) {
kbdstatus |= STATUS_ALT;
} else if (cmd == KBDC_ALTGR) {
kbdstatus |= STATUS_ALTGR;
} else if (cmd == KBDC_LEFTCTRL or cmd == KBDC_RIGHTCTRL) {
kbdstatus |= STATUS_CTRL;
} else if (cmd == KBDC_LEFTSHIFT or cmd == KBDC_RIGHTSHIFT) {
kbdstatus |= STATUS_SHIFT;
} else if (cmd == KBDC_CAPSLOCK) {
kbdstatus ^= STATUS_CAPS;
updateLeds();
} else if (cmd == KBDC_NUMLOCK) {
kbdstatus ^= STATUS_NUM;
updateLeds();
} else if (cmd == KBDC_SCRLLOCK) {
kbdstatus ^= STATUS_SCRL;
updateLeds();
}
if (!kp.haschar) {
kp.hascmd = true;
kp.command = cmd;
}
process(kp);
}
void keyRelease(u8int scancode) {
keypress_t kp;
kp.pressed = false;
kp.modifiers = kbdstatus & 0x0F;
u8int cmd = ctrlkeys[scancode];
scancode &= 0x7F;
if (cmd == 0) cmd = ctrlkeys[scancode];
if (cmd == 0) {
kp.haschar = true;
kp.character = 0;
if ((kbdstatus & STATUS_ALT) or (kbdstatus & STATUS_CTRL)) {
kp.hascmd = true;
}
if (((kbdstatus & STATUS_SHIFT) != 0) xor ((kbdstatus & STATUS_CAPS) != 0)) {
if (kbdstatus & STATUS_ALTGR) {
if (keymapShiftAltgr != NULL) kp.character = keymapShiftAltgr[scancode];
} else {
if (keymapCaps != NULL and (kbdstatus & STATUS_CAPS))
kp.character = keymapCaps[scancode];
else if (keymapShift != NULL)
kp.character = keymapShift[scancode];
}
} else {
if (kbdstatus & STATUS_ALTGR) {
if (keymapAltgr != NULL) kp.character = keymapAltgr[scancode];
} else {
if (keymapNormal != NULL) kp.character = keymapNormal[scancode];
}
}
} else if (cmd >= KBDC_KPINSERT and cmd <= KBDC_KPDEL and (kbdstatus & STATUS_NUM)) {
kp.haschar = true;
if ((kbdstatus & STATUS_ALT) or (kbdstatus & STATUS_CTRL)) {
kp.hascmd = true;
}
if (cmd == KBDC_KPDEL) {
kp.character = (u32int)'.';
} else {
kp.character = (u32int)'0' + (cmd - KBDC_KPINSERT);
}
} else if (cmd == KBDC_ALT) {
kbdstatus &= ~STATUS_ALT;
} else if (cmd == KBDC_ALTGR) {
kbdstatus &= ~STATUS_ALTGR;
} else if (cmd == KBDC_LEFTCTRL or cmd == KBDC_RIGHTCTRL) {
kbdstatus &= ~STATUS_CTRL;
} else if (cmd == KBDC_LEFTSHIFT or cmd == KBDC_RIGHTSHIFT) {
kbdstatus &= ~STATUS_SHIFT;
}
if (!kp.haschar && cmd) {
kp.hascmd = true;
kp.command = cmd;
}
process(kp);
}
}