kern/console.c:键盘码映射

/*早期的键盘实际上是一种5pin的键盘,称作AT键盘,是1984年IBM PC的标准键盘。在1987年IBM进行了改进,从而变成了现在的PS/2键盘。
当按下一个键或释放一个键,键盘都会发送键盘扫描码到主机。比如按下A,键盘就会发送0x1C到主机。如果持续按A,当经过一个给定时间后,就会发送0x1C到主机。当键盘被释放,键盘会发送0xF0加键码到主机,告诉主机键盘哪个键被释放。当再次按下A,键盘就会再次发送0x1C到主机。键盘的每一个键都有一个特定的键码,无论SHIFT、Num Lock、Caps Lock、Scroll Lock键是否被按下,键盘总是发送同样的键码,主机的键盘BIOS负责区分SHIFT、Num Lock、Caps Lock、Scroll Lock键的状态。键盘有101个键,而PS/2接口只有8比特。因此,并不是所有的键都只有一个字节的键码。扩展键盘中有一些键的键码是双字节的,以 E0开头,比如向左键为E04B。有些键的扫描码非常夸张,比如Pause Brk键的键码为E11D45
*/
/*
PS/2接口只有8比特,单字节最多能表示256个值,每个键被按下和被释放均需有不同的值表示,所以256个最多表示128个按键,为了区分和便于记忆,键被释放时的码值=0x80+键被按下时的码值,0和0x80没有被用作键值,最早的键盘按键较少,一个字节够用,随着扩展键的引入,单字节键值显得不够用了,就得使用多字节(2字节居多),以双字节为被按下键值=E0后面加一个字节xx,那么被释放时键值=E0后面加(0x80+xx)
比如:
a 的被按下键值为1E,那么被释放时键值为9E
HOME 的被按下键值为0E47,被释放时键值为0EC7
Pause Brk键的被按下键码为E11D45,被释放时的键码为E19DC5

*/

/***** Keyboard input code *****/

#define NO 0

#define SHIFT (1<<0)
#define CTL (1<<1)
#define ALT (1<<2)

#define CAPSLOCK (1<<3)
#define NUMLOCK (1<<4)
#define SCROLLLOCK (1<<5)

#define E0ESC (1<<6)


static uint8_t shiftcode[256] =
{
[0x1D] CTL, //左Ctrl, 1D

[0x2A] SHIFT, //左shift 2A

[0x36] SHIFT, //右shift 36

[0x38] ALT, //左alt 38

[0x9D] CTL, //右Ctrl E01D

[0xB8] ALT //右alt E038

};

static uint8_t togglecode[256] =
{
[0x3A] CAPSLOCK, // 3A

[0x45] NUMLOCK, // 45

[0x46] SCROLLLOCK // 46

};

// 按键码对应字符的asiic码(没有按下shift键),如 0x2 => '1'

static uint8_t normalmap[256] =
{
NO, 0x1B, '1', '2', '3', '4', '5', '6', // 0x00

'7', '8', '9', '0', '-', '=', '\b', '\t',
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', // 0x10

'o', 'p', '[', ']', '\n', NO, 'a', 's',
'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', // 0x20

'\'', '`', NO, '\\', 'z', 'x', 'c', 'v',
'b', 'n', 'm', ',', '.', '/', NO, '*', // 0x30

NO, ' ', NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO, NO, '7', // 0x40

'8', '9', '-', '4', '5', '6', '+', '1',
'2', '3', '0', '.', NO, NO, NO, NO, // 0x50

[0xC7] KEY_HOME, [0x9C] '\n' /*KP_Enter*/,
[0xB5] '/' /*KP_Div*/, [0xC8] KEY_UP,
[0xC9] KEY_PGUP, [0xCB] KEY_LF,
[0xCD] KEY_RT, [0xCF] KEY_END,
[0xD0] KEY_DN, [0xD1] KEY_PGDN,
[0xD2] KEY_INS, [0xD3] KEY_DEL
};

// 当按下shift键时,按键码对应字符的asiic码,如 0x2 => '!'

static uint8_t shiftmap[256] =
{
NO, 033, '!', '@', '#', '$', '%', '^', // 0x00

'&', '*', '(', ')', '_', '+', '\b', '\t',
'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', // 0x10

'O', 'P', '{', '}', '\n', NO, 'A', 'S',
'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', // 0x20

'"', '~', NO, '|', 'Z', 'X', 'C', 'V',
'B', 'N', 'M', '<', '>', '?', NO, '*', // 0x30

NO, ' ', NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO, NO, '7', // 0x40

'8', '9', '-', '4', '5', '6', '+', '1',
'2', '3', '0', '.', NO, NO, NO, NO, // 0x50

[0xC7] KEY_HOME, [0x9C] '\n' /*KP_Enter*/,
[0xB5] '/' /*KP_Div*/, [0xC8] KEY_UP,
[0xC9] KEY_PGUP, [0xCB] KEY_LF,
[0xCD] KEY_RT, [0xCF] KEY_END,
[0xD0] KEY_DN, [0xD1] KEY_PGDN,
[0xD2] KEY_INS, [0xD3] KEY_DEL
};

#define C(x) (x - '@')

static uint8_t ctlmap[256] =
{
NO, NO, NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO, NO, NO,
C('Q'), C('W'), C('E'), C('R'), C('T'), C('Y'), C('U'), C('I'),
C('O'), C('P'), NO, NO, '\r', NO, C('A'), C('S'),
C('D'), C('F'), C('G'), C('H'), C('J'), C('K'), C('L'), NO,
NO, NO, NO, C('\\'), C('Z'), C('X'), C('C'), C('V'),
C('B'), C('N'), C('M'), NO, NO, C('/'), NO, NO,
[0x97] KEY_HOME,
[0xB5] C('/'), [0xC8] KEY_UP,
[0xC9] KEY_PGUP, [0xCB] KEY_LF,
[0xCD] KEY_RT, [0xCF] KEY_END,
[0xD0] KEY_DN, [0xD1] KEY_PGDN,
[0xD2] KEY_INS, [0xD3] KEY_DEL
};

static uint8_t *charcode[4] = {
normalmap,
shiftmap,
ctlmap,
ctlmap

};




通常我们的很多程序都是一个while循环, 想在按下某个按键时退出.如何检测这个键按下?
通常有两种方式来做
一 利用阻塞函数来做.
利用阻塞函数检测按键, 又不想让主线程阻塞, 就可以另开一个线程,在线程里面检测按键是否按下. 好像老吉在linux下的版本
就是这样实现的. 通过一个全局变量和主线程通信.

二 利用非阻塞函数来做.
版本一:


/* KBHIT.C: This program loops until the user
* presses a key. If _kbhit returns nonzero, a
* keystroke is waiting in the buffer. The program
* can call _getch or _getche to get the keystroke.
*/
//
#include <conio.h>
#include <stdio.h>
void main( void )
{
while( 1 )
{
// :当按下 y 时退出
if ( _kbhit() && 'y'== _getch() )
{
return;
}
}
}
版本二:

// crt_getch.c
// compile with: /c
// This program reads characters from
// the keyboard until it receives a 'Y' or 'y'.
#include <conio.h>
#include <ctype.h>
int main( void )
{
int ch;
_cputs( "Type 'Y' when finished typing keys: " );
do
{
ch = _getch();
ch = toupper( ch );
} while( ch != 'Y' );
_putch( ch );
_putch( '\r' ); // Carriage return
_putch( '\n' ); // Line feed
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值