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

📄 kbd.c

📁 Linux0.01设备驱动程序 最精简的linux代码 适合操作系统入门
💻 C
📖 第 1 页 / 共 2 页
字号:
		/* nothing */;
/* test controller, expect 0x00 if successful */
	DEBUG(printf("\n  controller self-test");)
	Result=_kbdWriteRead(_KBD_CMD_REG, _KBD_CCMD_TEST2, 1,
		(u8 *)"\x00");
	if(Result != 0)
	{	static const char *Line[2]={ "clock", "data" };
		static const char *Stuck[2]={ "low", "high" };

		printf("  *** interface test failed, ");
		Result--;
		if(Result > 3)
			printf("cause unknown\n");
		else printf("%s line stuck %s\n", Line[Result >> 1],
			Stuck[Result & 1]);
BAIL:		crite(Flags);	/* restore previous interrupt mask */
		return(-1); }
/* enable keyboard interface on controller. Controller commands
(_KBD_CCMD_nnn) may return a data byte, but do not return an ACK */
	_kbdWrite(_KBD_CMD_REG, _KBD_CCMD_ENABLE);
/* reset keyboard (selects scancode set 2), expect 0xFA and 0xAA */
	DEBUG(printf("\n  resetting keyboard");)
	Result=_kbdWriteRead(_KBD_DATA_REG, _KBD_KCMD_RESET, 2,
		(u8 *)"\xFA\xAA");
	if(Result != 0)
		goto BAIL;
/* test keyboard, expect 0x55 if successful */
	DEBUG(printf("\n  keyboard self-test");)
	Result=_kbdWriteRead(_KBD_CMD_REG, _KBD_CCMD_TEST1, 1,
		(u8 *)"\x55");
	if(Result != 0)
		goto BAIL;
/* disable keyboard before programming it, expect 0xFA (ACK) */
	DEBUG(printf("\n  disable");)
	Result=_kbdWriteRead(_KBD_DATA_REG, _KBD_KCMD_DIS, 1,
		(u8 *)"\xFA");
	if(Result != 0)
		goto BAIL;
/* disable AT-to-XT keystroke conversion, disable PS/2 mouse,
set SYS bit, and Enable Keyboard Interrupt */
	_kbdWrite(_KBD_CMD_REG, _KBD_CCMD_WRCMDB);
	_kbdWrite(_KBD_DATA_REG, _KBD_CB_INIT);	/* DMS, SYS, EKI */
/* program desired scancode set, expect 0xFA (ACK)... */
	DEBUG(printf("\n  programming scancode set %u", ScanCodeSet);)
	Result=_kbdWriteRead(_KBD_DATA_REG, _KBD_KCMD_SCSET, 1,
		(u8 *)"\xFA");
	if(Result != 0)
		goto BAIL;
/* ...send scancode set value, expect 0xFA (ACK) */
	Result=_kbdWriteRead(_KBD_DATA_REG, ScanCodeSet, 1,
		(u8 *)"\xFA");
	if(Result != 0)
		goto BAIL;
/* make all keys typematic (auto-repeat) and make-break. This may work
only with scancode set 3, I'm not sure. Expect 0xFA (ACK) */
	DEBUG(printf("\n  making all keys typematic and make-break");)
	Result=_kbdWriteRead(_KBD_DATA_REG, _KBD_KCMD_TMB, 1,
		(u8 *)"\xFA");

	// -----------------------------
	//  if(Result != 0)  goto BAIL;

/* set typematic delay as short as possible;
repeat as fast as possible, expect ACK... */
	DEBUG(printf("\n  setting fast typematic mode");)
	Result=_kbdWriteRead(_KBD_DATA_REG, _KBD_KCMD_TYPEM, 1,
		(u8 *)"\xFA");
	
	// ----------------------------
	//if(Result != 0) goto BAIL;

/* ...typematic control byte (0 corresponds to MODE CON RATE=30 DELAY=1),
expect 0xFA (ACK) */
	Result=_kbdWriteRead(_KBD_DATA_REG, 0, 1,
		(u8 *)"\xFA");
	if(Result != 0)
		goto BAIL;
/* enable keyboard, expect 0xFA (ACK) */
	DEBUG(printf("\n  enable");)
	Result=_kbdWriteRead(_KBD_DATA_REG, _KBD_KCMD_EN, 1,
		(u8 *)"\xFA");
	if(Result != 0)
		goto BAIL;
	printf("\n  scancode set 3 driver activated\n");
/* restore previous interrupt mask */
	crite(Flags);
	return(0); }
/*****************************************************************************
	name:	irq1
	action:	IRQ1 (INT 9) interrupt handler (keyboard);
		puts scancode in Keystrokes queue (unless it's full)
*****************************************************************************/
static void interrupt _irq1(__CPPARGS)
{	u8 Code;

	Code=inportb(_KBD_DATA_REG);
	if(inq(&(_Con.Keystrokes), Code) != 0)
		/* full queue, beep or something */;
	outportb(0x20, 0x20); }	/* send EOI to 8259 interrupt controller */
/*****************************************************************************
	name:	my_getch
	action:	waits for keypress, converts raw set 3 scancodes to
		extended ASCII
	returns:extended ASCII value
*****************************************************************************/
int my_getch(console *_Con)
{/* convert raw set 3 scancodes to ASCII, no Shift
A-Z and a-z are in the "wrong" maps (this slightly simplifies the
conversion logic for Ctrl), but we fix that below */
	static const u16 Map[]={
/* 00 */0,	0,	0,	0,	0,	0,	0,	K_F1,
/* 08 */0x1B,	0,	0,	0,	0,	0x09,	'`',	K_F2,
/* 11 is left Ctrl; 12 is left Shift; 14 is CapsLock */
/* 10 */0,	0,	0,	0,	0,	'Q',	'1',	K_F3,
/* 19 is left Alt */
/* 18 */0,	0,	'Z',	'S',	'A',	'W',	'2',	K_F4,
/* 20 */0,	'C',	'X',	'D',	'E',	'4',	'3',	K_F5,
/* 28 */0,	' ',	'V',	'F',	'T',	'R',	'5',	K_F6,
/* 30 */0,	'N',	'B',	'H',	'G',	'Y',	'6',	K_F7,
/* 39 is right Alt */
/* 38 */0,	0,	'M',	'J',	'U',	'7',	'8',	K_F8,
/* 40 */0,	',',	'K',	'I',	'O',	'0',	'9',	K_F9,
/* 48 */0,	'.',	'/',	'L',	';',	'P',	'-',	K_F10,
/* 50 */0,	0,	'\'',	0,	'[',	'=',	K_F11,	K_PRNT,
/* 58 is right Ctrl; 59 is right Shift; 5F is Scroll Lock */
/* 58 */0,	0,	0x0D,	']',	'\\',	0,	K_F12,	0,
/* 60 */K_DN,	K_LFT,	K_PAUSE,K_UP,	K_DEL,	K_END,	0x08,	K_INS,
/* 68 */0,	K_END,	K_RT,	K_LFT,	K_HOME,	K_PGDN,	K_HOME,	K_PGUP,
/* 76 is Num Lock */
/* 70 */K_INS,	K_DEL,	K_DN,	'5',	K_RT,	K_UP,	0,	'/',
/* 78 */0,	0x0D,	K_PGDN,	0,	'+',	K_PGUP,	'*',	0,
/* 80 */0,	0,	0,	0,	'-',	0,	0,	0,
/* 88 */0,	0,	0,	K_LWIN,	K_RWIN,	K_MENU,	0,	0 };
/* convert raw set 3 scancodes to ASCII with Shift */
	static const u16 ShiftMap[]={
/* 00 */0,	0,	0,	0,	0,	0,	0,	K_F1,
/* 08 */0x1B,	0,	0,	0,	0,	0x09,	'~',	K_F2,
/* 10 */0,	0,	0,	0,	0,	'q',	'!',	K_F3,
/* 18 */0,	0,	'z',	's',	'a',	'w',	'@',	K_F4,
/* 20 */0,	'c',	'x',	'd',	'e',	'$',	'#',	K_F5,
/* 28 */0,	' ',	'v',	'f',	't',	'r',	'%',	K_F6,
/* 30 */0,	'n',	'b',	'h',	'g',	'y',	'^',	K_F7,
/* 38 */0,	0,	'm',	'j',	'u',	'&',	'*',	K_F8,
/* 40 */0,	'<',	'k',	'i',	'o',	')',	'(',	K_F9,
/* 48 */0,	'>',	'?',	'l',	':',	'p',	'_',	K_F10,
/* 50 */0,	0,	'"',	0,	'{',	'+',	K_F11,	K_PRNT,
/* 58 */0,	0,	0x0D,	'}',	'|',	0,	K_F12,	0,
/* 60 */K_DN,	K_LFT,	K_PAUSE,K_UP,	K_DEL,	K_END,	0x08,	K_INS,
/* 68 */0,	'1',	K_RT,	'4',	'7',	K_PGDN,	K_HOME,	K_PGUP,
/* 70 */'0',	'.',	'2',	'5',	'6',	'8',	0,	'/',
/* 78 */0,	0x0D,	'3',	0,	'+',	'9',	'*',	0,
/* 80 */0,	0,	0,	0,	'-',	0,	0,	0,
/* 88 */0,	0,	0,	K_LWIN,	K_RWIN,	K_MENU,	0,	0 };

	while(1)
	{	short Code, RetVal;
		bool SawBreakCode;

		SawBreakCode=false;
		do
/* get scancode
xxx - should yield to OS if no scancode available */
		{	do Code=deq(&(_Con->Keystrokes));
			while(Code < 0);
/* step 0: raw set 3 scancodes */
			if(Code == 0xF0)
				SawBreakCode=true;}
		while(Code == 0xF0);
		if(SawBreakCode)
			Code=-Code;
/* step 1: raw scancodes, negated if break code. Good for e.g. video games
Alt pressed = fire weapon, Alt released = cease fire

set "bucky bits" (Alt, Ctrl, and Shift) */
		if(Code == RK_LEFT_ALT || Code == RK_RIGHT_ALT)
		{	_Con->KbdStatus |= KBD_BUCKY_ALT;
			continue; }
		if(Code == -RK_LEFT_ALT || Code == -RK_RIGHT_ALT)
		{	_Con->KbdStatus &= ~KBD_BUCKY_ALT;
			continue; }
		if(Code == RK_LEFT_CTRL || Code == RK_RIGHT_CTRL)
		{	_Con->KbdStatus |= KBD_BUCKY_CTRL;
			continue; }
		if(Code == -RK_LEFT_CTRL || Code == -RK_RIGHT_CTRL)
		{	_Con->KbdStatus &= ~KBD_BUCKY_CTRL;
			continue; }
		if(Code == RK_LEFT_SHIFT || Code == RK_RIGHT_SHIFT)
		{	_Con->KbdStatus |= KBD_BUCKY_SHIFT;
			continue; }
		if(Code == -RK_LEFT_SHIFT || Code == -RK_RIGHT_SHIFT)
		{	_Con->KbdStatus &= ~KBD_BUCKY_SHIFT;
			continue; }
/* not interested in break codes other than Ctrl, Alt, Shift */
		if(Code < 0)
			continue;
/* Scroll Lock, Num Lock, and Caps Lock set the LEDs */
		if(Code == RK_SCROLL_LOCK)
		{	_Con->KbdStatus ^= KBD_BUCKY_SCRL;
			goto LEDS; }
		if(Code == RK_NUM_LOCK)
		{	_Con->KbdStatus ^= KBD_BUCKY_NUM;
			goto LEDS; }
		if(Code == RK_CAPS_LOCK)
		{	_Con->KbdStatus ^= KBD_BUCKY_CAPS;
LEDS:			_kbdWrite(_KBD_DATA_REG, _KBD_KCMD_LEDS);
/* clever choice of KBD_BUCKY_SCRL, etc. makes this work */
			_kbdWrite(_KBD_DATA_REG,
				(_Con->KbdStatus >> 10) & 7);
			continue; }
/* ignore invalid scan codes */
		if(Code >= 0x90)
			continue;
		RetVal=Map[Code];
/* defective keyboard? more than 104 keys? */
		if(RetVal == 0)
			continue;
/* merge bucky bits with raw scan code
(no, don't do this, we still need Code)
//		Code |= (_Con->KbdStatus & KBD_BUCKY_ANY);
/* step 2: raw scancodes with bucky bits. Good for e.g. user-interface
Alt+BackSpace = undo, Shift+Alt+BackSpace = redo

Using tables for scancode-to-ASCII conversion would be more flexible,
but take more memory. With 5 bucky bits (Ctrl, Shift, Alt, NumLock, and
CapsLock), it would take 32 tables, 144 entries each (one entry for
each scancode), 2 bytes/entry == 9216 bytes.

Alt pressed? there is no ASCII equivalent
just return mapped scancode with bucky bits */
		if((_Con->KbdStatus & KBD_BUCKY_ALT) != 0)
			RetVal |= (_Con->KbdStatus & KBD_BUCKY_ANY);
/* Ctrl pressed... */
		else if((_Con->KbdStatus & KBD_BUCKY_CTRL) != 0)
/* ...Ctrl @A-Z[\]^_ return 0-31 */
		{	if(RetVal >= '@' && RetVal <= '_')
				RetVal=RetVal - '@';
/* ...anything else: return mapped scancode with bucky bits */
			else RetVal |= (_Con->KbdStatus & KBD_BUCKY_ANY); }
/* Shift pressed... */
		else if((_Con->KbdStatus & KBD_BUCKY_SHIFT) != 0)
/* ...ASCII: use alternate map to convert Code to RetVal */
		{	if(RetVal >= ' ' && RetVal <= '~')
				RetVal=ShiftMap[Code];
/* ...non-ASCII: return mapped scancode with bucky bits */
			else RetVal |= (_Con->KbdStatus & KBD_BUCKY_ANY); }
/* no Alt, no Ctrl, no Shift: get return value from Map[] unless
	1. NumLock is on
	2. the key pressed is on the numeric keypad
in which case, return value comes from ShiftMap[] instead. Got that? */
		else if(((_Con->KbdStatus & KBD_BUCKY_NUM) != 0)
			&& RetVal >= RK_END_1)
				RetVal=ShiftMap[Code];
/* somehow, after all this, we got an invalid key... */
		if(RetVal == 0)
			continue;
/* CapsLock affects only A-Z
could use tolower() and toupper() here if you want to drag in ctype.h
Logic is backwards to get proper A-Z value from Map[] or ShiftMap[] */
		if((_Con->KbdStatus & KBD_BUCKY_CAPS) == 0)
		{	if(RetVal >= 'a' && RetVal <= 'z')
				RetVal=RetVal - 'a' + 'A';
			else if(RetVal >= 'A' && RetVal <= 'Z')
				RetVal=RetVal - 'A' + 'a'; }
/* ASCII at last... */
		return(RetVal); }}
/*****************************************************************************
	name:	main
*****************************************************************************/
#define	BUF_SIZE	512

int main(void)
{	u8 Buffer[BUF_SIZE];
	int Result, Temp;
	union REGS Regs;
	vector Vector9;

/* make sure it's really DOS */
	Regs.x.ax=0x1600;
	int86(0x2F, &Regs, &Regs);
	if(Regs.h.al != 0 && Regs.h.al != 0x80)
	{	printf("Detected Windows version ");
		if(Regs.h.al == 0x01 || Regs.h.al == 0xFF)
			printf("2.x");
		else printf("%u.%u\n", Regs.h.al, Regs.h.ah);
		printf("This keyboard driver/demo code will not work "
			"under Windows\n");
		return(-1); }
/* try the scancode set 3 keyboard driver */
	if(kbdInit(3) != 0)
		return(2);
/* init Con */
	_Con.Keystrokes.Data=Buffer;
	_Con.Keystrokes.Size=BUF_SIZE;
/* set new IRQ 9 (keyboard) interrupt handler */
	SAVE_VECT(9, Vector9);
	SET_VECT(9, _irq1);
/* demo */
	printf("(Press Esc to quit this demo)\n");
	do
	{	
		Temp=my_getch(&_Con);

		if(Temp < 0x100)
			putchar(Temp);
		else
			printf("<%04X>", Temp);

		printf("key = <%04X>\n", Temp);
		fflush(stdout);


	}while(Temp != '\x1B');

/* restore original keyboard interrupt vector */
	RESTORE_VECT(9, Vector9);
/* go back to scancode set 1 or 2 */
	Temp=1;
	DEBUG(printf("programming scancode set %u\n", Temp);)
	Result=_kbdWriteRead(_KBD_DATA_REG, _KBD_KCMD_SCSET, 1,
		(u8 *)"\xFA");
	if(Result == 0)
/* ...send scancode set value, expect 0xFA (ACK) */
	{	Result=_kbdWriteRead(_KBD_DATA_REG, Temp, 1,
			(u8 *)"\xFA"); }
	return(0); }

⌨️ 快捷键说明

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