一个操作系统的实现(7)


输入输出系统

键盘中断处理程序

关键代码分析:

键盘中断处理程序

PUBLIC void keyboard_hanlder(int irq)
{
   disp_str("str");
}

打开键盘中断

PUBLIC void init_keyboard()
{
   put_irq_handler(KEYBOARD_IRQ, keyboard_handler);/*设定键盘中断处理程序*/
   enable_irq(KEYBPARD_IRQ);/*开启键盘中断*/
}

调用 init_keyboard

PUBLIC int kerbel_main()
{
...
   init_keyboard();
...
}

运行结果:

打印扫描码

键盘中断

PUBLIC void keyboard_handler(int irq)
{
	/* disp_str("*"); */
	u8 scan_code = in_byte(0x60);
	disp_int(scan_code);
}

运行结果:

获取并打印扫描码

扫描码解析数组

其中每3个值一组(MAP_COLs被定义成3),分别是单独按某键、Shift+某键和有OxEO前缀的扫描码对应的字符。Esc、 Enter等被定义成了宏,宏的具体数值无所谓,只要不会造成冲突和混淆,让操作系统认识就可以。

u32 keymap[NR_SCAN_CODES * MAP_COLS] = {
/* scan-code !Shift Shift E0 XX */
/* ==================================================================== */
/* 0x00 - none */ 0, 0, 0,
/* 0x01 - ESC */ ESC, ESC, 0,
/* 0x02 - '1' */ '1', '!', 0,
/* 0x03 - '2' */ '2', '@', 0,
/* 0x04 - '3' */ '3', '#', 0,
/* 0x05 - '4' */ '4', '$', 0,
/* 0x06 - '5' */ '5', '%', 0,
/* 0x07 - '6' */ '6', '^', 0,
/* 0x08 - '7' */ '7', '&', 0,
/* 0x09 - '8' */ '8', '*', 0,
/* 0x0A - '9' */ '9', '(', 0,
/* 0x0B - '0' */ '0', ')', 0,
/* 0x0C - '-' */ '-', '_', 0,
/* 0x0D - '=' */ '=', '+', 0,
/* 0x0E - BS */ BACKSPACE, BACKSPACE, 0,
/* 0x0F - TAB */ TAB, TAB, 0,
/* 0x10 - 'q' */ 'q', 'Q', 0,
/* 0x11 - 'w' */ 'w', 'W', 0,
/* 0x12 - 'e' */ 'e', 'E', 0,
/* 0x13 - 'r' */ 'r', 'R', 0,
/* 0x14 - 't' */ 't', 'T', 0,
/* 0x15 - 'y' */ 'y', 'Y', 0,
/* 0x16 - 'u' */ 'u', 'U', 0,
/* 0x17 - 'i' */ 'i', 'I', 0,
/* 0x18 - 'o' */ 'o', 'O', 0,
/* 0x19 - 'p' */ 'p', 'P', 0,
/* 0x1A - '[' */ '[', '{', 0,
/* 0x1B - ']' */ ']', '}', 0,
/* 0x1C - CR/LF */ ENTER, ENTER, PAD_ENTER,
/* 0x1D - l. Ctrl */ CTRL_L, CTRL_L, CTRL_R,
/* 0x1E - 'a' */ 'a', 'A', 0,
/* 0x1F - 's' */ 's', 'S', 0,
/* 0x20 - 'd' */ 'd', 'D', 0,
/* 0x21 - 'f' */ 'f', 'F', 0,
/* 0x22 - 'g' */ 'g', 'G', 0,
/* 0x23 - 'h' */ 'h', 'H', 0,
/* 0x24 - 'j' */ 'j', 'J', 0,
/* 0x25 - 'k' */ 'k', 'K', 0,
/* 0x26 - 'l' */ 'l', 'L', 0,
/* 0x27 - ';' */ ';', ':', 0,
/* 0x28 - '\'' */ '\'', '"', 0,
/* 0x29 - '`' */ '`', '~', 0,
/* 0x2A - l. SHIFT */ SHIFT_L, SHIFT_L, 0,
/* 0x2B - '\' */ '\\', '|', 0,
/* 0x2C - 'z' */ 'z', 'Z', 0,
/* 0x2D - 'x' */ 'x', 'X', 0,
/* 0x2E - 'c' */ 'c', 'C', 0,
/* 0x2F - 'v' */ 'v', 'V', 0,
/* 0x30 - 'b' */ 'b', 'B', 0,
/* 0x31 - 'n' */ 'n', 'N', 0,
/* 0x32 - 'm' */ 'm', 'M', 0,
/* 0x33 - ',' */ ',', '<', 0,
/* 0x34 - '.' */ '.', '>', 0,
/* 0x35 - '/' */ '/', '?', PAD_SLASH,
/* 0x36 - r. SHIFT */ SHIFT_R, SHIFT_R, 0,
/* 0x37 - '*' */ '*', '*',     0,
/* 0x38 - ALT */ ALT_L, ALT_L,   ALT_R,
/* 0x39 - ' ' */ ' ', ' ', 0,
/* 0x3A - CapsLock */ CAPS_LOCK, CAPS_LOCK, 0,
/* 0x3B - F1 */ F1, F1, 0,
/* 0x3C - F2 */ F2, F2, 0,
/* 0x3D - F3 */ F3, F3, 0,
/* 0x3E - F4 */ F4, F4, 0,
/* 0x3F - F5 */ F5, F5, 0,
/* 0x40 - F6 */ F6, F6, 0,
/* 0x41 - F7 */ F7, F7, 0,
/* 0x42 - F8 */ F8, F8, 0,
/* 0x43 - F9 */ F9, F9, 0,
/* 0x44 - F10 */ F10, F10, 0,
/* 0x45 - NumLock */ NUM_LOCK, NUM_LOCK, 0,
/* 0x46 - ScrLock */ SCROLL_LOCK, SCROLL_LOCK, 0,
/* 0x47 - Home */ PAD_HOME, '7', HOME,
/* 0x48 - CurUp */ PAD_UP, '8', UP,
/* 0x49 - PgUp */ PAD_PAGEUP, '9', PAGEUP,
/* 0x4A - '-' */ PAD_MINUS, '-', 0,
/* 0x4B - Left */ PAD_LEFT, '4', LEFT,
/* 0x4C - MID */ PAD_MID, '5', 0,
/* 0x4D - Right */ PAD_RIGHT, '6', RIGHT,
/* 0x4E - '+' */ PAD_PLUS, '+', 0,
/* 0x4F - End */ PAD_END, '1', END,
/* 0x50 - Down */ PAD_DOWN, '2', DOWN,
/* 0x51 - PgDown */ PAD_PAGEDOWN, '3', PAGEDOWN,
/* 0x52 - Insert */ PAD_INS, '0', INSERT,
/* 0x53 - Delete */ PAD_DOT, '.', DELETE,
/* 0x54 - Enter */ 0, 0, 0,
/* 0x55 - ??? */ 0, 0, 0,
/* 0x56 - ??? */ 0, 0, 0,
/* 0x57 - F11 */ F11, F11, 0,
/* 0x58 - F12 */ F12, F12, 0,
/* 0x59 - ??? */ 0, 0, 0,
/* 0x5A - ??? */ 0, 0, 0,
/* 0x5B - ??? */ 0, 0, GUI_L,
/* 0x5C - ??? */ 0, 0, GUI_R,
/* 0x5D - ??? */ 0, 0, APPS,
/* 0x5E - ??? */ 0, 0, 0,
...
/* 0x7F - ??? */ 0, 0, 0
};

键盘缓冲区

/* Keyboard structure, 1 per console. */
typedef struct s_kb {
	char* p_head; /* 指向缓冲区中下一个空闲位置 */
	char* p_tail; /* 指向键盘任务应处理的字节 */
	int count; /* 缓冲区中共有多少字节 */
	char buf[KB_IN_BYTES]; /* 缓冲区 */
}KB_INPUT;

修改后的keyboard_handler

PRIVATE KB_INPUT kb_in;
/*keyboard_handler*/
PUBLIC void keyboard_handler(int irq){
	u8 scan_code = in_byte(KB_DATA);
	if (kb_in.count < KB_IN_BYTES) {
		*(kb_in.p_head) = scan_code;
		kb_in.p_head++;
		if (kb_in.p_head == kb_in.buf + KB_IN_BYTES) {
			kb_in.p_head = kb_in.buf;
		}
		kb_in.count++;
	}
}

修改后的init_keyboard

PUBLIC void init_keyboard()
{
	kb_in.count = 0;
	kb_in.p_head = kb_in.p_tail = kb_in.buf;
	put_irq_handler(KEYBOARD_IRQ, keyboard_handler);/*设定键盘中断处理程序*/
	enable_irq(KEYBOARD_IRQ);                       /*开键盘中断*/
}

键盘读取函数keyboard_read()

PUBLIC void keyboard_read()
{
	u8 scan_code;
	if(kb_in.count > 0){
	disable_int();
	scan_code = *(kb_in.p_tail);
	kb_in.p_tail++;
	if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES) {
		kb_in.p_tail = kb_in.buf;
	}
	kb_in.count--;
	enable_int();
	disp_int(scan_code);
}

运行结果:

打印字符

关键代码分析:

解析扫描码

PUBLIC void keyboard_read()
{
	u8 scan_code;
	char output[2];
	int make; /* TRUE: make;  FALSE: break. */
	memset(output, 0, 2);
	if(kb_in.count > 0){
		disable_int();
		scan_code = *(kb_in.p_tail);
		kb_in.p_tail++;
		if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES) {
			kb_in.p_tail = kb_in.buf;
		}
		kb_in.count--;
		enable_int();
		/* 下面开始解析扫描码 */
		if (scan_code == 0xE1) {
		/* 暂时不做任何操作 */
		}
		else if (scan_code == 0xE0) {
		/* 暂时不做任何操作 */
		}else { /* 下面处理可打印字符 */
			/* 首先判断Make Code 还是 Break Code */
			make = (scan_code & FLAG_BREAK ? FALSE : TRUE);
			/* 如果是Make Code 就打印,是 Break Code 则不做处理 */
			if(make) {
				output[0] = keymap[(scan_code&0x7F)*MAP_COLS];
				disp_str(output);
			}
		}
	/* disp_int(scan_code); */
	}
}

运行结果:


文章作者: Aiaa
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Aiaa !
  目录