键盘驱动程序设计(下)

问题

如何判断键盘是属于数字小键盘?数字小键盘上的按键有什么特殊之处?

数字小键盘键位判断

 因为数字小键盘上的键位功能并不唯一,所以需要配合完整的扫描码进行判断。

编码前的考虑

Shift 键:同一个键位可能表示不同功能

Caps Lock 键:默认字母大小写控制

Num Lock 键:小数字键盘启动控制

数字小键盘的特殊之处

默认情况下,Num Lock 处于关闭状态 

默认情况下按键不代表特殊字符,代表特殊功能

Num Lock 打开后,可使用 Shift 控制键位意义

数字按键键位编码

普通键位编码

键盘键位编码

keyboard.h


#ifndef KEYBOARD_H
#define KEYBOARD_H

#include "type.h"

#define Dim(a)    (sizeof((a)) / sizeof((*a)))

void PutScanCode(byte sc);
uint FetchKeyCode();

#endif

keyboard.c


#include "keyboard.h"
#include "screen.h"
#include "utility.h"

typedef struct
{
	byte ascii1;   // no shift code
    byte ascii2;   // shift code
    byte scode;    // scan code
    byte kcode;    // key code
} KeyCode;

enum
{
	KeyRelease = 0,
	KeyPress = 0x1000000
};

static const KeyCode gKeyMap[] = 
{
/* 0x00 - none      */ {  0,        0,        0,         0   },
/* 0x01 - ESC       */ {  0,        0,       0x01,      0x1B },
/* 0x02 - '1'       */ { '1',      '!',      0x02,      0x31 },
/* 0x03 - '2'       */ { '2',      '@',      0x03,      0x32 },
/* 0x04 - '3'       */ { '3',      '#',      0x04,      0x33 },
/* 0x05 - '4'       */ { '4',      '$',      0x05,      0x34 },
/* 0x06 - '5'       */ { '5',      '%',      0x06,      0x35 },
/* 0x07 - '6'       */ { '6',      '^',      0x07,      0x36 },
/* 0x08 - '7'       */ { '7',      '&',      0x08,      0x37 },
/* 0x09 - '8'       */ { '8',      '*',      0x09,      0x38 },
/* 0x0A - '9'       */ { '9',      '(',      0x0A,      0x39 },
/* 0x0B - '0'       */ { '0',      ')',      0x0B,      0x30 },
/* 0x0C - '-'       */ { '-',      '_',      0x0C,      0xBD },
/* 0x0D - '='       */ { '=',      '+',      0x0D,      0xBB },
/* 0x0E - BS        */ {  0,        0,       0x0E,      0x08 },
/* 0x0F - TAB       */ {  0,        0,       0x0F,      0x09 },
/* 0x10 - 'q'       */ { 'q',      'Q',      0x10,      0x51 },
/* 0x11 - 'w'       */ { 'w',      'W',      0x11,      0x57 },
/* 0x12 - 'e'       */ { 'e',      'E',      0x12,      0x45 },
/* 0x13 - 'r'       */ { 'r',      'R',      0x13,      0x52 },
/* 0x14 - 't'       */ { 't',      'T',      0x14,      0x54 },
/* 0x15 - 'y'       */ { 'y',      'Y',      0x15,      0x59 },
/* 0x16 - 'u'       */ { 'u',      'U',      0x16,      0x55 },
/* 0x17 - 'i'       */ { 'i',      'I',      0x17,      0x49 },
/* 0x18 - 'o'       */ { 'o',      'O',      0x18,      0x4F },
/* 0x19 - 'p'       */ { 'p',      'P',      0x19,      0x50 },
/* 0x1A - '['       */ { '[',      '{',      0x1A,      0xDB },
/* 0x1B - ']'       */ { ']',      '}',      0x1B,      0xDD },
/* 0x1C - CR/LF     */ {  0,        0,       0x1C,      0x0D },
/* 0x1D - l. Ctrl   */ {  0,        0,       0x1D,      0x11 },
/* 0x1E - 'a'       */ { 'a',      'A',      0x1E,      0x41 },
/* 0x1F - 's'       */ { 's',      'S',      0x1F,      0x53 },
/* 0x20 - 'd'       */ { 'd',      'D',      0x20,      0x44 },
/* 0x21 - 'f'       */ { 'f',      'F',      0x21,      0x46 },
/* 0x22 - 'g'       */ { 'g',      'G',      0x22,      0x47 },
/* 0x23 - 'h'       */ { 'h',      'H',      0x23,      0x48 },
/* 0x24 - 'j'       */ { 'j',      'J',      0x24,      0x4A },
/* 0x25 - 'k'       */ { 'k',      'K',      0x25,      0x4B },
/* 0x26 - 'l'       */ { 'l',      'L',      0x26,      0x4C },
/* 0x27 - ';'       */ { ';',      ':',      0x27,      0xBA },
/* 0x28 - '\''      */ { '\'',     '\"',     0x28,      0xDE },
/* 0x29 - '`'       */ { '`',      '~',      0x29,      0xC0 },
/* 0x2A - l. SHIFT  */ {  0,        0,       0x2A,      0x10 },
/* 0x2B - '\'       */ { '\\',     '|',      0x2B,      0xDC },
/* 0x2C - 'z'       */ { 'z',      'Z',      0x2C,      0x5A },
/* 0x2D - 'x'       */ { 'x',      'X',      0x2D,      0x58 },
/* 0x2E - 'c'       */ { 'c',      'C',      0x2E,      0x43 },
/* 0x2F - 'v'       */ { 'v',      'V',      0x2F,      0x56 },
/* 0x30 - 'b'       */ { 'b',      'B',      0x30,      0x42 },
/* 0x31 - 'n'       */ { 'n',      'N',      0x31,      0x4E },
/* 0x32 - 'm'       */ { 'm',      'M',      0x32,      0x4D },
/* 0x33 - ','       */ { ',',      '<',      0x33,      0xBC },
/* 0x34 - '.'       */ { '.',      '>',      0x34,      0xBE },
/* 0x35 - '/'       */ { '/',      '?',      0x35,      0xBF },
/* 0x36 - r. SHIFT  */ {  0,        0,       0x36,      0x10 },
/* 0x37 - '*'       */ { '*',      '*',      0x37,      0x6A },
/* 0x38 - ALT       */ {  0,        0,       0x38,      0x12 },
/* 0x39 - ' '       */ { ' ',      ' ',      0x39,      0x20 },
/* 0x3A - CapsLock  */ {  0,        0,       0x3A,      0x14 },
/* 0x3B - F1        */ {  0,        0,       0x3B,      0x70 },
/* 0x3C - F2        */ {  0,        0,       0x3C,      0x71 },
/* 0x3D - F3        */ {  0,        0,       0x3D,      0x72 },
/* 0x3E - F4        */ {  0,        0,       0x3E,      0x73 },
/* 0x3F - F5        */ {  0,        0,       0x3F,      0x74 },
/* 0x40 - F6        */ {  0,        0,       0x40,      0x75 },
/* 0x41 - F7        */ {  0,        0,       0x41,      0x76 },
/* 0x42 - F8        */ {  0,        0,       0x42,      0x77 },
/* 0x43 - F9        */ {  0,        0,       0x43,      0x78 },
/* 0x44 - F10       */ {  0,        0,       0x44,      0x79 },
/* 0x45 - NumLock   */ {  0,        0,       0x45,      0x90 },
/* 0x46 - ScrLock   */ {  0,        0,       0x46,      0x91 },
/* 0x47 - Home      */ {  0,        0,       0x47,      0x24 },
/* 0x48 - Up        */ {  0,        0,       0x48,      0x26 },
/* 0x49 - PgUp      */ {  0,        0,       0x49,      0x21 },
/* 0x4A - '-'       */ {  0,        0,       0x4A,      0x6D },
/* 0x4B - Left      */ {  0,        0,       0x4B,      0x25 },
/* 0x4C - MID       */ {  0,        0,       0x4C,      0x0C },
/* 0x4D - Right     */ {  0,        0,       0x4D,      0x27 },
/* 0x4E - '+'       */ {  0,        0,       0x4E,      0x6B },
/* 0x4F - End       */ {  0,        0,       0x4F,      0x23 },
/* 0x50 - Down      */ {  0,        0,       0x50,      0x28 },
/* 0x51 - PgDown    */ {  0,        0,       0x51,      0x22 },
/* 0x52 - Insert    */ {  0,        0,       0x52,      0x2D },
/* 0x53 - Del       */ {  0,        0,       0x53,      0x2E },
/* 0x54 - Enter     */ {  0,        0,       0x54,      0x0D },
/* 0x55 - ???       */ {  0,        0,        0,         0   },
/* 0x56 - ???       */ {  0,        0,        0,         0   },
/* 0x57 - F11       */ {  0,        0,       0x57,      0x7A },  
/* 0x58 - F12       */ {  0,        0,       0x58,      0x7B },
/* 0x59 - ???       */ {  0,        0,        0,         0   },
/* 0x5A - ???       */ {  0,        0,        0,         0   },
/* 0x5B - Left Win  */ {  0,        0,       0x5B,      0x5B },	
/* 0x5C - Right Win */ {  0,        0,       0x5C,      0x5C },
/* 0x5D - Apps      */ {  0,        0,       0x5D,      0x5D }
};

static uint IsShift(byte sc)
{
	return (sc == 0x2A) || (sc == 0x36);
}

static uint IsCapsLock(byte sc)
{
	return (sc == 0x3A);
}

static uint IsNumLock(byte sc)
{
	return (sc == 0x45);
}

static uint IsNumPadKey(byte sc, byte E0)
{
	static const byte cNumScanCode[]            = {0x52, 0x53, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47, 0x48, 0x49, 0x35, 0x37, 0x4A, 0x4E, 0x1C};  
    static const byte cNumE0[Dim(cNumScanCode)] = {0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,    1   };
    
    uint ret = 0;
    uint i = 0;
    
    for(i = 0; i < Dim(cNumScanCode); i++)
    {
    	byte* pc = AddrOff(cNumScanCode, i);
    	byte* pe = AddrOff(cNumE0, i);
    	
    	if((sc == *pc) && (*pe == E0))
    	{
    		ret = 1;
    		
    		break;
    	}
    }
    
    return ret;
}

static uint MakeNumCode(KeyCode* pkc, int shift, int num)
{
	static const KeyCode cNumKeyMap[] = 
    {
        { '0',       0,       0x52,     0x2D },
        { '.',       0,       0x53,     0x2E },
        { '1',       0,       0x4F,     0x23 },
        { '2',       0,       0x50,     0x28 },
        { '3',       0,       0x51,     0x22 },
        { '4',       0,       0x4B,     0x25 },
        { '5',       0,       0x4C,     0x0C },
        { '6',       0,       0x4D,     0x27 },
        { '7',       0,       0x47,     0x24 },
        { '8',       0,       0x48,     0x26 },
        { '9',       0,       0x49,     0x21 },
        { '/',      '/',      0x35,     0x6F },
        { '*',      '*',      0x37,     0x6A },
        { '-',      '-',      0x4A,     0x6D },
        { '+',      '+',      0x4E,     0x6B },
        {  0,        0,       0x1C,     0x0D },
        {  0,        0,        0,        0   }
    };
    
    uint ret = 0;
    int i = 0;
    KeyCode* nkc = NULL;
    
    for(i = 0; i < Dim(cNumKeyMap); i++)
	{
		KeyCode* tmp = AddrOff(cNumKeyMap, i);
		
		if(tmp->scode == pkc->scode)
		{
			nkc = tmp;
			break;
		}
	}
	
	if(nkc != NULL)
	{
		if(!num)
		{
			ret = (nkc->scode << 16) | (nkc->kcode << 8) | nkc->ascii2;
		}
		else
		{
			if(!shift)
			{
				ret = (nkc->scode << 16) | (nkc->kcode << 8) | nkc->ascii1;
			}
			else
			{
				ret = (nkc->scode << 16) | (nkc->kcode << 8) | nkc->ascii2;
			}
		}
	}
	
	return ret;
}

static uint MakeNormalCode(KeyCode* pkc, int shift, int caps)
{
	uint ret = 0;
	
	if(!caps)
	{
		if(!shift)
		{
			ret = (pkc->scode << 16) | (pkc->kcode << 8) | pkc->ascii1;
		}
		else
		{
			ret = (pkc->scode << 16) | (pkc->kcode << 8) | pkc->ascii2;
		}
	}
	else
	{
		if((pkc->ascii1 >= 'a') && (pkc->ascii1 <= 'z'))
		{
			if(!shift)
			{
				ret = (pkc->scode << 16) | (pkc->kcode << 8) | pkc->ascii2;
			}
			else
			{
				ret = (pkc->scode << 16) | (pkc->kcode << 8) | pkc->ascii1;
			}
		}
		else
		{
			if(!shift)
			{
				ret = (pkc->scode << 16) | (pkc->kcode << 8) | pkc->ascii1;
			}
			else
			{
				ret = (pkc->scode << 16) | (pkc->kcode << 8) | pkc->ascii2;
			}
		}
	}
	
	return ret;
}

static uint MakeCode(KeyCode* pkc, int shift, int caps, int num, int E0)
{
	uint ret = 0;
	
	if(IsNumPadKey(pkc->scode, E0))
	{
		ret = MakeNumCode(pkc, shift, num);
	}
	else
	{
		ret = MakeNormalCode(pkc, shift, caps);
	}
	
	return ret;
}

static uint KeyType(byte sc)
{
	uint ret = KeyPress;
	
	if(sc & 0x80)
	{
		ret = KeyRelease;
	}
	
	return ret;
}

static uint PauseHandler(byte sc)
{
	uint ret = 0;
	
	
	return ret;
}

static uint KeyHandler(byte sc)
{
	uint ret = 0;
	
	static uint cShift = 0;
	static uint cCapsLock = 0;
	static uint cNumLock = 0;
	static uint E0 = 0;
	
	if(sc == 0xE0)
	{
		E0 = 1;
		ret = 1;
	}
	else
	{
		uint pressed = KeyType(sc);
		KeyCode* pkc = NULL;
		
		if(!pressed)
		{
			sc -= 0x80;
		}
		
		pkc = (KeyCode*)AddrOff(gKeyMap, sc);
		
		if(ret = !!pkc->scode)
		{
			uint code = 0;
			
			if(IsShift(sc))
			{
				cShift = pressed;
			}
			else if(IsCapsLock(sc) && pressed)
			{
				cCapsLock = !cCapsLock;
			}
			else if(IsNumLock(sc) && pressed)
			{
				cNumLock = !cNumLock;
			}
			
			code = pressed | MakeCode(pkc, cShift, cCapsLock, cNumLock, E0);
			
			if(pressed)
			{
				PrintChar((char)code);
			}
			
			E0 = 0;
		}
	}
	
	return ret;
}

void PutScanCode(byte sc)
{
	if(PauseHandler(sc))
	{
		/* Pause Key */
	}
	else if(KeyHandler(sc))
	{
		/* Normal Key */
	}
	else
	{
		/* Uknown Key */
	}
}

uint FetchKeyCode()
{
	uint ret = 0;
	
	
	return ret;
}

ihandler.c

void KeyboardHandler()
{
	byte sc = ReadPort(0x60);
	
	// PrintIntHex(sc);
	// PrintString("  ");

	PutScanCode(sc);

	SendEOI(MASTER_EOI_PORT);
}

MakeCode 函数根据按键的区域,对不同区域的按键调用不同的按键编码函数。

我们打印获得 code 的低8位,也就是 ASCII 值。

根据 Shift、Caps Lock 和 Num Lock 的组合,屏幕上打印了相应按键的 ASCII 值。 

思考

内核对按键事件进行编码后,如何处理?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值