hschumann2/TempleOS-Source-Code
0847
1 2asm {3NORMAL_KEY_SCAN_DECODE_TABLE::4 DU8 0,CH_ESC,"1234567890-=",CH_BACKSPACE,'\t';5 DU8 "qwertyuiop[]",'\n',0,"as";6 DU8 "dfghjkl;'\`",0,"\\zxcv";7 DU8 "bnm,./",0,'*',0,CH_SPACE,0,0,0,0,0,0;8 DU8 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;9SHIFT_KEY_SCAN_DECODE_TABLE::10 DU8 0,CH_SHIFT_ESC,"[email protected]#$%^&*()_+",CH_BACKSPACE,'\t';11 DU8 "QWERTYUIOP{}",'\n',0,"AS";12 DU8 "DFGHJKL:\"~",0,"|ZXCV";13 DU8 "BNM<>?",0,'*',0,CH_SHIFT_SPACE,0,0,0,0,0,0;14 DU8 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;15CTRL_KEY_SCAN_DECODE_TABLE::16 DU8 0,CH_ESC,"1234567890-=",CH_BACKSPACE,'\t';17 DU8 CH_CTRLQ,CH_CTRLW,CH_CTRLE,CH_CTRLR,CH_CTRLT,CH_CTRLY,CH_CTRLU,18 CH_CTRLI,CH_CTRLO,CH_CTRLP,"[]",'\n',0,CH_CTRLA,CH_CTRLS;19 DU8 CH_CTRLD,CH_CTRLF,CH_CTRLG,CH_CTRLH,CH_CTRLJ,CH_CTRLK,CH_CTRLL,20 ";'\`",0,"\\",CH_CTRLZ,CH_CTRLX,CH_CTRLC,CH_CTRLV;21 DU8 CH_CTRLB,CH_CTRLN,CH_CTRLM,",./",0,'*',0,CH_SPACE,0,0,0,0,0,0;22 DU8 0,0,0,0,0,0,0,0,0,0,'-',0,0,0,'+',0;23}24 25U0 KbdCmdSend(I64 port, U8 val)26{27 F64 timeout=tS+0.125;28 while (tS<timeout) {29 if (!(InU8(KBD_CTRL)&2)) {30 OutU8(port,val);31 return;32 }33 }34 throw;35}36 37I64 KbdCmdRead()38{39 F64 timeout=tS+0.125;40 while (tS<timeout)41 if (InU8(KBD_CTRL)&1)42 return InU8(KBD_PORT);43 throw;44}45 46U0 KbdCmdFlush()47{48 F64 timeout=tS+0.03;49 while (tS<timeout)50 InU8(KBD_PORT);51}52 53U0 KbdLEDsSet(I64 sc)54{55 U8 v=0;56 BEqu(&v,0,Bt(&sc,SCf_SCROLL));57 BEqu(&v,1,Bt(&sc,SCf_NUM));58 BEqu(&v,2,Bt(&sc,SCf_CAPS));59 try {60 KbdCmdSend(KBD_PORT,0xED);61 KbdCmdSend(KBD_PORT,v);62 } catch63 Fs->catch_except=TRUE;64}65 66U0 KbdMsCmdAck(...)67{68 I64 i,ack,timeout;69 for (i=0;i<argc;i++) {70 timeout=5;71 do {72 ack=0;73 try {74 KbdCmdSend(KBD_CTRL,0xD4);75 KbdCmdSend(KBD_PORT,argv[i]);76 ack=KbdCmdRead;77 } catch {78 KbdCmdFlush;79 Fs->catch_except=TRUE;80 }81 } while (ack!=0xFA && --timeout);82 if (!timeout)83 throw;84 }85}86 87U0 KbdTypeMatic(U8 delay)88{//Set speed of repeated keys.89 try {90 KbdCmdSend(KBD_CTRL,0xA7); //Disable Mouse91 KbdCmdSend(KBD_CTRL,0xAE); //Enable Keyboard92 KbdCmdSend(KBD_PORT,0xF3);93 KbdCmdSend(KBD_PORT,delay); //Typematic rate94 KbdCmdSend(KBD_CTRL,0xA8); //Enable Mouse95 } catch {96 KbdCmdFlush;97 Fs->catch_except=TRUE;98 }99}100 101I64 Char2ScanCode(I64 ch,I64 sc_flags=0)102{//ASCII val to scan code (Slow).103 I64 i;104 U8 *table;105 if (sc_flags) {106 table=NORMAL_KEY_SCAN_DECODE_TABLE;107 if (sc_flags & SCF_CTRL || ch<26)108 table=CTRL_KEY_SCAN_DECODE_TABLE;109 else if (sc_flags & SCF_SHIFT || 'A'<=ch<='Z') {110 if (!(sc_flags & SCF_CAPS))111 table=SHIFT_KEY_SCAN_DECODE_TABLE;112 } else {113 if (sc_flags & SCF_CAPS)114 table=SHIFT_KEY_SCAN_DECODE_TABLE;115 }116 for (i=0;i<0x50;i++)117 if (table[i]==ch)118 return i|sc_flags;119 return sc_flags;120 } else {121 table=NORMAL_KEY_SCAN_DECODE_TABLE;122 for (i=0;i<0x50;i++)123 if (table[i]==ch)124 return i;125 table=SHIFT_KEY_SCAN_DECODE_TABLE;126 for (i=0;i<0x50;i++)127 if (table[i]==ch)128 return i|SCF_SHIFT;129 table=CTRL_KEY_SCAN_DECODE_TABLE;130 for (i=0;i<0x50;i++)131 if (table[i]==ch)132 return i|SCF_CTRL;133 return 0;134 }135}136 137U8 ScanCode2Char(I64 sc)138{//Scan code to ASCII val.139 U8 *table=NORMAL_KEY_SCAN_DECODE_TABLE;140 if (sc&SCF_E0_PREFIX)141 return 0;142 if (sc&SCF_CTRL)143 table=CTRL_KEY_SCAN_DECODE_TABLE;144 else if (sc&SCF_SHIFT) {145 if (!(sc&SCF_CAPS))146 table=SHIFT_KEY_SCAN_DECODE_TABLE;147 } else {148 if (sc&SCF_CAPS)149 table=SHIFT_KEY_SCAN_DECODE_TABLE;150 }151 sc&=0x7F;152 if (sc>=0x50)153 return 0;154 else155 return table[sc];156}157 158U8 scan_code_map[0x100]={159 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,160 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,161 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,162 0,0,0,0,0,0,SC_SHIFT,0,0,0,0,0,0,0,0,0,163 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,164 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,165 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,166 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,167 168 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,169 0,0,0,0,0,0,0,0,0,0,0,0,SC_ENTER,SC_CTRL,0,0,170 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,171 0,0,0,0,0,0x35,0,0,SC_ALT,0,0,0,0,0,0,0,172 0,0,0,0,0,0,0,SC_HOME,173 SC_CURSOR_UP,SC_PAGE_UP,0,SC_CURSOR_LEFT,0,SC_CURSOR_RIGHT,0,SC_END,174 SC_CURSOR_DOWN,SC_PAGE_DOWN,SC_INS,SC_DELETE,0,0,0,0,175 0,0,0,0,SC_GUI,0,0,0,176 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,177 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,178};179 180U8 num_lock_map[0x100]={181 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,182 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,183 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,184 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185 0,0,0,0,0,0,0,8,9,10,0,5,6,7,0,2,186 3,4,11,0x34,0,0,0,0,0,0,0,0,0,0,0,0,187 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,188 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,189 190 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,191 0,0,0,0,0,0,0,0,0,0,0,0,SC_ENTER,SC_CTRL,0,0,192 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,193 0,0,0,0,0,0x35,0,0,SC_ALT,0,0,0,0,0,0,0,194 0,0,0,0,0,0,0,SC_HOME,195 SC_CURSOR_UP,SC_PAGE_UP,0,SC_CURSOR_LEFT,0,SC_CURSOR_RIGHT,0,SC_END,196 SC_CURSOR_DOWN,SC_PAGE_DOWN,SC_INS,SC_DELETE,0,0,0,0,197 0,0,0,0,SC_GUI,0,0,0,198 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,199 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,200};201 202U8 *Char2KeyName(I64 ch,Bool include_ctrl=TRUE)203{//ASCII val to key name.204 I64 i;205 U8 buf[STR_LEN];206 if (ch<=CH_SPACE) {207 switch [ch] {208 case '\n':209 StrCpy(buf,"ENTER");210 break;211 case CH_BACKSPACE:212 StrCpy(buf,"BACKSPACE");213 break;214 case '\t':215 StrCpy(buf,"TAB");216 break;217 case CH_ESC:218 StrCpy(buf,"ESC");219 break;220 case CH_SHIFT_ESC:221 StrCpy(buf,"SHIFT_ESC");222 break;223 case 0: //nobound switch224 case 29:225 case 30:226 *buf=0;227 break;228 case CH_SHIFT_SPACE:229 StrCpy(buf,"SHIFT_SPACE");230 break;231 case CH_SPACE:232 StrCpy(buf,"SPACE");233 break;234 default:235 if (include_ctrl)236 StrCpy(buf,"CTRL ");237 buf[i=StrLen(buf)]=ch-1+'a';238 buf[i+1]=0;239 break;240 }241 } else if (Bt(char_bmp_printable,ch)) {242 *buf=ch;243 buf[1]=0;244 } else245 *buf=0;246 return StrNew(buf);247}248 249U8 *ScanCode2KeyName(I64 sc)250{//Scan code to key name.251 I64 ch;252 U8 buf[STR_LEN],*st;253 *buf=0;254 if (sc&SCF_CTRL)255 CatPrint(buf,"CTRL ");256 if (sc&SCF_ALT)257 CatPrint(buf,"ALT ");258 if (sc&SCF_SHIFT)259 CatPrint(buf,"SHIFT ");260 if (sc&SCF_NO_SHIFT)261 CatPrint(buf," ");262 if (ch=ScanCode2Char(sc&255)) {263 st=Char2KeyName(ch,FALSE);264 StrCpy(buf+StrLen(buf),st);265 Free(st);266 } else {267 switch (sc&255) {268 case SC_BACKSPACE:CatPrint(buf,"BACK"); break;269 case SC_CAPS: CatPrint(buf,"CAPS"); break;270 case SC_NUM: CatPrint(buf,"NUM"); break;271 case SC_SCROLL: CatPrint(buf,"SCROLL"); break;272 case SC_CURSOR_UP:CatPrint(buf,"UP"); break;273 case SC_CURSOR_DOWN:CatPrint(buf,"DOWN"); break;274 case SC_CURSOR_LEFT:CatPrint(buf,"LEFT"); break;275 case SC_CURSOR_RIGHT:CatPrint(buf,"RIGHT"); break;276 case SC_PAGE_UP: CatPrint(buf,"PAGE_UP"); break;277 case SC_PAGE_DOWN:CatPrint(buf,"PAGE_DOWN");break;278 case SC_HOME: CatPrint(buf,"HOME"); break;279 case SC_END: CatPrint(buf,"END"); break;280 case SC_INS: CatPrint(buf,"INS"); break;281 case SC_DELETE: CatPrint(buf,"DELETE"); break;282 case SC_F1: CatPrint(buf,"F1"); break;283 case SC_F2: CatPrint(buf,"F2"); break;284 case SC_F3: CatPrint(buf,"F3"); break;285 case SC_F4: CatPrint(buf,"F4"); break;286 case SC_F5: CatPrint(buf,"F5"); break;287 case SC_F6: CatPrint(buf,"F6"); break;288 case SC_F7: CatPrint(buf,"F7"); break;289 case SC_F8: CatPrint(buf,"F8"); break;290 case SC_F9: CatPrint(buf,"F9"); break;291 case SC_F10: CatPrint(buf,"F10"); break;292 case SC_F11: CatPrint(buf,"F11"); break;293 case SC_F12: CatPrint(buf,"F12"); break;294 case SC_GUI: CatPrint(buf,"WINDOWS"); break;295 case SC_PRTSCRN1: CatPrint(buf,"PRTSCRN1"); break;296 case SC_PRTSCRN2: CatPrint(buf,"PRTSCRN2"); break;297 }298 }299 return StrNew(buf);300}301 302U0 KbdBuildSC(U8 raw_byte,Bool in_irq,U8 *_last_raw_byte,I64 *_last_sc)303{304 I64 ch,sc_flags,sc,sc2,sc_raw,new_key_f;305 Bool set_LEDs=FALSE;306 if (raw_byte==0xE0) {307 *_last_sc&=~0x1FF;308 *_last_raw_byte=raw_byte;309 return;310 }311 sc=raw_byte;312 BEqu(&sc,SCf_E0_PREFIX,*_last_raw_byte==0xE0);313 BEqu(&sc,SCf_KEY_UP,raw_byte & 0x80);314 *_last_raw_byte=raw_byte;315 316 sc_flags=_last_sc->u32[0]&~0x1FF;317 sc_raw=sc;318 319 if (sc_flags & SCF_NUM) {320 if (sc2=num_lock_map[sc.u8[0]])321 sc.u8[0]=sc2;322 } else {323 if (sc2=scan_code_map[sc.u8[0]])324 sc.u8[0]=sc2;325 }326 327 new_key_f=SCF_NEW_KEY;328 if (sc&SCF_KEY_UP)329 switch (sc&~SCF_KEY_UP) {330 case SC_SHIFT: sc_flags&=~SCF_SHIFT; break;331 case SC_CTRL: sc_flags&=~SCF_CTRL; break;332 case SC_ALT: sc_flags&=~SCF_ALT; break;333 case SC_DELETE: sc_flags&=~SCF_DELETE; break;334 case SC_INS: sc_flags&=~SCF_INS; break;335 case SC_CAPS: sc_flags^=SCF_CAPS; set_LEDs=TRUE; break;336 case SC_NUM: sc_flags^=SCF_NUM; set_LEDs=TRUE; break;337 case SC_SCROLL: sc_flags^=SCF_SCROLL; set_LEDs=TRUE; break;338 }339 else340 switch (sc) {341 case SC_SHIFT:342 if (Bts(&sc_flags,SCf_SHIFT)) new_key_f=0;343 break;344 case SC_CTRL:345 if (Bts(&sc_flags,SCf_CTRL)) new_key_f=0;346 break;347 case SC_ALT:348 if (Bts(&sc_flags,SCf_ALT)) new_key_f=0;349 break;350 case SC_DELETE:351 sc_flags|=SCF_DELETE;352 break;353 case SC_INS:354 sc_flags|=SCF_INS;355 break;356 }357 358 sc_flags|=new_key_f;359 sc=sc_flags|sc|(sc_flags|sc_raw)<<32;360 if (sc_flags & SCF_CTRL && sc_flags & SCF_ALT) {361 if (!(sc&SCF_KEY_UP)) {362 if (sc&255==SC_DELETE && !(sc_flags & SCF_SHIFT))363 CtrlAltDel(sc);364 else {365 if (sc&255==SC_ESC)366 ch='t';367 else if (sc&255==SC_TAB)368 ch='n';369 else370 ch=ScanCode2Char(sc&255);371 if ('a'<=ch<='z') {372 sc&=~(SCF_NEW_KEY|SCF_NEW_KEY<<32);373 ch-='a';374 kbd.last_down_scan_code=sc;375 if (keydev.fp_ctrl_alt_cbs[ch] &&376 Bt(&keydev.ctrl_alt_in_irq_flags,ch)==in_irq &&377 (!(sc_flags & SCF_SHIFT)&&keydev.ctrl_alt_no_shift_descs[ch]) ||378 sc_flags & SCF_SHIFT && keydev.ctrl_alt_shift_descs[ch])379 (*keydev.fp_ctrl_alt_cbs[ch])(sc);380 }381 }382 }383 }384 if (set_LEDs && !in_irq)385 KbdLEDsSet(sc);386 *_last_sc=sc;387}388 389U0 KbdPktRead()390{391 static U8 last_raw_byte=0;392 static I64 last_sc=0;393 U8 raw_byte;394 if (GetTSC>kbd.timestamp+cnts.time_stamp_freq>>3)395 FifoU8Flush(kbd.fifo);396 kbd.timestamp=GetTSC;397 raw_byte=InU8(KBD_PORT);398 KbdBuildSC(raw_byte,TRUE,&last_raw_byte,&last_sc);399 if (!FifoU8Cnt(kbd.fifo)) {400 FifoU8Ins(kbd.fifo,raw_byte);401 if (raw_byte!=0xE0) {402 while (FifoU8Rem(kbd.fifo,&raw_byte))403 FifoU8Ins(kbd.fifo2,raw_byte);404 }405 } else {406 FifoU8Ins(kbd.fifo,raw_byte);407 while (FifoU8Rem(kbd.fifo,&raw_byte))408 FifoU8Ins(kbd.fifo2,raw_byte);409 }410}411 412interrupt U0 IRQKbd()413{414 CLD415 OutU8(0x20,0x20);416 kbd.irqs_working=TRUE;417 if (ms_hard.install_in_progress) {418 kbd.rst=TRUE;419 return;420 }421 keydev.ctrl_alt_ret_addr=GetRBP()(I64)+8;422 KbdPktRead;423}424 425U0 KbdInit()426{427 try {428 KbdCmdFlush;429 KbdCmdSend(KBD_CTRL,0xA7); //Disable Mouse430 KbdCmdSend(KBD_CTRL,0xAE); //Enable Keyboard431 KbdCmdSend(KBD_PORT,0xF0);432 KbdCmdSend(KBD_PORT,0x02);433 KbdLEDsSet(kbd.scan_code);434 } catch {435 KbdCmdFlush;436 Fs->catch_except=TRUE;437 }438 IntEntrySet(0x21,&IRQKbd);439 OutU8(0x21,InU8(0x21)&~2);440}441 442U0 KbdHndlr()443{444 static U8 last_raw_byte=0;445 U8 raw_byte;446 FifoU8Rem(kbd.fifo2,&raw_byte);447 KbdBuildSC(raw_byte,FALSE,&last_raw_byte,&kbd.scan_code);448 if (raw_byte==0xE0) {449 FifoU8Rem(kbd.fifo2,&raw_byte);450 KbdBuildSC(raw_byte,FALSE,&last_raw_byte,&kbd.scan_code);451 }452 if (Btr(&kbd.scan_code,SCf_NEW_KEY)) {453 kbd.new_key_timestamp=kbd.timestamp;454 Btr(&kbd.scan_code,32+SCf_NEW_KEY);455 FifoI64Ins(kbd.scan_code_fifo,kbd.scan_code);456 kbd.cnt++;457 if (!(kbd.scan_code&SCF_KEY_UP)) {458 kbd.last_down_scan_code=kbd.scan_code;459 Bts(kbd.down_bitmap,kbd.scan_code.u8[0]);460 Bts(kbd.down_bitmap2,kbd.scan_code.u8[4]);461 } else {462 Btr(kbd.down_bitmap,kbd.scan_code.u8[0]);463 Btr(kbd.down_bitmap2,kbd.scan_code.u8[4]);464 }465 }466}467 468I64 KbdMsgsQue()469{470 I64 arg1,arg2,msg_code=MSG_NULL;471 CTask *task_focus;472 if (task_focus=sys_focus_task) {473 while (FifoI64Rem(kbd.scan_code_fifo,&arg2)) {474 arg1=ScanCode2Char(arg2);475 if (arg2 & SCF_KEY_UP) {476 TaskMsg(task_focus,0,MSG_KEY_UP,arg1,arg2,0);477 msg_code=MSG_KEY_UP;478 } else {479 TaskMsg(task_focus,0,MSG_KEY_DOWN,arg1,arg2,0);480 msg_code=MSG_KEY_DOWN;481 }482 }483 }484 return msg_code;485}486 487I64 KbdMsEvtTime()488{//Timestamp of last key or mouse event.489 if (ms_hard.timestamp>kbd.timestamp)490 return ms_hard.timestamp;491 else492 return kbd.new_key_timestamp;493}494 