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

📄 kbd.c

📁 一个操作系统,用C语言实现开发的,我在一个浙江大学的操作系统实验网站找到.大家学习以下
💻 C
字号:
// Kernel
// Default Keyboard

#include <console.h>
#include <knlcon.h>
#include <knllib.h>
#include <gates.h>
#include <devices.h>

static HDRIVER _this_driver;			// driver handle

static _u32 _keyboard_status;		// shift, ctrl, alt, etc.
static _u32 _status;
static KBDHANDLER _pfnKeyHandler;

// status flags
#define SF_CAPS		0x00010000
#define SF_SCROLL	0x00020000
#define SF_NUM		0x00040000
#define SF_2A		0x00100000

// key maps
static _u32 _default_keys[] =
{
	VK_NULL, VK_ESC, '1', '2', '3', '4', '5', '6',
	'7', '8', '9', '0', '-', '=', VK_BKSP, VK_TAB,
	'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
	'o', 'p', '[', ']', VK_CR, VK_LCTRL, 'a', 's',
	'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
	'\'', '`', VK_LSHIFT, '\\', 'z', 'x', 'c', 'v',
	'b', 'n', 'm', ',', '.', '/', VK_RSHIFT, VKNUMPAD('*'),
	VK_LALT, VK_SP, VK_CAPS, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5,
	VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_NUM, VK_SCROLL, VKNUMPAD('7'),
	VKNUMPAD('8'), VKNUMPAD('9'), VKNUMPAD('-'), VKNUMPAD('4'),
	VKNUMPAD('5'), VKNUMPAD('6'), VKNUMPAD('+'), VKNUMPAD('1'),
	VKNUMPAD('2'), VKNUMPAD('3'), VKNUMPAD('0'), VKNUMPAD('.'),
	VK_NULL, VK_NULL, VK_NULL, VK_F11, VK_F12, VK_NULL, VK_NULL, VK_NULL
};

static _u32 _shift_keys[] =
{
	VK_NULL, VK_ESC, '!', '@', '#', '$', '%', '^',
	'&', '*', '(', ')', '_', '+', VK_BKSP, VK_TAB,
	'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
	'O', 'P', '{', '}', VK_CR, VK_LCTRL, 'A', 'S',
	'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
	'"', '~', VK_LSHIFT, '|', 'Z', 'X', 'C', 'V',
	'B', 'N', 'M', '<', '>', '?', VK_RSHIFT, VKNUMPAD('*'),
	VK_LALT, VK_SP, VK_CAPS, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5,
	VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_NUM, VK_SCROLL, VKNUMPAD(VK_HOME),
	VKNUMPAD(VK_UP), VKNUMPAD(VK_PGDN), VKNUMPAD('-'), VKNUMPAD(VK_LEFT),
	VKNUMPAD('5'), VKNUMPAD(VK_RIGHT), VKNUMPAD('+'), VKNUMPAD(VK_END),
	VKNUMPAD(VK_DOWN), VKNUMPAD(VK_PGDN), VKNUMPAD(VK_INSERT), VKNUMPAD(VK_DELETE),
	VK_NULL, VK_NULL, VK_NULL, VK_F11, VK_F12, VK_NULL, VK_NULL, VK_NULL
};

static void set_leds(void)
{
	asm("jmp set_leds_set\n"
		"kb_wait: pushl %%eax\n"
		"1:	inb $0x64,%%al\n"
		"testb $0x02,%%al\n"
		"jne 1b\n"
		"popl %%eax\n"
		"ret\n"
		"set_leds_set: call kb_wait\n"
		"movb $0xed,%%al\n"
		"outb %%al,$0x60\n"
		"call kb_wait\n"
		"movb %%cl,%%al\n"
		"outb %%al,$0x60\n"::"c"((_keyboard_status>>4)&7)
	);
}

static inline void set_status(_u8 key)
{
	_status = (_status&0xffffff00) | key;
}

static inline _u32 get_cursor_keys(_u8 key)
{
	switch(key)
	{
	case 0x37: return VK_PRTSCR;
	case 0x52: return VK_INSERT;
	case 0x53: return VK_DELETE;
	case 0x47: return VK_HOME;
	case 0x4f: return VK_END;
	case 0x49: return VK_PGUP;
	case 0x51: return VK_PGDN;
	case 0x4b: return VK_LEFT;
	case 0x4d: return VK_RIGHT;
	case 0x48: return VK_UP;
	case 0x50: return VK_DOWN;
	}
	return VK_NULL;
}

void onKBD(_u8 key)
{
	_u32 code = 0;

	SysLock();

	switch((_u8)_status)
	{
	case 0:
		if(key==0xe0 || key==0xe1) set_status(key);
		else	// normal keys
		{
			int size = sizeof(_default_keys)/sizeof(_u32);
			_u32 release = key&0x80 ? VKF_RELEASE : 0;
			key &= 0x7f;
			if(key>=(_u8)size) code = VK_NULL;
			else if(_default_keys[key])
			{
				code = _default_keys[key];
				if(code&VKF_SPECIAL)
				{
					switch(code)
					{
					case VK_LSHIFT:
						if(release) _keyboard_status&=~KS_LSHIFT;
						else _keyboard_status|=KS_LSHIFT;
						break;
					case VK_RSHIFT:
						if(release) _keyboard_status&=~KS_RSHIFT;
						else _keyboard_status|=KS_RSHIFT;
						break;
					case VK_LCTRL:
						if(release) _keyboard_status&=~((_keyboard_status&KS_RCTRL?0:KS_CTRL)|KS_LCTRL);
						else _keyboard_status|=KS_CTRL|KS_LCTRL;
						break;
					case VK_LALT:
						if(release) _keyboard_status&=~((_keyboard_status&KS_RALT?0:KS_ALT)|KS_LALT);
						else _keyboard_status|=KS_ALT|KS_LALT;
						break;
					case VK_CAPS:
						if(_status&SF_CAPS && release) _status&=~SF_CAPS;
						else if(!(_status&SF_CAPS) && !release)
						{ _keyboard_status^=KS_CAPS; _status|=SF_CAPS; set_leds(); }
						else code = VK_NULL;
						break;
					case VK_SCROLL:
						if(_status&SF_SCROLL && release) _status&=~SF_SCROLL;
						else if(!(_status&SF_SCROLL) && !release)
						{ _keyboard_status^=KS_SCROLL; _status|=SF_SCROLL; set_leds(); }
						else code = VK_NULL;
						break;
					case VK_NUM:
						if(_status&SF_NUM && release) _status&=~SF_NUM;
						else if(!(_status&SF_NUM) && !release)
						{ _keyboard_status^=KS_NUM; _status|=SF_NUM; set_leds(); }
						else code = VK_NULL;
						break;
					default: code = VK_NULL;	// keys not supported
					}
				}
				else
				{
					if((code&VKF_NUMPAD &&
						((_keyboard_status&KS_SHIFT && _keyboard_status&KS_NUM) ||	// numpad + shift
						 (!(_keyboard_status&KS_SHIFT) && !(_keyboard_status&KS_NUM))) ) ||
						(!(code&VKF_NUMPAD) && _keyboard_status&KS_SHIFT))
						code = _shift_keys[key];
					if((char)code>='a' && (char)code<='z' &&
						((!(_keyboard_status&KS_CAPS) && _keyboard_status&KS_SHIFT) ||	// shift uncaps
						 (!(_keyboard_status&KS_SHIFT) && _keyboard_status&KS_CAPS)) )
						code = _shift_keys[key];
					else if((char)code>='A' && (char)code<='Z' && _keyboard_status&KS_CAPS)
						code = _default_keys[key];
					code |= key<<8;	// add scan code
				}
			}
			if(code) code|=release;
		}
		break;
	case 0xe0:
		if(key==0x2a) _status|=SF_2A;
		else if(_status&SF_2A && key==0xaa) _status&=~SF_2A;
		else
		{
			_u32 release = key&0x80 ? VKF_RELEASE : 0;
			key&=0x7f;
			code = get_cursor_keys(key);
			if(code) code|=VKF_CURSOR;
			else
			{
				switch(key)
				{
				case 0x35:		// '/' in numpad
					code = VKNUMPAD('/'); break;
				case 0x38:		// right alt
					code = VK_RALT;
					if(release) _keyboard_status&=~((_keyboard_status&KS_LALT?0:KS_ALT)|KS_RALT);
					else _keyboard_status|=KS_ALT|KS_RALT;
					break;
				case 0x1c:		// enter in numpad
					code = VKNUMPAD(VK_CR); break;
				case 0x1d:		// right ctrl
					code = VK_RCTRL;
					if(release) _keyboard_status&=~((_keyboard_status&KS_LCTRL?0:KS_CTRL)|KS_RCTRL);
					else _keyboard_status|=KS_CTRL|KS_RCTRL;
					break;
				case 0x5b:		// left win
					code = VK_LWIN;
					if(release) _keyboard_status&=~KS_LWIN;
					else _keyboard_status|=KS_LWIN;
					break;
				case 0x5c:		// right win
					code = VK_RWIN;
					if(release) _keyboard_status&=~KS_RWIN;
					else _keyboard_status|=KS_RWIN;
					break;
				case 0x5d:		// app
					code = VK_APP; break;
				default: code = VK_NULL;
				}
			}
			if(code) code|=release;
		}
		set_status(0);
		break;
	case 0xe1:
		if(key==0x1d) set_status(0x1d);
		else if(key==0x9d) set_status(0x9d);
		else set_status(0);
		break;
	case 0x1d:
		if(key==0x45) set_status(0x45);
		else set_status(0);
		break;
	case 0x45:
		if(key==0xe1) set_status(0xe1);
		else set_status(0);
		break;
	case 0x9d:
		if(key==0xc5) code = VK_BREAK;
		set_status(0);
	}
	SysUnlock();
	if(code && _pfnKeyHandler) (*_pfnKeyHandler)(code);
}

void irq_kbd(void);

_u32 kbdGetStatus(void)
{
	return _keyboard_status;
}

void kbdSetStatus(_u32 status)
{
	SysLock();
	_keyboard_status = status;
	set_leds();
	SysUnlock();
}

KBDHANDLER kbdGetHandler(void)
{
	return _pfnKeyHandler;
}

void kbdSetHandler(KBDHANDLER pHandler)
{
	SysLock();
	_pfnKeyHandler = pHandler;
	SysUnlock();
}

void InstallKeyboard(void)
{
	_keyboard_status = 0;
	_status = 0;
	_pfnKeyHandler = NULL;
	set_leds();
	SetIRQ(1, (_u32)irq_kbd);
}

static long __syscall ioctrl(HDEVICE hDevice, _u32 cmd, void* in_buf, _u32 in_len, void* out_buf, _u32 out_len, _u32* trans_len)
{
	switch(cmd)
	{
	case DEV_IOCTRL_INITIALIZE: return 0;
	case DEV_IOCTRL_READ: return 0;
	case DEV_IOCTRL_WRITE: return 0;
	}
	return DEVICE_MAKEERR(DEVERR_BADCMD);
}

static long OnLoad(HDRIVER hDrv)
{
	_this_driver = hDrv;
	return 0;
}

static long OnUnload(void)
{
	return 0;
}

static long OnInstallDevices(void)
{
	if(!RegisterDevice(_this_driver, DEV_TYPE_CHAR, 0, 1, "console", ioctrl, 0, 0))
	{
		kprintf("console: device registering failed\n");
		return DEVICE_MAKEERR(DEVERR_INTERNAL);
	}
	InstallKeyboard();
	return 0;
}

long __syscall drvDefaultConsole(_u32 cmd, _u32 param1, _u32 param2)
{
	switch(cmd)
	{
	case DRV_SVC_LOAD: return OnLoad((HDRIVER)param1);
	case DRV_SVC_UNLOAD: return OnUnload();
	case DRV_SVC_INSTALLDEVICES:
		return OnInstallDevices();
	}
	return 0;
}

⌨️ 快捷键说明

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