Fix the terminal driver to call hotkey callback even no one is calling ReadKeyStroke

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11562 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
niruiyu 2011-04-19 06:51:44 +00:00
parent 66fe714632
commit f0368006b0
3 changed files with 93 additions and 104 deletions

View File

@ -2,7 +2,7 @@
Produces Simple Text Input Protocol, Simple Text Input Extended Protocol and
Simple Text Output Protocol upon Serial IO Protocol.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -75,6 +75,7 @@ TERMINAL_DEV mTerminalDevTemplate = {
NULL, // EfiKeyFiFo
NULL, // ControllerNameTable
NULL, // TimerEvent
NULL, // TwoSecondTimeOut
INPUT_STATE_DEFAULT,
RESET_STATE_DEFAULT,
@ -648,7 +649,7 @@ TerminalDriverBindingStart (
EVT_NOTIFY_WAIT,
TPL_NOTIFY,
TerminalConInWaitForKeyEx,
&TerminalDevice->SimpleInputEx,
TerminalDevice,
&TerminalDevice->SimpleInputEx.WaitForKeyEx
);
if (EFI_ERROR (Status)) {
@ -659,7 +660,7 @@ TerminalDriverBindingStart (
EVT_NOTIFY_WAIT,
TPL_NOTIFY,
TerminalConInWaitForKey,
&TerminalDevice->SimpleInput,
TerminalDevice,
&TerminalDevice->SimpleInput.WaitForKey
);
if (EFI_ERROR (Status)) {
@ -842,6 +843,22 @@ TerminalDriverBindingStart (
goto ReportError;
}
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
TerminalConInTimerHandler,
TerminalDevice,
&TerminalDevice->TimerEvent
);
ASSERT_EFI_ERROR (Status);
Status = gBS->SetTimer (
TerminalDevice->TimerEvent,
TimerPeriodic,
KEYBOARD_TIMER_INTERVAL
);
ASSERT_EFI_ERROR (Status);
Status = gBS->CreateEvent (
EVT_TIMER,
TPL_CALLBACK,
@ -849,6 +866,7 @@ TerminalDriverBindingStart (
NULL,
&TerminalDevice->TwoSecondTimeOut
);
ASSERT_EFI_ERROR (Status);
Status = gBS->InstallProtocolInterface (
&TerminalDevice->Handle,
@ -1052,6 +1070,10 @@ Error:
gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);
}
if (TerminalDevice->TimerEvent != NULL) {
gBS->CloseEvent (TerminalDevice->TimerEvent);
}
if (TerminalDevice->SimpleInput.WaitForKey != NULL) {
gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);
}
@ -1245,6 +1267,7 @@ TerminalDriverBindingStop (
FreeUnicodeStringTable (TerminalDevice->ControllerNameTable);
}
gBS->CloseEvent (TerminalDevice->TimerEvent);
gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut);
gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey);
gBS->CloseEvent (TerminalDevice->SimpleInputEx.WaitForKeyEx);

View File

@ -1,7 +1,7 @@
/** @file
Header file for Terminal driver.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -61,6 +61,8 @@ typedef struct {
EFI_INPUT_KEY Data[FIFO_MAX_NUMBER + 1];
} EFI_KEY_FIFO;
#define KEYBOARD_TIMER_INTERVAL 200000 // 0.02s
#define TERMINAL_DEV_SIGNATURE SIGNATURE_32 ('t', 'm', 'n', 'l')
#define TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE SIGNATURE_32 ('t', 'm', 'e', 'n')
@ -86,6 +88,7 @@ typedef struct {
UNICODE_FIFO *UnicodeFiFo;
EFI_KEY_FIFO *EfiKeyFiFo;
EFI_UNICODE_STRING_TABLE *ControllerNameTable;
EFI_EVENT TimerEvent;
EFI_EVENT TwoSecondTimeOut;
UINT32 InputState;
UINT32 ResetState;
@ -954,7 +957,7 @@ IsRawFiFoFull (
BOOLEAN
EfiKeyFiFoInsertOneKey (
TERMINAL_DEV *TerminalDevice,
EFI_INPUT_KEY Key
EFI_INPUT_KEY *Key
);
/**
@ -1348,4 +1351,16 @@ IsHotPlugDevice (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
);
/**
Timer handler to poll the key from serial.
@param Event Indicates the event that invoke this function.
@param Context Indicates the calling context.
**/
VOID
EFIAPI
TerminalConInTimerHandler (
IN EFI_EVENT Event,
IN VOID *Context
);
#endif

View File

@ -1,7 +1,7 @@
/** @file
Implementation for EFI_SIMPLE_TEXT_INPUT_PROTOCOL protocol.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@ -26,8 +26,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
@retval EFI_SUCCESS The keystroke information was returned.
@retval EFI_NOT_READY There was no keystroke data available.
@retval EFI_DEVICE_ERROR The keystroke information was not returned due
to hardware errors.
@retval EFI_INVALID_PARAMETER KeyData is NULL.
**/
@ -37,26 +35,10 @@ ReadKeyStrokeWorker (
OUT EFI_KEY_DATA *KeyData
)
{
EFI_STATUS Status;
LIST_ENTRY *Link;
LIST_ENTRY *NotifyList;
TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
if (KeyData == NULL) {
return EFI_INVALID_PARAMETER;
}
//
// Initialize *Key to nonsense value.
//
KeyData->Key.ScanCode = SCAN_NULL;
KeyData->Key.UnicodeChar = 0;
Status = TerminalConInCheckForKey (&TerminalDevice->SimpleInput);
if (EFI_ERROR (Status)) {
return EFI_NOT_READY;
}
if (!EfiKeyFiFoRemoveOneKey (TerminalDevice, &KeyData->Key)) {
return EFI_NOT_READY;
}
@ -64,21 +46,6 @@ ReadKeyStrokeWorker (
KeyData->KeyState.KeyShiftState = 0;
KeyData->KeyState.KeyToggleState = 0;
//
// Invoke notification functions if exist
//
NotifyList = &TerminalDevice->NotifyList;
for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {
CurrentNotify = CR (
Link,
TERMINAL_CONSOLE_IN_EX_NOTIFY,
NotifyEntry,
TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
CurrentNotify->KeyNotificationFn (KeyData);
}
}
return EFI_SUCCESS;
@ -226,12 +193,7 @@ TerminalConInWaitForKeyEx (
IN VOID *Context
)
{
TERMINAL_DEV *TerminalDevice;
TerminalDevice = TERMINAL_CON_IN_EX_DEV_FROM_THIS (Context);
TerminalConInWaitForKey (Event, &TerminalDevice->SimpleInput);
TerminalConInWaitForKey (Event, Context);
}
//
@ -532,43 +494,37 @@ TerminalConInWaitForKey (
// Someone is waiting on the keystroke event, if there's
// a key pending, signal the event
//
// Context is the pointer to EFI_SIMPLE_TEXT_INPUT_PROTOCOL
//
if (!EFI_ERROR (TerminalConInCheckForKey (Context))) {
if (!IsEfiKeyFiFoEmpty ((TERMINAL_DEV *) Context)) {
gBS->SignalEvent (Event);
}
}
/**
Check for a pending key in the Efi Key FIFO or Serial device buffer.
@param This Indicates the calling context.
@retval EFI_SUCCESS There is key pending.
@retval EFI_NOT_READY There is no key pending.
@retval EFI_DEVICE_ERROR If Serial IO is not attached to serial device.
Timer handler to poll the key from serial.
@param Event Indicates the event that invoke this function.
@param Context Indicates the calling context.
**/
EFI_STATUS
TerminalConInCheckForKey (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
VOID
EFIAPI
TerminalConInTimerHandler (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
TERMINAL_DEV *TerminalDevice;
UINT32 Control;
UINT8 Input;
EFI_SERIAL_IO_MODE *Mode;
EFI_SERIAL_IO_PROTOCOL *SerialIo;
UINTN SerialInTimeOut;
TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This);
TerminalDevice = (TERMINAL_DEV *) Context;
SerialIo = TerminalDevice->SerialIo;
if (SerialIo == NULL) {
return EFI_DEVICE_ERROR;
return ;
}
//
// if current timeout value for serial device is not identical with
@ -602,28 +558,7 @@ TerminalConInCheckForKey (
TerminalDevice->SerialInTimeOut = SerialInTimeOut;
}
}
//
// Check whether serial buffer is empty.
//
Status = SerialIo->GetControl (SerialIo, &Control);
if ((Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) != 0) {
//
// Translate all the raw data in RawFIFO into EFI Key,
// according to different terminal type supported.
//
TranslateRawDataToEfiKey (TerminalDevice);
//
// if there is pre-fetched Efi Key in EfiKeyFIFO buffer,
// return directly.
//
if (!IsEfiKeyFiFoEmpty (TerminalDevice)) {
return EFI_SUCCESS;
} else {
return EFI_NOT_READY;
}
}
//
// Fetch all the keys in the serial buffer,
// and insert the byte stream into RawFIFO.
@ -651,12 +586,6 @@ TerminalConInCheckForKey (
// according to different terminal type supported.
//
TranslateRawDataToEfiKey (TerminalDevice);
if (IsEfiKeyFiFoEmpty (TerminalDevice)) {
return EFI_NOT_READY;
}
return EFI_SUCCESS;
}
/**
@ -837,15 +766,37 @@ IsRawFiFoFull (
**/
BOOLEAN
EfiKeyFiFoInsertOneKey (
TERMINAL_DEV *TerminalDevice,
EFI_INPUT_KEY Key
TERMINAL_DEV *TerminalDevice,
EFI_INPUT_KEY *Key
)
{
UINT8 Tail;
UINT8 Tail;
LIST_ENTRY *Link;
LIST_ENTRY *NotifyList;
TERMINAL_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
EFI_KEY_DATA KeyData;
Tail = TerminalDevice->EfiKeyFiFo->Tail;
ASSERT (Tail < FIFO_MAX_NUMBER + 1);
CopyMem (&KeyData.Key, Key, sizeof (EFI_INPUT_KEY));
KeyData.KeyState.KeyShiftState = 0;
KeyData.KeyState.KeyToggleState = 0;
//
// Invoke notification functions if exist
//
NotifyList = &TerminalDevice->NotifyList;
for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList,Link); Link = GetNextNode (NotifyList,Link)) {
CurrentNotify = CR (
Link,
TERMINAL_CONSOLE_IN_EX_NOTIFY,
NotifyEntry,
TERMINAL_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
CurrentNotify->KeyNotificationFn (&KeyData);
}
}
if (IsEfiKeyFiFoFull (TerminalDevice)) {
//
// Efi Key FIFO is full
@ -853,9 +804,9 @@ EfiKeyFiFoInsertOneKey (
return FALSE;
}
TerminalDevice->EfiKeyFiFo->Data[Tail] = Key;
CopyMem (&TerminalDevice->EfiKeyFiFo->Data[Tail], Key, sizeof (EFI_INPUT_KEY));
TerminalDevice->EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
TerminalDevice->EfiKeyFiFo->Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1));
return TRUE;
}
@ -1113,31 +1064,31 @@ UnicodeToEfiKeyFlushState (
if ((InputState & INPUT_STATE_ESC) != 0) {
Key.ScanCode = SCAN_ESC;
Key.UnicodeChar = 0;
EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
}
if ((InputState & INPUT_STATE_CSI) != 0) {
Key.ScanCode = SCAN_NULL;
Key.UnicodeChar = CSI;
EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
}
if ((InputState & INPUT_STATE_LEFTOPENBRACKET) != 0) {
Key.ScanCode = SCAN_NULL;
Key.UnicodeChar = LEFTOPENBRACKET;
EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
}
if ((InputState & INPUT_STATE_O) != 0) {
Key.ScanCode = SCAN_NULL;
Key.UnicodeChar = 'O';
EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
}
if ((InputState & INPUT_STATE_2) != 0) {
Key.ScanCode = SCAN_NULL;
Key.UnicodeChar = '2';
EfiKeyFiFoInsertOneKey (TerminalDevice, Key);
EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
}
//
@ -1368,7 +1319,7 @@ UnicodeToEfiKey (
if (Key.ScanCode != SCAN_NULL) {
Key.UnicodeChar = 0;
EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
TerminalDevice->InputState = INPUT_STATE_DEFAULT;
UnicodeToEfiKeyFlushState (TerminalDevice);
continue;
@ -1423,7 +1374,7 @@ UnicodeToEfiKey (
if (Key.ScanCode != SCAN_NULL) {
Key.UnicodeChar = 0;
EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
TerminalDevice->InputState = INPUT_STATE_DEFAULT;
UnicodeToEfiKeyFlushState (TerminalDevice);
continue;
@ -1561,7 +1512,7 @@ UnicodeToEfiKey (
if (Key.ScanCode != SCAN_NULL) {
Key.UnicodeChar = 0;
EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
TerminalDevice->InputState = INPUT_STATE_DEFAULT;
UnicodeToEfiKeyFlushState (TerminalDevice);
continue;
@ -1613,6 +1564,6 @@ UnicodeToEfiKey (
Key.UnicodeChar = UnicodeChar;
}
EfiKeyFiFoInsertOneKey (TerminalDevice,Key);
EfiKeyFiFoInsertOneKey (TerminalDevice, &Key);
}
}