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

📄 keyboard.c

📁 nucleus10版本源码
💻 C
字号:
/* (C) Copyright TDS (Mathias Martin)                    *//*                                                       *//* keyboard.c                                            *//*                                                       *//* - main code taken from the pc_keyb.c and keyboard.c   *//*   from the Linux source code                          *//*   -> read the GNU GENERAL PUBLIC LICENSE              *//*                                                       *//* todo-list:                                            *//*   - add more keys, like F13-F24 or alternative keys   *//*                                                       *//* - started rewriting of pascal code on                 *//*   Tuesday, 10.04.2001                                 *//* - first version on                                    *//*   Friday, 13.04.2001 Easter ;-)                       *//*   - readkey supports: - alt+key, ctrl+key + shift+key *//*                       - same as the crt readkey       *//*   - full support of all keys (including print, break  *//*     and left+right ctrl/alt keys)                     *//*   - 28.08.2004 - ported to NucleusKL					 */#include <support.h>#include <stdio.h>#include <multi.h>#include <drivers/timer.h>#include <drivers/input/keyboard.h>#include <drivers/input/keys_def.h>#include <interrupts.h>#include <drivers/pic.h>#include <irqa.h>//#define KBD_REPORT_UNKNOWN#define KBD_REPORT_TIMEOUTS//#define DEBUG_KEYBOARD#define scan_key#define reboot()	{}static char CanReboot = 0; // carefulstatic char CanExit = 0;// Each buffered key is stored in one of these structurestypedef struct {	unsigned char keycode;	unsigned char down;} BufferEnt;#define KEYB_BUFFER_LEN		128						// Must be power of two#define KEYB_BUFFER_MASK	(KEYB_BUFFER_LEN - 1)	// For wraparoundstatic char reply_expected = 0;static char acknowledge = 0;static char resend = 0;static unsigned char led_state = 0;static unsigned char shift_state = 0;static unsigned char shift_state2 = 0; // normal, w/o left and rightstatic unsigned int prev_scancode = 0;// Keyboard bufferstatic BufferEnt keyb_scbuffer[KEYB_BUFFER_LEN];// Buffer head and tail pointers. When these are equal, buffer is empty.static int keyb_sc_head;	// Pre-increment before insertingstatic int keyb_sc_tail;	// Post-increment after removing// Append a scancode to the keyboard bufferstatic void keyb_insert(unsigned char keycode, unsigned char down){	int newhead;	// See where the head would be if I inserted a character	newhead = (keyb_sc_head + 1) & KEYB_BUFFER_MASK;	if (newhead == keyb_sc_tail) {		// FIXME: click speaker		return;		// Buffer is full, discard	}	// Insert the character in the queue	keyb_scbuffer[newhead].keycode = keycode;	keyb_scbuffer[newhead].down = down;	keyb_sc_head = newhead;}// Get the next scancode in the keyboard buffer// Returns true if the scancode was retrieved successfully// Pass NULL pointer to just test buffer for a keystatic int keyb_remove(BufferEnt *scancode){	int ints_were_enabled = interrupts_disable();	int ret;	// See if there is something in the queue	ret = 0;	if (keyb_sc_head != keyb_sc_tail) {		if (scancode) {			*scancode = keyb_scbuffer[keyb_sc_tail++];			keyb_sc_tail &= KEYB_BUFFER_MASK;		}		ret = 1;	}	if (ints_were_enabled)		interrupts_enable();	return ret;}char do_acknowledge( unsigned char scancode ){	if ( reply_expected )	{		if ( scancode == KBD_REPLY_ACK )		{			acknowledge = 1;			reply_expected = 0;			return 0;		}		else		if ( scancode == KBD_REPLY_RESEND )		{			resend = 1;			reply_expected = 0;			return 0;		}#ifdef DEBUG_KEYBOARD		printf( "Keyboard reply expected - got %02X\n", scancode );#endif	}	return 1;}char kbd_translate( unsigned char scancode, unsigned char *keycode, char raw_mode ){	if ( ( scancode == 0xE0 ) || ( scancode == 0xE1 ) )	{		prev_scancode = scancode;		return 0;	}	if ( ( scancode == 0x00 ) || ( scancode == 0xFF ) )	{		prev_scancode = 0;		return 0;	}	scancode &= 0x7F;	if ( prev_scancode )	{		if ( prev_scancode != 0xE0 )		{			if ( ( prev_scancode == 0xE1 ) && ( scancode == 0x1D ) )			{				prev_scancode = 0x100;				return 0;			}			else			if ( ( prev_scancode == 0x100 ) && ( scancode == 0x45 ) )			{				*keycode = E1_PAUSE;				prev_scancode = 0;			}			else			{ // unknown escape sequence#ifdef KBD_REPORT_UNKNOWN				if ( !raw_mode )					printf( "Unknown E1 escape sequence.\n" );#endif				prev_scancode = 0;				return 0;			}		}		else		{			prev_scancode = 0;			if ( ( scancode == 0x2A ) || ( scancode == 0x36 ) )				return 0;			if ( e0_keys[ scancode ] )				* keycode = e0_keys[ scancode ];			else			{ // unknown scancode#ifdef KBD_REPORT_UNKNOWN				if ( !raw_mode )					printf( "Unknown scancode E0 %02X.\n", scancode );#endif				return 0;			}		}	} else if ( scancode >= SC_LIM )	{		*keycode = high_keys[ scancode - SC_LIM ];		if ( !*keycode )		{			if ( !raw_mode )			{ // unexpected scancode#ifdef KBD_REPORT_UNKNOWN				printf( "Unexpected scancode (%02X) ignored.\n", scancode );#endif			}			return 0;		}	}	else		*keycode = scancode;	return 1;}unsigned int pckbd_unexpected_up( unsigned char keycode ){	if ( ( keycode >= SC_LIM ) || ( keycode == 85 ) )		return 0;	return 200;}void Boot( void ){	delay( 500 );	// if we have come here: reset CPU }	outportb( 0x64, 0xFE ); // tell keyboard controller to reset CPU	delay( 500 );           // wait until it has an effect	// if all didn't work, try this: }	reboot();	// we had no luck, so go into an endless loop	printf( "Can't reboot system, system halted..." );	halt(0);}unsigned char handle_kbd_event( void );void setleds( unsigned char _led_ );void setshift( unsigned char _shift_, unsigned char on );void handle_scancode( unsigned char scancode, unsigned char down ){	unsigned char keycode;	if ( !kbd_translate( scancode, & keycode, 1 ) )		return ;	if ( keycode == SHIFT_LEFT )		setshift( 0x01, down );	if ( keycode == SHIFT_RIGHT )		setshift( 0x02, down );	if ( keycode == CTRL_LEFT )		setshift( 0x04, down );	if ( keycode == CTRL_RIGHT )		setshift( 0x08, down );	if ( keycode == ALT_LEFT )		setshift( 0x10, down );	if ( keycode == ALT_RIGHT )		setshift( 0x20, down );	if ( !down )	{		if ( keycode == SCROLL_LOCK )			setleds( 0x01 );		if ( keycode == NUM_LOCK )			setleds( 0x02 );		if ( keycode == CAPS_LOCK )			setleds( 0x04 );	}	else	{		if ( CanReboot )		{			if ( keycode == 111 )             // Delete pressed			{				if ( ( shift_state2 & 2 ) &&   // Ctrl			        ( shift_state2 & 4 ) )         // Alt				Boot();			}		}	}	keyb_insert(scancode, down);	//	keyb_scancode.keycode = scancode;	//	keyb_scancode.down = down;}unsigned char handle_kbd_event( void ){	unsigned char status = inportb( KBD_STATUS_REG );	unsigned char scancode;	while ( status & KBD_STAT_OBF )	{		scancode = inportb( KBD_DATA_REG );		if ( ( status & KBD_STAT_MOUSE_OBF ) == 0 )		{			if ( do_acknowledge( scancode ) )					handle_scancode( scancode, ! ( scancode & 0x80 ) );		}		status = inportb( KBD_STATUS_REG );	}	return status;}void kb_wait( void ){	unsigned long timeout = KBC_TIMEOUT;	do	{		unsigned char status = handle_kbd_event();		if ( !( status & KBD_STAT_IBF ) )			return ;	} while ( timeout-- );#ifdef KBD_REPORT_TIMEOUTS	printf( "Keyboard TimeOut! (1)\n" );#endif}int KBD_NO_DATA = -1;  /* No data */int KBD_BAD_DATA = -2; /* Parity or other error */int kbd_read_input( void ){	int retval;	unsigned char status, data;	retval = KBD_NO_DATA;	status = inportb( KBD_STATUS_REG );	if ( status & KBD_STAT_OBF )	{		data = inportb( KBD_DATA_REG );		retval = data;		if ( status & ( KBD_STAT_GTO | KBD_STAT_PERR ) )			retval = KBD_BAD_DATA;	}	return retval;}void kbd_clear_input( void ){	unsigned char maxread;	maxread = 100;	do {		if ( kbd_read_input() == KBD_NO_DATA )			break;		maxread--;	}	while ( maxread > 0 );}char send_data( unsigned char data ){	int retries = 3;	unsigned long timeout = KBD_TIMEOUT;	do {		acknowledge = 0;		resend = 0;		reply_expected = 1;		kb_wait();		outportb( KBD_DATA_REG, data );		for ( ; ; )		{			if ( acknowledge )				return 1;			if ( resend )				break;			if ( timeout-- == 0 )			{#ifdef KBD_REPORT_TIMEOUTS				printf( "Keyboard TimeOut! (2)\n" );#endif				return 0;			}		}	}	while ( retries-- );#ifdef KBD_REPORT_TIMEOUTS	printf( "Too many NACK's. Noisy keyboard cable ?\n" );#endif	return 0;}/* 1 = Scroll2 = Num4 = Caps */void setleds( unsigned char _led_ ){	if ( led_state & _led_ )		led_state &= ~_led_;	else		led_state |= _led_;	send_data( KBD_CMD_SET_LEDS ); // besserer Weg, da sonst Abbruch nach	// False-R?ckgabe	send_data( led_state );	send_data( KBD_CMD_ENABLE );}/*  1 = Shift links2 = Shift rechts4 = Strg  links8 = Strg  rechts16 = Alt   links32 = Alt   rechts */void setshift( unsigned char _shift_, unsigned char on ){	unsigned char shift;	shift = shift_state;	if ( on )		shift |= _shift_;	else		shift &= ~_shift_;	shift_state = shift;	//Abfrage f?r Shift ohne links/rechts-Unterscheidung	shift = shift_state2;	if ( ( shift_state & 1 ) ||     // Shift links	        ( shift_state & 2 ) )   // Shift rechts		shift |= 1;	else		shift &= ~1;	if ( ( shift_state & 4 ) ||     //Strg links	        ( shift_state & 8 ) )   //Strg rechts		shift |= 2;	else		shift &= ~2;	if ( ( shift_state & 16 ) ||     //Alt links	        ( shift_state & 32 ) )   //Alt rechts		shift |= 4;	else		shift &= ~4;	shift_state2 = shift;}char GetCurrentKey( unsigned char *keycode, unsigned char *down ){	int ints_were_enabled = interrupts_disable();	int ret;	BufferEnt tmp;	ret = 0;	if (keyb_remove(&tmp)) {		*keycode = tmp.keycode;		*down = tmp.down;		ret = 1;	}	if (ints_were_enabled)		interrupts_enable();	return ret;}void ClearKey( void ){	//	keyb_scancode.keycode = 0;	//	kbd_clear_input();}unsigned char SaveKey = 0x00;unsigned char readkey( void ){	unsigned char KeyBuffer, keycode, down, result;	BufferEnt tmp;	result = 0x00;	if ( SaveKey != 0x00 )	{		result = SaveKey;		SaveKey = 0x00;		return result;	}	do	{		// wait till key is pressed		while (!keyb_remove(&tmp))			multi_yield(); // give time to other threads		// save variables		keycode = tmp.keycode - 1;		down = tmp.down;		if ( down )		{			if ( norm_map[ keycode ] == 255 )				continue;			// get third level keys			if ( shift_state & 32 )   // Alt-Gr			{				KeyBuffer = alt_map[ keycode ];				result = KeyBuffer;				ClearKey();				break;			}			if ( ( ( shift_state & 1 ) == 0 ) && ( ( led_state & 2 ) == 0 ) &&   // Numpad			        ( ( keycode >= 70 ) && ( keycode <= 82 ) ) )			{				KeyBuffer = num_map[ keycode ];				result = KeyBuffer;				if ( KeyBuffer == 0x00 )   // extended key					SaveKey = ext_num_map[ keycode ];				ClearKey();				break;			}			else			{				if ( shift_state2 & 1 )   // shift pressed					KeyBuffer = shift_map[ keycode ];				else					KeyBuffer = norm_map[ keycode ];				result = KeyBuffer;				if ( KeyBuffer == 0x00 )   // extended key					SaveKey = ext_map[ keycode ];				ClearKey();				break;			}		}	} while ( 1 );		return result;}char keypressed( void ){	return keyb_remove(0);}unsigned char GetLEDStatus( void ){	return led_state;}void SetLEDStatus( unsigned char Status ){	setleds( Status );}unsigned char GetShiftStatus( void ){	return shift_state;}unsigned char GetShiftStatus2( void ){	return shift_state2;}void get_char( unsigned char ch, void * chardata ){	outportw( 0x3C4, 0x0402 );	outportw( 0x3C4, 0x0704 );	outportw( 0x3CE, 0x0204 );	outportw( 0x3CE, 0x0005 );	outportw( 0x3CE, 0x0006 );	//  Move(Ptr(SegA000, Ord(ch) shl 5)^, Data, 16);	outportw( 0x3C4, 0x0302 );	outportw( 0x3C4, 0x0304 );	outportw( 0x3CE, 0x0004 );	outportw( 0x3CE, 0x1005 );	outportw( 0x3CE, 0x0E06 );}void set_char( unsigned char ch, void * chardata ){	outportw( 0x3C4, 0x0402 );	outportw( 0x3C4, 0x0704 );	outportw( 0x3CE, 0x0204 );	outportw( 0x3CE, 0x0005 );	outportw( 0x3CE, 0x0006 );	//  move(chardate, Ptr(segA000, Ord(ch) shl 5)^, 16);	outportw( 0x3C4, 0x0302 );	outportw( 0x3C4, 0x0304 );	outportw( 0x3CE, 0x0004 );	outportw( 0x3CE, 0x1005 );	outportw( 0x3CE, 0x0E06 );}void kbd_reset( void ){	int status;	outportb( KBD_DATA_REG, 0xFF ); /*reset keyboard   */	do {		status = inportb( KBD_STATUS_REG );		//		printf( "%d", status & 2 );	}	while ( status & 0x02 );		outportb( KBD_CNTL_REG, 0xAA ); /*selftest   */	inportb( KBD_DATA_REG );	outportb( KBD_CNTL_REG, 0xAB ); /*interface selftest   */	inportb( KBD_DATA_REG );	outportb( KBD_CNTL_REG, 0xAE ); /*enable keyboard   */	outportb( KBD_DATA_REG, 0xFF ); /*reset keyboard   */		inportb( KBD_DATA_REG );	inportb( KBD_DATA_REG );	outportb( KBD_CNTL_REG, 0xAD ); /*disable keyboard   */	outportb( KBD_CNTL_REG, 0x60 );	outportb( KBD_DATA_REG, 0x01 | 0x04 | 0x20 | 0x40 );	outportb( KBD_CNTL_REG, 0xAE ); /*enable keyboard   */}void keyboard_handler( void ){	handle_kbd_event();}char keyboard_init( void ){	// 	unsigned char i;	if ( !CanExit )	{		printf( "keyboard: Initialize keyboard functions (german layout)\n" );		kbd_reset();		kbd_clear_input();		setleds( 0x00 ); // getting LED status not possible,		// init with reset		//		for (i=0;i<=255;i++)		//			GetChar(chr(i), Save[i]); // save font		//		Font = Save;		CanReboot = 1;		CanExit = 1;	}	else		printf( "keyboard: Error: Keyboard driver already started\n" );	interrupt_install(INT_HARDWARE, 1, isr_keyboard);	irq_enable(1);	return 1;}#ifdef DEBUG_KEYBOARDint main( void ){	unsigned char a = 0;#ifdef scan_key	unsigned char b, save1, save2;#endif	if ( !StartKeyboard() )		return 1;#ifdef scan_key	b = 0;	save1 = 0;	save2 = 0;#endif#ifdef scan_key	do	{		GetCurrentKey( & a, & b );		if ( save1 != a || save2 != b )		{			printf( "%03d %s\n", a, b ? "pressed" : "released" );			save1 = a;			save2 = b;		}	}	while ( a != 1 );#else	do {		while ( keypressed() )		{			a = readkey();			if ( a != 0x00 )				printf( "%c", a );		}	}	while ( a != 27 );#endif	EndKeyboard();	return 0;}#endif

⌨️ 快捷键说明

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