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

📄 keyb.c

📁 小型操作系统,以VC为开发环境,需要boachs调试
💻 C
字号:
/***************************************************************************
**     File name   : keyb.c
**     Author      : x.cheng
**     Create date :
**
**	   Comment:
**        keyboard driver
**
**     Revisions:
**     $Log: keyb.c,v $
**     Revision 1.6  2005/08/10 13:02:51  x.cheng
**     surport l-shift and r-shift key
**
**     Revision 1.5  2005/08/05 15:04:37  x.cheng
**     export function vKeybWaitForBusy() for reboot
**
**     Revision 1.4  2005/08/04 08:42:15  x.cheng
**     new method for interrupt ISR install
**
**     Revision 1.3  2005/07/27 07:45:58  x.cheng
**     function added:
**       int iKeybReadChar(), which read key without wait...
**       bug fix...
**
**     Revision 1.2  2005/07/27 07:03:24  x.cheng
**     function added: int iKeybGetChar()
**     structure ts_Console has changed, so fix this file.
**
**     Revision 1.1.1.1  2005/07/27 06:53:15  x.cheng
**     add into repositories
**
**
***************************************************************************/
#include "const.h"
#include "type.h"
#include "stdio.h"
#include "stdarg.h"
 
#include "..\..\Inc\i386\io.h"
#include "..\..\Inc\i386\system.h"
#include "..\..\Inc\i386\x86.h"
#include "..\..\Inc\i386\interrupt.h"

#include "..\..\inc\keyb.h"
#include "..\..\inc\tui.h"
#include "..\..\inc\mts.h"
#include "..\..\inc\debug.h"

#include "..\..\inc\wqueue.h"

#include "..\inc\def_keyb.h"

/*********************************************
 * global variable
 *********************************************/
unsigned char g_ucLedStatus;
struct KeybStatus_Struct {
	unsigned char ucCtrl;
	unsigned char ucAlt;
	unsigned char ucShift;
}g_stKeybStatus;

DECLARE_WAITQUEUE( g_stKeybWaitQueue );

/************************************************************
*************************************************************
**      Function Name:			vKeybWaitForBusy
**      Author:                 x.cheng
**
**      Comment:
**		   Wait after a keyboard operation.
**
**      List of parameters:
**			no
**
**      Return value:   
**
**      Revisions:
**
*************************************************************
*************************************************************/
void vKeybWaitForBusy()
{
	int iRetries = 1000;

	while( (ucInPort(PORT_8255_KEYB_STATUS) & KEYB_BUSY) == KEYB_BUSY ) {
		//udelay(50)
		if ( --iRetries == 0 )
			break;
	}
}

/************************************************************
*************************************************************
**      Function Name:			vKeybUpdateLeds
**      Author:                 x.cheng
**
**      Comment:
**		 键盘驱动函数,用于设置键盘灯
**
**      List of parameters:
**			ucState - scroll lock | num lock<<1 | caps lock<<2
**
**      Return value:   
**
**      Revisions:
**
*************************************************************
*************************************************************/
void vKeybUpdateLeds(unsigned char ucState )
{
	unsigned long ulFlags;

	g_ucLedStatus = ucState;

	SaveEflagsAndCli(ulFlags);
	
	vKeybWaitForBusy();
	vOutPort(PORT_8255_BASE_ADDRESS, PORT_8255_KEYB_LED_CODE);
	vKeybWaitForBusy();
	vOutPort(PORT_8255_BASE_ADDRESS, g_ucLedStatus);

	RestoreEflags(ulFlags);
}

/************************************************************
*************************************************************
**      Function Name:			vKeybInitial
**      Author:                 x.cheng
**
**      Comment:
**		 键盘驱动初始化,设置中断处理函数
**
**      List of parameters:
**			no
**
**      Return value:   
**
**      Revisions:
**
*************************************************************
*************************************************************/
/******ISR defined in hwISR2.asm***********/
void vKeybISR(void);
void vDoKeybIRQ();
//-----------------------------------------------------------
void vKeybInitial()
{ 
	unsigned long ulFlags;

	SaveEflagsAndCli(ulFlags);
	
	// Set typematic delay as short as possible.
	vOutPort(PORT_8255_BASE_ADDRESS, KEYB_SET_TYPEMATIC);
	vKeybWaitForBusy();
	// typematic 0 means "MODE CON RATE=30 DELAY=1".
	vOutPort(PORT_8255_BASE_ADDRESS, 0);

	vKeybUpdateLeds((0) | (1<<1) | (0<<2));

	// Install the keyboard handler.
	IsrInstallHandler(HWM_KEYB_IRQ1, &vDoKeybIRQ );
	
//	RestoreEflags(ulFlags);
//	vSTI(); 
}
//----------------------------------------------------------
//local function:
// get the hitten keyboard code, and return the hitten key scan code
//
//----------------------------------------------------------
static unsigned short uiScanKey()
{
	unsigned short uiScanCode, uiAck;
	unsigned long ulFlags;

	SaveEflagsAndCli(ulFlags);

	uiScanCode = ucInPort(PORT_8255_BASE_ADDRESS);
	uiAck = ucInPort(PORT_8255_KEYB_ACK);
	vOutPort(PORT_8255_KEYB_ACK, uiAck | 0x80);	// Disable bit 7
	vOutPort(PORT_8255_KEYB_ACK, uiAck);		// Send that back

	RestoreEflags(ulFlags);

	return (uiScanCode);
}
//----------------------------------------------------------
//local function:
// This is the keyboard interrupt handler routine. It is
//invoked every time a key is pressed or released on the
//keyboard.
//
//----------------------------------------------------------
void vDoKeybIRQ()
{
	ts_Console *pstConsole;
	unsigned short uiPressedKey = uiScanKey();
	unsigned short uiKeyCode;

	pstConsole = pstTuiGetConsoleAddress( iTuiGetCurrentConsole() );
	if ( (g_stKeybStatus.ucCtrl == 1) && (g_stKeybStatus.ucAlt == 1) &&
		(uiPressedKey == DEL_SCAN) ) {
		kprintf("Reboot system......\n");
		UtilRebootSystem();
	}

	if ( g_stKeybStatus.ucAlt == 1 ) uiKeyCode = auiKeyWithAlt[ uiPressedKey ];
	else if ( g_stKeybStatus.ucCtrl == 1 ) uiKeyCode = auiKeyWithCtrl[ uiPressedKey ];
	else {
		if ( !(pstConsole->ucLedState & LED_ON_CAPS_LOCK) && (g_stKeybStatus.ucShift==0) )
			uiKeyCode = auiKeyRegular[ uiPressedKey ];
		else if ( !(pstConsole->ucLedState & LED_ON_CAPS_LOCK) && (g_stKeybStatus.ucShift==1) ) {
			uiKeyCode = auiKeyWithShift[ uiPressedKey ];
		}
		else if ( (pstConsole->ucLedState & LED_ON_CAPS_LOCK) && (g_stKeybStatus.ucShift==0) ){
			uiKeyCode = auiKeyRegular[ uiPressedKey ];
			if ( ( (uiKeyCode&0xFF)>='a') && ( (uiKeyCode&0xFF)<='z') ) uiKeyCode -='a'-'A';
		}
		else {
			uiKeyCode = auiKeyWithShift[ uiPressedKey ];
			if ( ((uiKeyCode&0xFF)>='A') && ((uiKeyCode&0xFF)<='Z') ) uiKeyCode -='a'-'A';
		}
		if ( (pstConsole->ucLedState != g_stKeybStatus.ucShift) && (uiPressedKey>=71 && uiPressedKey<=83) )
			uiKeyCode = aucKeyPadChar[ uiPressedKey-71 ];
	}
	// Print the char only if it's not released (bit 8 set).
	switch( uiPressedKey ) {
	case 56:	//alt
		g_stKeybStatus.ucAlt = 1;
		break;
	case (56+128):
		g_stKeybStatus.ucAlt = 0;
		break;
	case 29:	//ctrl
		g_stKeybStatus.ucCtrl = 1;
		break;
	case (29+128):
		g_stKeybStatus.ucCtrl = 0;
		break;
	case 0x2a:	//l-shift
		g_stKeybStatus.ucShift = 1;
		break;
	case (0x2a+128):
		g_stKeybStatus.ucShift = 0;
		break;
	case 0x36:	//r-shift
		g_stKeybStatus.ucShift = 1;
		break;
	case (0x36+128):	//r-shift
		g_stKeybStatus.ucShift = 0;
		break;
	case 58:	//caps lock
		pstConsole->ucLedState ^= LED_ON_CAPS_LOCK;
		vKeybUpdateLeds(pstConsole->ucLedState);
		break;
	case 69:	//num lock
		pstConsole->ucLedState ^= LED_ON_NUM_LOCK;
		vKeybUpdateLeds(pstConsole->ucLedState);
		break;
	case 70:	//scroll lock
		pstConsole->ucLedState ^= LED_ON_SCROLL_LOCK;
		vKeybUpdateLeds(pstConsole->ucLedState);
		break;
	default:
		if (!(uiPressedKey & 0x80)) {
			if ( (uiKeyCode>=ALT_F1) && (uiKeyCode<=ALT_F10) ) {
				//change console.
				int iConsole;
				iConsole = ((uiKeyCode - ALT_F1) >> 8) +1;
				iTuiSwitchToConsole(iConsole);
				return;
			}
			// A key has been released => update the buffer
			if ( (pstConsole->uiKeybBufferCount) < KEYB_BUFFER_SIZE ) {
				(pstConsole->uiKeybBufferCount)++;

				if ( ++(pstConsole->uiKeybBufferWrite) >= KEYB_BUFFER_SIZE )
					pstConsole->uiKeybBufferWrite = 0;
				pstConsole->auiKeybBuffer[ (pstConsole->uiKeybBufferWrite) ] = uiKeyCode;
	
				vMtsWakeupWaitQueue( &g_stKeybWaitQueue );
			} else {
				iTuiPrintf("%s: keyboard buffer for console %i full!\n",
					__FUNCTION__, iTuiGetCurrentConsole() );
			}
			//唤醒等待按键的任务
				//...
		}
		break;
	}
}

/************************************************************
*************************************************************
**      Function Name:			iKeybGetChar
**      Author:                 x.cheng
**
**      Comment:
**		 Wait for keypressed and return the hitten character ASCII code.
**
**      List of parameters:
**			no
**
**      Return value:   
**			The hitten character ASCII code.
**
**      Revisions:
**
*************************************************************
*************************************************************/
int iKeybGetChar()
{

	ts_Task *pstCurrentTask = pstMtsGetCurrentTask();
	ts_Console *pstConsole = pstTuiGetConsoleAddress( pstCurrentTask->iConsole );
	register int iKeyPressed;
	unsigned long ulFlags;

	SaveEflagsAndCli(ulFlags);

	for( ; ; ) {
		if( pstConsole->uiKeybBufferCount )
			break;
		MtsWaitEvent( g_stKeybWaitQueue, pstConsole->uiKeybBufferCount );
	}

	// Update keyboard buffer in mutual exclusion.
	(pstConsole->uiKeybBufferCount)--;
	if ( ++(pstConsole->uiKeybBufferRead) >= KEYB_BUFFER_SIZE )
		pstConsole->uiKeybBufferRead = 0;
	iKeyPressed = (int)( pstConsole->auiKeybBuffer[ pstConsole->uiKeybBufferRead ] );

	RestoreEflags( ulFlags );

	if( iKeyPressed == CTRL_D )	return( EOF );

	return( iKeyPressed );
}

/************************************************************
*************************************************************
**      Function Name:			iKeybReadChar
**      Author:                 x.cheng
**
**      Comment:
**		 Return the first key in the buffer, without waiting if
**		the buffer is empty.
**
**      List of parameters:
**			no
**
**      Return value:   
**			The hitten character ASCII code if a character has
**		  been hitten or -1 if error.
**
**      Revisions:
**
*************************************************************
*************************************************************/
int iKeybReadChar()
{
	ts_Console *pstConsole = pstTuiGetConsoleAddress( pstMtsGetCurrentTask()->iConsole );
	int iKey;
	unsigned long ulFlags;
	
	SaveEflagsAndCli(ulFlags);

	// If the task's console is not the current console return.
	if ( pstMtsGetCurrentTask()->iConsole != iTuiGetCurrentConsole() ) {
		RestoreEflags(ulFlags);
		return (-1);
	}

	// If the keyboard buffer is empty return NULL.
	if ( pstConsole->uiKeybBufferCount == 0 ) {
		RestoreEflags(ulFlags);
		return (NULL);
	}

	// Update keyboard buffer in mutual exclusion.
	(pstConsole->uiKeybBufferCount)--;
	if ( ++(pstConsole->uiKeybBufferRead) >= KEYB_BUFFER_SIZE )
		pstConsole->uiKeybBufferRead = 0;
	iKey = (int)(pstConsole->auiKeybBuffer[ pstConsole->uiKeybBufferRead ] );
	RestoreEflags(ulFlags);

	if( iKey == CTRL_C )	return (EOF);

	return (iKey);
}


⌨️ 快捷键说明

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