📄 ps2_kbd.c
字号:
return 0;
}
//--------------------------------------------------------------------------
// wait_ps2_kbd_obf_set()
//
// This routine waits until the Output Buffer Flag is Set,
// or time's out
vulong wait_ps2_kbd_obf_set()
{
int timeout;
// check the results
timeout = PS2_TIMEOUT;
while(timeout){
// delay before each check
monDelay(1);
if (PS2_REG(PS2_STAT) & PS2_STAT_OBF) break;
timeout--;
}
if (timeout == 0){
ps2_kbd_ok = 0;
printf("PS2 Wait for Output Buffer Flag Set Timed Out - Controller Failure?\n");
return -1;
}
return 0;
}
//--------------------------------------------------------------------------
// ps2_gotachar()
//
// This routine will retreive a character from the PS/2 keyboard. We
// have to do a scan code conversion to see if we have a returnable
// character, thus removing it from the ps/2 controller. This routine
// will save the converted value, if valid, in ps2_char for retrieval
// by ps2_getchar.
//
vulong ps2_gotachar()
{
vuchar sc, c;
// make sure we even have a keyboard
if(ps2_kbd_ok == 0) return 0;
// return true immediately if we still have a
// character that has not been read
if(ps2_char_ok == 1) return 1;
// get a scan code
sc = ps2_scan();
if(sc){
// make sure we have a valid code
// if not we just ignore it
if (sc <= LAST_SCAN_CODE) {
// check the state of caps, ctl and shift to get the
// right array
if (ps2_ctl_flag) {
c = ps2_scan_code[sc][3];
}
else if(ps2_shift_flag) {
c = ps2_scan_code[sc][1];
}
else if(ps2_led_flag & PS2_KBD_CMD_LED_CAPS){
c = ps2_scan_code[sc][2];
}
else {
c = ps2_scan_code[sc][0];
}
// see if we have a valid ascii lookup
if(c != 0xff) {
ps2_char = c;
ps2_char_ok = 1;
return 1;
}
} // if sc <= LAST_SCAN_CODE
} // if sc
return 0;
}
//--------------------------------------------------------------------------
// ps2_getchar()
//
// This routine returns ps2_char
//
vuchar ps2_getchar()
{
if((ps2_kbd_ok) && (ps2_char_ok)) {
ps2_char_ok = 0;
return ps2_char;
}
return 0;
}
//--------------------------------------------------------------------------
// ps2_scan()
//
// This routine will return a scan code from the keyboard if there is
// one. If not, or if it is a control key, it will return 0. For control
// keys it will update the global flags so the calling routine can
// interpret the next non-control key appropriately.
//
vuchar ps2_scan()
{
vuchar c;
if(PS2_REG(PS2_STAT) & PS2_STAT_OBF){
c = PS2_REG(PS2_DATA);
// if it is a break, we still process it to handle de-assertion of shift, alt, etc,
if(c & 0x80) ps2_break_c = 1;
// strip the break bit
c = c & 0x7f;
switch (c){
case KEY_EXT0 :
case KEY_EXT1 :
break;
// set the flags for shift, ctl and alt when the key
// is pressed, clear when the key is released
case KEY_R_SHIFT :
case KEY_L_SHIFT :
if(ps2_break_c == 0) ps2_shift_flag = 1;
else{ ps2_shift_flag = 0; ps2_break_c = 0; }
break;
case KEY_ALT :
if(ps2_break_c == 0) ps2_alt_flag = 1;
else { ps2_alt_flag = 0; ps2_break_c = 0; }
break;
case KEY_CTL :
if(ps2_break_c == 0) ps2_ctl_flag = 1;
else { ps2_ctl_flag = 0; ps2_break_c = 0; }
break;
// update led_flag when CAPS, NUM or Scroll lock are pressed,
// maintain state when they are released.
case KEY_CAPS :
if(ps2_break_c == 0) ps2_led_flag = ps2_led_flag ^ PS2_KBD_CMD_LED_CAPS;
else ps2_break_c = 0;
// update the LED's
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = PS2_KBD_CMD_LED;
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = ps2_led_flag & 0x07;
ps2_kbd_obf_flush();
break;
case KEY_NUM_LK :
if(ps2_break_c == 0) ps2_led_flag = ps2_led_flag ^ PS2_KBD_CMD_LED_NUM;
else ps2_break_c = 0;
// update the LED's
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = PS2_KBD_CMD_LED;
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = ps2_led_flag & 0x07;
ps2_kbd_obf_flush();
break;
case KEY_SCROLL_LK :
if(ps2_break_c == 0) ps2_led_flag = ps2_led_flag ^ PS2_KBD_CMD_LED_SCROLL;
else ps2_break_c = 0;
// update the LED's
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = PS2_KBD_CMD_LED;
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = ps2_led_flag & 0x07;
ps2_kbd_obf_flush();
break;
default :
// printf("c = 0x%02x\n", c);
if(ps2_break_c == 0) return c;
else { ps2_break_c = 0; break; }
} // switch
} // if PS2_STAT
return 0;
}
//--------------------------------------------------------------------------
// ps2_tst()
//
// This routine will display an ascii string corresponding to the
// received scan code. The END key will end the test.
//
char *ps2Help[] = {
"PS/2 compatible port test",
"",
"Notes:",
" * For each keypress (except control keys), this test will display",
" an ascii string describing the scan code. If the scan code is",
" not recognized the hex value of the scan code will be displayed",
" instead.",
" * Pressing the END Key terminates the test. It also updates the",
" LEDs when CAPS, Num Lock or Scroll Lock are pressed.",
(char *)0,
};
int ps2_tst()
{
vuchar c, sc;
ps2_kbd_init();
if (ps2_kbd_ok == 0){
printf("PS/2 Keyboard Init Failed.\n");
return 0;
}
printf("Keyboard Detected - Turning LEDs off.\n");
// Flush the Output buffer
ps2_kbd_obf_flush();
// Blink the LED's
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = PS2_KBD_CMD_LED;
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = 0x00;
monDelay(100);
printf("Turning LEDs on.\n");
ps2_kbd_obf_flush();
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = PS2_KBD_CMD_LED;
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = PS2_KBD_CMD_LED_SCROLL |
PS2_KBD_CMD_LED_NUM |
PS2_KBD_CMD_LED_CAPS;
monDelay(100);
printf("Turning LEDs off.\n");
ps2_kbd_obf_flush();
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = PS2_KBD_CMD_LED;
if (wait_ps2_kbd_ibf_clr()) return 0;
PS2_REG(PS2_DATA) = 0x00;
if (wait_ps2_kbd_ibf_clr()) return 0;
ps2_kbd_obf_flush();
ps2_shift_flag = 0;
ps2_alt_flag = 0;
ps2_ctl_flag = 0;
ps2_led_flag = 0;
printf("Entering Scan Code Display Loop. Press END key to terminate.\n");
// loop until the END key or an error (which will clear ps2_kbd_ok)
while(ps2_kbd_ok == 1){
sc = ps2_scan();
if(sc){
// make sure we have a valid code
// if not we just ignore it
if (sc <= LAST_SCAN_CODE) {
printf("Raw Keypress = 0x%02x, ", sc);
printf("Converted Keypress = ");
// print a leading CTL- or ALT- based on the flags
if(ps2_ctl_flag) printf("CTL-");
if(ps2_alt_flag) printf("ALT-");
// check the state of caps and shift to get the
// right array
if(ps2_shift_flag) {
c = ps2_scan_code[sc][1];
}
else if(ps2_led_flag & PS2_KBD_CMD_LED_CAPS){
c = ps2_scan_code[sc][2];
}
else {
c = ps2_scan_code[sc][0];
}
// only print it if it is printable
if ((c < 0x7f) && (c > 0x1f)) printf("%c\n", c);
else printf("\n");
} // if c <= LAST_SCAN_CODE
} // if ps2_scan
if(c == KEY_END) break;
} // while
return 0;
}
//--------------------------------------------------------------------------
// End of ps2_kbd.c
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -