Project: OSMain
asm {
NORMAL_KEY_SCAN_DECODE_TABLE::
DU1 0,CH_ESC,"1234567890-=",8,9;
DU1 "qwertyuiop[]",CH_CR,0,"as";
DU1 "dfghjkl;'\`",0,"\\zxcv";
DU1 "bnm,./",0,'*',0,CH_SPACE,0,0,0,0,0,0;
DU1 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;
SHIFT_KEY_SCAN_DECODE_TABLE::
DU1 0,CH_ESC,"!@#$%^&*()_+",8,9;
DU1 "QWERTYUIOP{}",CH_CR,0,"AS";
DU1 "DFGHJKL:\"~",0,"|ZXCV";
DU1 "BNM<>?",0,'*',0,CH_SHIFT_SPACE,0,0,0,0,0,0;
DU1 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;
CTRL_KEY_SCAN_DECODE_TABLE::
DU1 0,CH_ESC,"1234567890-=",8,9;
DU1 17,23,5,18,20,25,21,9,15,16,"[]",CH_CR,0,1,19;
DU1 4,6,7,8,CH_LINE_FEED,11,12,";'\`",0,"\\",26,24,3,22;
DU1 2,14,13,",./",0,'*',0,CH_SPACE,0,0,0,0,0,0;
DU1 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;
}
U0 KbdCmdSend(U8 port, U1 val)
{
LTDate timeout=BootTime+LTDATE_FREQ/8;
while (BootTime<timeout) {
if (!(InU1(KEYB_CTRL)&2)) {
OutU1(port,val);
return;
}
}
throw (EXCEPT_LOCAL);
}
I8 KbdCmdRead()
{
LTDate timeout=BootTime+LTDATE_FREQ/8;
while (BootTime<timeout)
if (InU1(KEYB_CTRL)&1)
return InU1(KEYB_PORT);
throw (EXCEPT_LOCAL);
}
U0 KbdCmdFlush()
{
LTDate timeout=BootTime+LTDATE_FREQ/32;
while (BootTime<timeout)
InU1(KEYB_PORT);
}
U0 KbdSetLEDs(U8 sc)
{
BoolI1 old_preempt=Preempt(OFF);
U1 v=0;
BEqu(&v,0,Bt(&sc,SCf_SCROLL));
BEqu(&v,1,Bt(&sc,SCf_NUM));
BEqu(&v,2,Bt(&sc,SCf_CAPS));
try {
KbdCmdSend(KEYB_PORT,0xED);
KbdCmdSend(KEYB_PORT,v);
} catch
Fs->catch_except=TRUE;
Preempt(old_preempt);
}
U0 KbdMouseCmdAck(U1 val)
{
I8 ack,timeout=5;
do {
ack=0;
try {
KbdCmdSend(KEYB_CTRL,0xD4);
KbdCmdSend(KEYB_PORT,val);
ack=KbdCmdRead;
} catch {
KbdCmdFlush;
Fs->catch_except=TRUE;
}
} while (ack!=0xFA && --timeout);
if (!timeout)
throw (EXCEPT_LOCAL);
}
U0 SetTypeMatic(U1 delay)
{
try {
KbdCmdSend(KEYB_CTRL,0xA7); //Disable Mouse
KbdCmdSend(KEYB_CTRL,0xAE); //Enable Keyboard
KbdCmdSend(KEYB_PORT,0xF3);
KbdCmdSend(KEYB_PORT,delay); //Typematic rate
KbdCmdSend(KEYB_CTRL,0xA8); //Enable Mouse
} catch {
KbdCmdFlush;
Fs->catch_except=TRUE;
}
}
U8 A2ScanCode(U8 ch,U8 sc_flags=0)
{ //ASCII value to scan code (Slow)
I8 i;
U1 *table;
if (sc_flags) {
table=NORMAL_KEY_SCAN_DECODE_TABLE;
if (sc_flags & SCF_CTRL || ch<26)
table=CTRL_KEY_SCAN_DECODE_TABLE;
else if (sc_flags & SCF_SHIFT || 'A'<=ch<='Z') {
if (!(sc_flags & SCF_CAPS))
table=SHIFT_KEY_SCAN_DECODE_TABLE;
} else {
if (sc_flags & SCF_CAPS)
table=SHIFT_KEY_SCAN_DECODE_TABLE;
}
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i|sc_flags;
return sc_flags;
} else {
table=NORMAL_KEY_SCAN_DECODE_TABLE;
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i;
table=SHIFT_KEY_SCAN_DECODE_TABLE;
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i|SCF_SHIFT;
table=CTRL_KEY_SCAN_DECODE_TABLE;
for (i=0;i<0x50;i++)
if (table[i]==ch)
return i|SCF_CTRL;
return 0;
}
}
U1 ScanCode2A(U8 sc)
{//Scan Code to ASCII value
U1 *table=NORMAL_KEY_SCAN_DECODE_TABLE;
if (sc & SCF_E0_PREFIX)
return 0;
if (sc & SCF_CTRL)
table=CTRL_KEY_SCAN_DECODE_TABLE;
else if (sc & SCF_SHIFT) {
if (!(sc & SCF_CAPS))
table=SHIFT_KEY_SCAN_DECODE_TABLE;
} else {
if (sc & SCF_CAPS)
table=SHIFT_KEY_SCAN_DECODE_TABLE;
}
sc&=0x7F;
if (sc>=0x50)
return 0;
else
return table[sc];
}
U1 scan_code_map[0x100]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,SC_SHIFT,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,SC_CR,SC_CTRL,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0x35,0,0,SC_ALT,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,SC_HOME,SC_CURSOR_UP,SC_PAGE_UP,0,SC_CURSOR_LEFT,0,SC_CURSOR_RIGHT,0,SC_END,
SC_CURSOR_DOWN,SC_PAGE_DOWN,SC_INSERT,SC_DELETE,0,0,0,0,0,0,0,0,SC_GUI,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
U1 num_lock_map[0x100]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,8,9,10,0,5,6,7,0,2,
3,4,11,0x34,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,SC_CR,SC_CTRL,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0x35,0,0,SC_ALT,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,SC_HOME,SC_CURSOR_UP,SC_PAGE_UP,0,SC_CURSOR_LEFT,0,SC_CURSOR_RIGHT,0,SC_END,
SC_CURSOR_DOWN,SC_PAGE_DOWN,SC_INSERT,SC_DELETE,0,0,0,0,0,0,0,0,SC_GUI,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
U1 *A2KeyName(U8 ch,BoolI1 include_ctrl=TRUE)
{//ASCII value to key name
U8 i;
U1 buf[64];
*buf=0;
if (ch) {
if (ch<=27) {
if (ch==CH_CR)
StrCat(buf,"ENTER");
else if (ch==CH_ESC)
StrCat(buf,"ESC");
else if (ch==CH_BACKSPACE)
StrCat(buf,"BACKSPACE");
else if (ch==CH_TAB)
StrCat(buf,"TAB");
else if (ch==CH_CURSOR)
StrCat(buf,"CURSOR");
else {
if (include_ctrl)
StrCat(buf,"CTRL");
buf[i=StrLen(buf)]=ch-1+'a';
buf[i+1]=0;
}
} else if (Bt(printable_chars_bitmap,ch)) {
if (ch==CH_SPACE)
StrCat(buf,"SPACE");
else if (ch==CH_SHIFT_SPACE)
StrCat(buf,"SHIFT_SPACE");
else {
buf[i=StrLen(buf)]=ch;
buf[i+1]=0;
}
}
}
return StrNew(buf);
}
U1 *ScanCode2KeyName(U8 sc)
{
U8 ch;
U1 buf[64],*st;
*buf=0;
if (sc&SCF_CTRL)
StrCat(buf,"CTRL");
if (sc&SCF_ALT)
StrCat(buf,"ALT");
if (sc&SCF_SHIFT)
StrCat(buf,"SHIFT");
if (ch=ScanCode2A(sc.u1[0])) {
st=A2KeyName(ch,FALSE);
StrCpy(buf+StrLen(buf),st);
Free(st);
} else {
switch (sc.u1[0]) {
case SC_BACKSPACE:StrCat(buf,"BACK"); break;
case SC_CAPS: StrCat(buf,"CAPS"); break;
case SC_NUM: StrCat(buf,"NUM"); break;
case SC_SCROLL: StrCat(buf,"SCROLL"); break;
case SC_CURSOR_UP:StrCat(buf,"UP"); break;
case SC_CURSOR_DOWN:StrCat(buf,"DOWN"); break;
case SC_CURSOR_LEFT:StrCat(buf,"LEFT"); break;
case SC_CURSOR_RIGHT:StrCat(buf,"RIGHT"); break;
case SC_PAGE_UP:StrCat(buf,"PAGE_UP"); break;
case SC_PAGE_DOWN:StrCat(buf,"PAGE_DOWN"); break;
case SC_HOME: StrCat(buf,"HOME"); break;
case SC_END: StrCat(buf,"END"); break;
case SC_INSERT: StrCat(buf,"INSERT"); break;
case SC_DELETE: StrCat(buf,"DELETE"); break;
case SC_F1: StrCat(buf,"F1"); break;
case SC_F2: StrCat(buf,"F2"); break;
case SC_F3: StrCat(buf,"F3"); break;
case SC_F4: StrCat(buf,"F4"); break;
case SC_F5: StrCat(buf,"F5"); break;
case SC_F6: StrCat(buf,"F6"); break;
case SC_F7: StrCat(buf,"F7"); break;
case SC_F8: StrCat(buf,"F8"); break;
case SC_F9: StrCat(buf,"F9"); break;
case SC_F10: StrCat(buf,"F10"); break;
case SC_F11: StrCat(buf,"F11"); break;
case SC_F12: StrCat(buf,"F12"); break;
case SC_GUI: StrCat(buf,"WINDOWS"); break;
case SC_PRTSCRN1: StrCat(buf,"PRTSCRN1"); break;
case SC_PRTSCRN2: StrCat(buf,"PRTSCRN2"); break;
}
}
return StrNew(buf);
}
U0 KbdPktRead()
{
U1 j;
if (GetTimeStamp>kbd_evt_time+time_stamp_freq>>3)
U1FifoFlush(kbd_fifo);
kbd_evt_time=GetTimeStamp;
LowPower(FALSE);
j=InU1(KEYB_PORT);
if (!U1FifoCnt(kbd_fifo)) {
U1FifoInsert(kbd_fifo,0x01);
U1FifoInsert(kbd_fifo,j);
if (j!=0xE0) {
while (U1FifoRem(kbd_fifo,&j))
U1FifoInsert(kbdmouse_fifo,j);
}
} else {
U1FifoInsert(kbd_fifo,j);
while (U1FifoRem(kbd_fifo,&j))
U1FifoInsert(kbdmouse_fifo,j);
}
}
interrupt U0 KbdIntHandler()
{
Cld;
OutU1(0x20,0x20);
if (attempting_mouse_install) {
reset_kbdmouse=TRUE;
return;
}
KbdPktRead;
}
U0 KbdInit()
{
try {
KbdCmdFlush;
KbdCmdSend(KEYB_CTRL,0xA7); //Disable Mouse
KbdCmdSend(KEYB_CTRL,0xAE); //Enable Keyboard
KbdCmdSend(KEYB_PORT,0xF0);
KbdCmdSend(KEYB_PORT,0x02);
KbdSetLEDs(sys_cur_scan_code);
} catch {
KbdCmdFlush;
Fs->catch_except=TRUE;
}
SetIDTEntry(0x21,&KbdIntHandler,0);
OutU1(0x21,InU1(0x21)&~2);
SetCtrlAltLetterRoutine('C',&CtrlAltC,"Sys/Break Execution");
SetCtrlAltLetterRoutine('D',&CtrlAltD,"Sys/Reboot");
SetCtrlAltLetterRoutine('E',&CtrlAltE,"Sys/Spawn New User Task");
SetCtrlAltLetterRoutine('P',&CtrlAltP,"Sys/Toggle Pause Focused Task");
SetCtrlAltLetterRoutine('T',&CtrlAltT,"Sys/Switch Focus to Next Task");
SetCtrlAltLetterRoutine('X',&CtrlAltX,"Sys/Kill Focused Task");
}
U0 KbdHandler()
{
U8 ch,sc,sc2=0,sc3,sc_raw;
U1FifoRem(kbdmouse_fifo,&sc2);
if (sc2==0xE0) {
U1FifoRem(kbdmouse_fifo,&sc2);
BEqu(&sc2,SCf_KEY_UP,sc2 & 0x80);
Bts(&sc2,SCf_E0_PREFIX);
} else {
BEqu(&sc2,SCf_KEY_UP,sc2 & 0x80);
Btr(&sc2,SCf_E0_PREFIX);
}
sc=sys_cur_scan_code.u4[0]&~0x1FF;
sc_raw=sc2;
if (sc & SCF_NUM) {
if (sc3=num_lock_map[sc2.u1[0]])
sc2.u1[0]=sc3;
} else {
if (sc3=scan_code_map[sc2.u1[0]])
sc2.u1[0]=sc3;
}
if (sc2==SC_SHIFT) {
sc|=SCF_SHIFT;
goto new_key_done;
}
if (sc2==SC_SHIFT+SCF_KEY_UP) {
sc&=~SCF_SHIFT;
goto new_key_done;
}
if (sc2==SC_CTRL) {
sc|=SCF_CTRL;
goto new_key_done;
}
if (sc2==SC_CTRL+SCF_KEY_UP) {
sc&=~SCF_CTRL;
goto new_key_done;
}
if (sc2==SC_ALT) {
sc|=SCF_ALT;
goto new_key_done;
}
if (sc2==SC_ALT+SCF_KEY_UP) {
sc&=~SCF_ALT;
goto new_key_done;
}
if (sc2==SC_DELETE)
sc|=SCF_DELETE;
else if (sc2==SC_DELETE+SCF_KEY_UP)
sc&=~SCF_DELETE;
if (sc2==SC_INSERT)
sc|=SCF_INSERT;
else if (sc2==SC_INSERT+SCF_KEY_UP)
sc&=~SCF_INSERT;
if (sc2==SC_CAPS)
goto new_key_done;
if (sc2==SC_CAPS+SCF_KEY_UP) {
sc^=SCF_CAPS;
KbdSetLEDs(sc);
goto new_key_done;
}
if (sc2==SC_NUM)
goto new_key_done;
if (sc2==SC_NUM+SCF_KEY_UP) {
sc^=SCF_NUM;
KbdSetLEDs(sc);
goto new_key_done;
}
if (sc2==SC_SCROLL)
goto new_key_done;
if (sc2==SC_SCROLL+SCF_KEY_UP) {
sc^=SCF_SCROLL;
KbdSetLEDs(sc);
goto new_key_done;
}
if (sc & SCF_CTRL && sc & SCF_ALT) {
sc&=~SCF_NEW_KEY;
sys_cur_scan_code=sc|sc2|
(sc|sc_raw)<<32;
if (!(sc2 & SCF_KEY_UP)) {
if (sc2.u1[0]==SC_DELETE)
ch='d';
else if (sc2.u1[0]==SC_ESC)
ch='e';
else if (sc2.u1[0]==SC_TAB)
ch='t';
else
ch=ScanCode2A(sc2.u1[0]);
if ('a'<=ch<='z') {
if (fp_ctrl_alt_letter_routines[ch-'a'])
fp_ctrl_alt_letter_routines[ch-'a'](sys_cur_scan_code);
}
}
return;
}
new_key_done:
sc|=SCF_NEW_KEY;
sys_cur_scan_code=sc|sc2|
(sc|sc_raw)<<32;
if (Btr(&sys_cur_scan_code,SCf_NEW_KEY)) {
Btr(&sys_cur_scan_code,32+SCf_NEW_KEY);
U8FifoInsert(scan_code_fifo,sys_cur_scan_code);
sys_key_cnt++;
if (!(sys_cur_scan_code&SCF_KEY_UP)) {
last_down_scan_code=sys_cur_scan_code;
Bts(key_down_bitmap,sys_cur_scan_code.u1[0]);
Bts(key_down_bitmap2,sys_cur_scan_code.u1[4]);
} else {
Btr(key_down_bitmap,sys_cur_scan_code.u1[0]);
Btr(key_down_bitmap2,sys_cur_scan_code.u1[4]);
}
}
}
U8 KbdQueueMsgs()
{
I8 p1,p2,msg_code=MSG_NULL;
TaskStruct *task_focus;
if (task_focus=sys_cur_focus_task) {
while (U8FifoRem(scan_code_fifo,&p2)) {
p1=ScanCode2A(p2);
if (p2 & SCF_KEY_UP) {
QueueMsg(task_focus,0,
MSG_KEY_UP,p1,p2,0);
msg_code=MSG_KEY_UP;
} else {
QueueMsg(task_focus,0,
MSG_KEY_DOWN,p1,p2,0);
msg_code=MSG_KEY_DOWN;
}
}
}
return msg_code;
}