⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kbd.c

📁 自己从头开始开发操作系统的几个实例
💻 C
字号:
/*============================================================================
KEYBOARD ROUTINES

EXPORTS:
void keyboard_irq(void);
void init_keyboard(void);
============================================================================*/
#include <conio.h> /* KEY_nnn */
#include <x86.h> /* outportb(), inportb() */
#include "_krnl.h" /* MAX_VC */

/* IMPORTS
from VIDEO.C */
extern console_t _vc[];

void select_vc(unsigned which_vc);
void putch(unsigned c);

/* from MAIN.C */
void kprintf(const char *fmt, ...);

/* "raw" set 1 scancodes from PC keyboard. Keyboard info here:
http://www.execpc.com/~geezer/osd/kbd */
#define	RAW1_LEFT_CTRL		0x1D
#define	RAW1_RIGHT_CTRL		0x1D	/* same as left */
#define	RAW1_LEFT_SHIFT		0x2A
#define	RAW1_RIGHT_SHIFT	0x36
#define	RAW1_LEFT_ALT		0x38
#define	RAW1_RIGHT_ALT		0x38	/* same as left */
#define	RAW1_CAPS_LOCK		0x3A
#define	RAW1_F1			0x3B
#define	RAW1_F2			0x3C
#define	RAW1_F3			0x3D
#define	RAW1_F4			0x3E
#define	RAW1_F5			0x3F
#define	RAW1_F6			0x40
#define	RAW1_F7			0x41
#define	RAW1_F8			0x42
#define	RAW1_F9			0x43
#define	RAW1_F10		0x44
#define	RAW1_NUM_LOCK		0x45
#define	RAW1_SCROLL_LOCK	0x46
#define	RAW1_F11		0x57
#define	RAW1_F12		0x58

#define	KBD_BUF_SIZE		64
/*****************************************************************************
*****************************************************************************/
static void reboot(void)
{
	unsigned temp;

	disable();
/* flush the keyboard controller */
	do
	{
		temp = inportb(0x64);
		if((temp & 0x01) != 0)
		{
			(void)inportb(0x60);
			continue;
		}
	} while((temp & 0x02) != 0);
/* pulse the CPU reset line */
	outportb(0x64, 0xFE);
/* ...and if that didn't work, just halt */
	while(1)
		/* nothing */;
}
/*****************************************************************************
*****************************************************************************/
static void write_kbd(unsigned adr, unsigned data)
{
	unsigned long timeout;
	unsigned stat;

/* Linux code didn't have a timeout here... */
	for(timeout = 500000L; timeout != 0; timeout--)
	{
		stat = inportb(0x64);
/* loop until 8042 input buffer empty */
		if((stat & 0x02) == 0)
			break;
	}
	if(timeout != 0)
		outportb(adr, data);
}
/*****************************************************************************
*****************************************************************************/
static unsigned convert(unsigned key)
{
	static const unsigned char set1_map[] =
	{
/* 00 */0,	0x1B,	'1',	'2',	'3',	'4',	'5',	'6',
/* 08 */'7',	'8',	'9',	'0',	'-',	'=',	'\b',	'\t',
/* 10 */'q',	'w',	'e',	'r',	't',	'y',	'u',	'i',
/* 1Dh is left Ctrl */
/* 18 */'o',	'p',	'[',	']',	'\n',	0,	'a',	's',
/* 20 */'d',	'f',	'g',	'h',	'j',	'k',	'l',	';',
/* 2Ah is left Shift */
/* 28 */'\'',	'`',	0,	'\\',	'z',	'x',	'c',	'v',
/* 36h is right Shift */
/* 30 */'b',	'n',	'm',	',',	'.',	'/',	0,	0,
/* 38h is left Alt, 3Ah is Caps Lock */
/* 38 */0,	' ',	0,	KEY_F1,	KEY_F2,	KEY_F3,	KEY_F4,	KEY_F5,
/* 45h is Num Lock, 46h is Scroll Lock */
/* 40 */KEY_F6,	KEY_F7,	KEY_F8,	KEY_F9,	KEY_F10,0,	0,	KEY_HOME,
/* 48 */KEY_UP,	KEY_PGUP,'-',	KEY_LFT,'5',	KEY_RT,	'+',	KEY_END,
/* 50 */KEY_DN,	KEY_PGDN,KEY_INS,KEY_DEL,0,	0,	0,	KEY_F11,
/* 58 */KEY_F12
	};
	static unsigned short kbd_status, saw_break_code;
/**/
	unsigned short temp;

/* check for break key (i.e. a key is released) */
	if(key >= 0x80)
	{
		saw_break_code = 1;
		key &= 0x7F;
	}
/* the only break codes we're interested in are Shift, Ctrl, Alt */
	if(saw_break_code)
	{
		if(key == RAW1_LEFT_ALT || key == RAW1_RIGHT_ALT)
			kbd_status &= ~KBD_META_ALT;
		else if(key == RAW1_LEFT_CTRL || key == RAW1_RIGHT_CTRL)
			kbd_status &= ~KBD_META_CTRL;
		else if(key == RAW1_LEFT_SHIFT || key == RAW1_RIGHT_SHIFT)
			kbd_status &= ~KBD_META_SHIFT;
		saw_break_code = 0;
		return 0;
	}
/* it's a make key: check the "meta" keys, as above */
	if(key == RAW1_LEFT_ALT || key == RAW1_RIGHT_ALT)
	{
		kbd_status |= KBD_META_ALT;
		return 0;
	}
	if(key == RAW1_LEFT_CTRL || key == RAW1_RIGHT_CTRL)
	{
		kbd_status |= KBD_META_CTRL;
		return 0;
	}
	if(key == RAW1_LEFT_SHIFT || key == RAW1_RIGHT_SHIFT)
	{
		kbd_status |= KBD_META_SHIFT;
		return 0;
	}
/* Scroll Lock, Num Lock, and Caps Lock set the LEDs. These keys
have on-off (toggle or XOR) action, instead of momentary action */
	if(key == RAW1_SCROLL_LOCK)
	{
		kbd_status ^= KBD_META_SCRL;
		goto LEDS;
	}
	if(key == RAW1_NUM_LOCK)
	{
		kbd_status ^= KBD_META_NUM;
		goto LEDS;
	}
	if(key == RAW1_CAPS_LOCK)
	{
		kbd_status ^= KBD_META_CAPS;
LEDS:		write_kbd(0x60, 0xED);	/* "set LEDs" command */
		temp = 0;
		if(kbd_status & KBD_META_SCRL)
			temp |= 1;
		if(kbd_status & KBD_META_NUM)
			temp |= 2;
		if(kbd_status & KBD_META_CAPS)
			temp |= 4;
		write_kbd(0x60, temp);	/* bottom 3 bits set LEDs */
		return 0;
	}
/* ignore invalid scan codes */
	if(key >= sizeof(set1_map) / sizeof(set1_map[0]))
		return 0;
/* convert raw scancode in key to unshifted ASCII in temp */
	temp = set1_map[key];
/* defective keyboard? non-US keyboard? more than 104 keys? */
	if(temp == 0)
		return temp;
/* handle the three-finger salute */
	if((kbd_status & KBD_META_CTRL) && (kbd_status & KBD_META_ALT) &&
		(temp == KEY_DEL))
	{
		kprintf("\n""\x1B[42;37;1m""*** rebooting!");
		reboot();
	}
/* I really don't know what to do yet with Alt, Ctrl, etc. -- punt */
	return temp;
}
/*****************************************************************************
*****************************************************************************/
void keyboard_irq(void)
{
	unsigned key, i;

/* get scancode from port 0x60 */
	key = inportb(0x60);
/* if it's F1, F2 etc. switch to the appropriate virtual console */
	switch(key)
	{
	case RAW1_F1:
		i = 0;
		goto SWITCH_VC;
	case RAW1_F2:
		i = 1;
		goto SWITCH_VC;
	case RAW1_F3:
		i = 2;
		goto SWITCH_VC;
	case RAW1_F4:
		i = 3;
		goto SWITCH_VC;
	case RAW1_F5:
		i = 4;
		goto SWITCH_VC;
	case RAW1_F6:
		i = 5;
		goto SWITCH_VC;
	case RAW1_F7:
		i = 6;
		goto SWITCH_VC;
	case RAW1_F8:
		i = 7;
		goto SWITCH_VC;
	case RAW1_F9:
		i = 8;
		goto SWITCH_VC;
	case RAW1_F10:
		i = 9;
		goto SWITCH_VC;
	case RAW1_F11:
		i = 10;
		goto SWITCH_VC;
	case RAW1_F12:
		i = 11;
SWITCH_VC:
		select_vc(i);
		break;
	default:
		i = convert(key);
		if(i != 0)
			putch(i);
		break;
	}
/* reset hardware interrupt at 8259 chip */
	outportb(0x20, 0x20);
}
/*****************************************************************************
*****************************************************************************/
void init_keyboard(void)
{
	static unsigned char buffers[KBD_BUF_SIZE * MAX_VC];
/**/
	int i;

	for(i = 0; i < MAX_VC; i++)
	{
		_vc[i].keystrokes.data = buffers + KBD_BUF_SIZE * i;
		_vc[i].keystrokes.size = KBD_BUF_SIZE;
	}
	kprintf("init_kbd: %u buffers, %u bytes each\n",
		MAX_VC, KBD_BUF_SIZE);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -