📄 keyb.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 + -