-/**@file\r
- PS/2 Keyboard driver\r
- Routines that support SIMPLE_TEXT_IN protocol\r
+/** @file\r
+ Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces\r
+ provided by Ps2KbdCtrller.c.\r
\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
\r
#include "Ps2Keyboard.h"\r
\r
-//\r
-// function declarations\r
-//\r
-EFI_STATUS\r
-EFIAPI\r
-KeyboardEfiReset (\r
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
- IN BOOLEAN ExtendedVerification\r
- );\r
+/**\r
+ Check whether the EFI key buffer is empty.\r
\r
-EFI_STATUS\r
-EFIAPI\r
-KeyboardReadKeyStroke (\r
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
- OUT EFI_INPUT_KEY *Key\r
- );\r
+ @param Queue Pointer to instance of EFI_KEY_QUEUE.\r
\r
-VOID\r
-EFIAPI\r
-KeyboardWaitForKey (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- );\r
+ @retval TRUE The EFI key buffer is empty.\r
+ @retval FALSE The EFI key buffer isn't empty.\r
+**/\r
+BOOLEAN\r
+IsEfikeyBufEmpty (\r
+ IN EFI_KEY_QUEUE *Queue\r
+ )\r
+{\r
+ return (BOOLEAN) (Queue->Head == Queue->Tail);\r
+}\r
+\r
+/**\r
+ Read & remove one key data from the EFI key buffer.\r
\r
+ @param Queue Pointer to instance of EFI_KEY_QUEUE.\r
+ @param KeyData Receive the key data.\r
+\r
+ @retval EFI_SUCCESS The key data is popped successfully.\r
+ @retval EFI_NOT_READY There is no key data available.\r
+**/\r
EFI_STATUS\r
-KeyboardCheckForKey (\r
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This\r
- );\r
+PopEfikeyBufHead (\r
+ IN EFI_KEY_QUEUE *Queue,\r
+ OUT EFI_KEY_DATA *KeyData OPTIONAL\r
+ )\r
+{\r
+ if (IsEfikeyBufEmpty (Queue)) {\r
+ return EFI_NOT_READY;\r
+ }\r
+ //\r
+ // Retrieve and remove the values\r
+ //\r
+ if (KeyData != NULL) {\r
+ CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA));\r
+ }\r
+ Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Push one key data to the EFI key buffer.\r
+\r
+ @param Queue Pointer to instance of EFI_KEY_QUEUE.\r
+ @param KeyData The key data to push.\r
+**/\r
+VOID\r
+PushEfikeyBufTail (\r
+ IN EFI_KEY_QUEUE *Queue,\r
+ IN EFI_KEY_DATA *KeyData\r
+ )\r
+{\r
+ if ((Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT == Queue->Head) {\r
+ //\r
+ // If Queue is full, pop the one from head.\r
+ //\r
+ PopEfikeyBufHead (Queue, NULL);\r
+ }\r
+ CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA));\r
+ Queue->Tail = (Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;\r
+}\r
\r
/**\r
- @param RegsiteredData - A pointer to a buffer that is filled in with the keystroke \r
- state data for the key that was registered.\r
- @param InputData - A pointer to a buffer that is filled in with the keystroke \r
- state data for the key that was pressed.\r
-\r
- @retval TRUE - Key be pressed matches a registered key.\r
- @retval FALSE - Match failed. \r
- \r
+ Judge whether is a registed key\r
+\r
+ @param RegsiteredData A pointer to a buffer that is filled in with the keystroke\r
+ state data for the key that was registered.\r
+ @param InputData A pointer to a buffer that is filled in with the keystroke\r
+ state data for the key that was pressed.\r
+\r
+ @retval TRUE Key be pressed matches a registered key.\r
+ @retval FLASE Match failed.\r
+\r
**/\r
BOOLEAN\r
IsKeyRegistered (\r
IN EFI_KEY_DATA *RegsiteredData,\r
IN EFI_KEY_DATA *InputData\r
- );\r
+ )\r
+\r
+{\r
+ ASSERT (RegsiteredData != NULL && InputData != NULL);\r
+\r
+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
+ //\r
+ if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
+ RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
+ return FALSE;\r
+ }\r
+ if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
+ RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+\r
+}\r
\r
/**\r
- Reads the next keystroke from the input device. The WaitForKey Event can \r
+ Reads the next keystroke from the input device. The WaitForKey Event can\r
be used to test for existance of a keystroke via WaitForEvent () call.\r
\r
- \r
- @param ConsoleInDev - Ps2 Keyboard private structure\r
- @param KeyData - A pointer to a buffer that is filled in with the keystroke \r
- state data for the key that was pressed.\r
+ @param ConsoleInDev Ps2 Keyboard private structure\r
+ @param KeyData A pointer to a buffer that is filled in with the keystroke\r
+ state data for the key that was pressed.\r
+\r
\r
- \r
- @retval EFI_SUCCESS - The keystroke information was returned.\r
- @retval EFI_NOT_READY - There was no keystroke data availiable.\r
- @retval EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
- hardware errors.\r
- @retval EFI_INVALID_PARAMETER - KeyData is NULL. \r
+ @retval EFI_SUCCESS The keystroke information was returned.\r
+ @retval EFI_NOT_READY There was no keystroke data availiable.\r
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
+ hardware errors.\r
+ @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
\r
**/\r
EFI_STATUS\r
{\r
EFI_STATUS Status;\r
EFI_TPL OldTpl;\r
- LIST_ENTRY *Link;\r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
- EFI_KEY_DATA OriginalKeyData;\r
+\r
if (KeyData == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
//\r
// Enter critical section\r
//\r
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
\r
+ KeyboardTimerHandler (NULL, ConsoleInDev);\r
+\r
if (ConsoleInDev->KeyboardErr) {\r
- gBS->RestoreTPL (OldTpl);\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // If there's no key, just return\r
- //\r
- Status = KeyboardCheckForKey (&ConsoleInDev->ConIn);\r
- if (EFI_ERROR (Status)) {\r
- gBS->RestoreTPL (OldTpl);\r
- return EFI_NOT_READY;\r
- }\r
- CopyMem (&KeyData->Key, &ConsoleInDev->Key, sizeof (EFI_INPUT_KEY));\r
-\r
- ConsoleInDev->Key.ScanCode = SCAN_NULL; \r
- ConsoleInDev->Key.UnicodeChar = 0x0000; \r
- CopyMem (&KeyData->KeyState, &ConsoleInDev->KeyState, sizeof (EFI_KEY_STATE));\r
- \r
- ConsoleInDev->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
- ConsoleInDev->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
- gBS->RestoreTPL (OldTpl);\r
- //\r
- //Switch the control value to their original characters. In KeyGetchar() the CTRL-Alpha characters have been switched to \r
- // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.\r
- //\r
- CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));\r
- if (ConsoleInDev->Ctrled) {\r
- if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {\r
- if (ConsoleInDev->CapsLock) {\r
- OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'A' - 1);\r
- } else {\r
- OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'a' - 1);\r
- } \r
- }\r
- }\r
- //\r
- // Invoke notification functions if exist\r
- //\r
- for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
- CurrentNotify = CR (\r
- Link, \r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
- NotifyEntry, \r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
- );\r
- if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { \r
- CurrentNotify->KeyNotificationFn (&OriginalKeyData);\r
+ Status = EFI_DEVICE_ERROR;\r
+ } else {\r
+ Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData);\r
+ if (Status == EFI_NOT_READY) {\r
+ ZeroMem (&KeyData->Key, sizeof (KeyData->Key));\r
+ InitializeKeyState (ConsoleInDev, &KeyData->KeyState);\r
}\r
}\r
\r
- return EFI_SUCCESS;\r
+ gBS->RestoreTPL (OldTpl);\r
+ return Status;\r
}\r
\r
/**\r
- logic reset keyboard\r
- Implement SIMPLE_TEXT_IN.Reset()\r
- Perform 8042 controller and keyboard initialization\r
+ Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset()\r
\r
- @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
- @param ExtendedVerification Indicate that the driver may perform a more \r
- exhaustive verification operation of the device during \r
- reset, now this par is ignored in this driver \r
+ @param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
+ @param ExtendedVerification Indicate that the driver may perform a more\r
+ exhaustive verification operation of the device during\r
+ reset, now this par is ignored in this driver\r
\r
**/\r
EFI_STATUS\r
gBS->RestoreTPL (OldTpl);\r
return EFI_DEVICE_ERROR;\r
}\r
- //\r
- // Clear the status of ConsoleIn.Key\r
- //\r
- ConsoleIn->Key.ScanCode = SCAN_NULL;\r
- ConsoleIn->Key.UnicodeChar = 0x0000;\r
\r
//\r
// Leave critical section and return\r
//\r
// Report the status If keyboard is locked\r
//\r
- if (!(KeyReadStatusRegister (ConsoleIn) & 0x10)) {\r
+ if ((KeyReadStatusRegister (ConsoleIn) & 0x10) == 0) {\r
REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_LOCKED,\r
}\r
\r
/**\r
- Implement SIMPLE_TEXT_IN.ReadKeyStroke().\r
- Retrieve key values for driver user.\r
+ Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke().\r
\r
@param This Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
- @param Key The output buffer for key value \r
+ @param Key The output buffer for key value\r
\r
@retval EFI_SUCCESS success to read key stroke\r
**/\r
EFI_KEY_DATA KeyData;\r
\r
ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
- Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
\r
- CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
- return EFI_SUCCESS;\r
- \r
+ //\r
+ // Considering if the partial keystroke is enabled, there maybe a partial\r
+ // keystroke in the queue, so here skip the partial keystroke and get the\r
+ // next key from the queue\r
+ //\r
+ while (1) {\r
+ //\r
+ // If there is no pending key, then return.\r
+ //\r
+ Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // If it is partial keystroke, skip it.\r
+ //\r
+ if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {\r
+ continue;\r
+ }\r
+ //\r
+ // Translate the CTRL-Alpha characters to their corresponding control value\r
+ // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
+ //\r
+ if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
+ if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
+ KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);\r
+ } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
+ KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);\r
+ }\r
+ }\r
+\r
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+ return EFI_SUCCESS;\r
+ }\r
}\r
\r
/**\r
IN VOID *Context\r
)\r
{\r
- EFI_TPL OldTpl;\r
- KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
+ EFI_TPL OldTpl;\r
+ KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
+ EFI_KEY_DATA KeyData;\r
\r
- ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context);\r
+ ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;\r
\r
//\r
// Enter critical section\r
//\r
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
\r
- if (ConsoleIn->KeyboardErr) {\r
+ KeyboardTimerHandler (NULL, ConsoleIn);\r
+\r
+ if (!ConsoleIn->KeyboardErr) {\r
//\r
- // Leave critical section and return\r
+ // WaitforKey doesn't suppor the partial key.\r
+ // Considering if the partial keystroke is enabled, there maybe a partial\r
+ // keystroke in the queue, so here skip the partial keystroke and get the\r
+ // next key from the queue\r
//\r
- gBS->RestoreTPL (OldTpl);\r
- return ;\r
- }\r
- //\r
- // Someone is waiting on the keyboard event, if there's\r
- // a key pending, signal the event\r
- //\r
- if (!EFI_ERROR (KeyboardCheckForKey (Context))) {\r
- gBS->SignalEvent (Event);\r
+ while (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) {\r
+ CopyMem (\r
+ &KeyData,\r
+ &(ConsoleIn->EfiKeyQueue.Buffer[ConsoleIn->EfiKeyQueue.Head]),\r
+ sizeof (EFI_KEY_DATA)\r
+ );\r
+ if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {\r
+ PopEfikeyBufHead (&ConsoleIn->EfiKeyQueue, &KeyData);\r
+ continue;\r
+ }\r
+ //\r
+ // if there is pending value key, signal the event.\r
+ //\r
+ gBS->SignalEvent (Event);\r
+ break;\r
+ }\r
}\r
//\r
// Leave critical section and return\r
//\r
gBS->RestoreTPL (OldTpl);\r
-\r
- return ;\r
-}\r
-\r
-/**\r
- Check keyboard for given key value\r
- \r
- @param This Point to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL\r
- \r
- @retval EFI_SUCCESS success check keyboard value\r
-**/\r
-EFI_STATUS\r
-KeyboardCheckForKey (\r
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This\r
- )\r
-{\r
- KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
-\r
- ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
-\r
- //\r
- // If ready to read next key, check it\r
- //\r
- if (ConsoleIn->Key.ScanCode == SCAN_NULL && ConsoleIn->Key.UnicodeChar == 0x00) {\r
- return KeyGetchar (ConsoleIn);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Judge whether is a registed key\r
-\r
- @param RegsiteredData - A pointer to a buffer that is filled in with the keystroke \r
- state data for the key that was registered.\r
- @param InputData - A pointer to a buffer that is filled in with the keystroke \r
- state data for the key that was pressed.\r
-\r
- @retval TRUE - Key be pressed matches a registered key.\r
- @retval FLASE - Match failed. \r
- \r
-**/\r
-BOOLEAN\r
-IsKeyRegistered (\r
- IN EFI_KEY_DATA *RegsiteredData,\r
- IN EFI_KEY_DATA *InputData\r
- )\r
-\r
-{\r
- ASSERT (RegsiteredData != NULL && InputData != NULL);\r
- \r
- if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
- (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
- return FALSE; \r
- } \r
- \r
- //\r
- // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
- //\r
- if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
- RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
- return FALSE; \r
- } \r
- if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
- RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
- return FALSE; \r
- } \r
- \r
- return TRUE;\r
-\r
}\r
\r
/**\r
)\r
\r
{\r
- KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
-\r
- ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context); \r
- KeyboardWaitForKey (Event, &ConsoleInDev->ConIn);\r
- \r
+ KeyboardWaitForKey (Event, Context);\r
}\r
\r
/**\r
Reset the input device and optionaly run diagnostics\r
\r
- @param This - Protocol instance pointer.\r
- @param ExtendedVerification - Driver may perform diagnostics on reset.\r
+ @param This Protocol instance pointer.\r
+ @param ExtendedVerification Driver may perform diagnostics on reset.\r
\r
- @retval EFI_SUCCESS - The device was reset.\r
- @retval EFI_DEVICE_ERROR - The device is not functioning properly and could \r
+ @retval EFI_SUCCESS The device was reset.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
not be reset.\r
\r
**/\r
)\r
\r
{\r
- EFI_STATUS Status;\r
KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
- EFI_TPL OldTpl;\r
\r
- ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); \r
- if (ConsoleInDev->KeyboardErr) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Status = ConsoleInDev->ConIn.Reset (\r
- &ConsoleInDev->ConIn, \r
- ExtendedVerification\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
-\r
- ConsoleInDev->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
- ConsoleInDev->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
+ ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
\r
- gBS->RestoreTPL (OldTpl); \r
- \r
- return EFI_SUCCESS;\r
+ return ConsoleInDev->ConIn.Reset (\r
+ &ConsoleInDev->ConIn,\r
+ ExtendedVerification\r
+ );\r
}\r
\r
/**\r
- Reads the next keystroke from the input device. The WaitForKey Event can \r
+ Reads the next keystroke from the input device. The WaitForKey Event can\r
be used to test for existance of a keystroke via WaitForEvent () call.\r
\r
\r
- @param This - Protocol instance pointer.\r
- @param KeyData - A pointer to a buffer that is filled in with the keystroke \r
- state data for the key that was pressed.\r
+ @param This Protocol instance pointer.\r
+ @param KeyData A pointer to a buffer that is filled in with the keystroke\r
+ state data for the key that was pressed.\r
\r
- @retval EFI_SUCCESS - The keystroke information was returned.\r
- @retval EFI_NOT_READY - There was no keystroke data availiable.\r
- @retval EFI_DEVICE_ERROR - The keystroke information was not returned due to \r
- hardware errors.\r
- @retval EFI_INVALID_PARAMETER - KeyData is NULL. \r
+ @retval EFI_SUCCESS The keystroke information was returned.\r
+ @retval EFI_NOT_READY There was no keystroke data availiable.\r
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
+ hardware errors.\r
+ @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
\r
**/\r
EFI_STATUS\r
\r
ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
return KeyboardReadKeyStrokeWorker (ConsoleInDev, KeyData);\r
- \r
}\r
\r
/**\r
Set certain state for the input device.\r
\r
- @param This - Protocol instance pointer.\r
- @param KeyToggleState - A pointer to the EFI_KEY_TOGGLE_STATE to set the \r
- state for the input device.\r
+ @param This Protocol instance pointer.\r
+ @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
+ state for the input device.\r
\r
- @retval EFI_SUCCESS - The device state was set successfully.\r
- @retval EFI_DEVICE_ERROR - The device is not functioning correctly and could \r
- not have the setting adjusted.\r
- @retval EFI_UNSUPPORTED - The device does not have the ability to set its state.\r
- @retval EFI_INVALID_PARAMETER - KeyToggleState is NULL. \r
+ @retval EFI_SUCCESS The device state was set successfully.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could\r
+ not have the setting adjusted.\r
+ @retval EFI_UNSUPPORTED The device does not have the ability to set its state.\r
+ @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.\r
\r
-**/ \r
+**/\r
EFI_STATUS\r
EFIAPI\r
KeyboardSetState (\r
if (KeyToggleState == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
\r
//\r
goto Exit;\r
}\r
\r
- if (((ConsoleInDev->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||\r
- ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID)) {\r
+ if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {\r
Status = EFI_UNSUPPORTED;\r
goto Exit;\r
}\r
- \r
+\r
//\r
// Update the status light\r
//\r
- ConsoleInDev->ScrollLock = FALSE;\r
- ConsoleInDev->NumLock = FALSE;\r
- ConsoleInDev->CapsLock = FALSE;\r
+ ConsoleInDev->ScrollLock = FALSE;\r
+ ConsoleInDev->NumLock = FALSE;\r
+ ConsoleInDev->CapsLock = FALSE;\r
+ ConsoleInDev->IsSupportPartialKey = FALSE;\r
\r
if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
ConsoleInDev->ScrollLock = TRUE;\r
- } \r
+ }\r
if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
ConsoleInDev->NumLock = TRUE;\r
}\r
if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
ConsoleInDev->CapsLock = TRUE;\r
}\r
+ if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {\r
+ ConsoleInDev->IsSupportPartialKey = TRUE;\r
+ }\r
\r
Status = UpdateStatusLights (ConsoleInDev);\r
if (EFI_ERROR (Status)) {\r
- Status = EFI_DEVICE_ERROR; \r
+ Status = EFI_DEVICE_ERROR;\r
}\r
\r
- ConsoleInDev->KeyState.KeyToggleState = *KeyToggleState;\r
- \r
-Exit: \r
+Exit:\r
//\r
// Leave critical section and return\r
//\r
/**\r
Register a notification function for a particular keystroke for the input device.\r
\r
- @param This - Protocol instance pointer.\r
- @param KeyData - A pointer to a buffer that is filled in with the keystroke \r
- information data for the key that was pressed.\r
- @param KeyNotificationFunction - Points to the function to be called when the key \r
- sequence is typed specified by KeyData. \r
- @param NotifyHandle - Points to the unique handle assigned to the registered notification. \r
-\r
- @retval EFI_SUCCESS - The notification function was registered successfully.\r
- @retval EFI_OUT_OF_RESOURCES - Unable to allocate resources for necesssary data structures.\r
- @retval EFI_INVALID_PARAMETER - KeyData or NotifyHandle is NULL. \r
- \r
-**/ \r
+ @param This Protocol instance pointer.\r
+ @param KeyData A pointer to a buffer that is filled in with the keystroke\r
+ information data for the key that was pressed. If KeyData.Key,\r
+ KeyData.KeyState.KeyToggleState and KeyData.KeyState.KeyShiftState\r
+ are 0, then any incomplete keystroke will trigger a notification of\r
+ the KeyNotificationFunction.\r
+ @param KeyNotificationFunction Points to the function to be called when the key\r
+ sequence is typed specified by KeyData. This notification function\r
+ should be called at <=TPL_CALLBACK.\r
+ @param NotifyHandle Points to the unique handle assigned to the registered notification.\r
+\r
+ @retval EFI_SUCCESS The notification function was registered successfully.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.\r
+ @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
KeyboardRegisterKeyNotify (\r
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
IN EFI_KEY_DATA *KeyData,\r
IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
- OUT EFI_HANDLE *NotifyHandle\r
+ OUT VOID **NotifyHandle\r
)\r
{\r
EFI_STATUS Status;\r
KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
EFI_TPL OldTpl;\r
LIST_ENTRY *Link;\r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
\r
if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
\r
//\r
//\r
for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
CurrentNotify = CR (\r
- Link, \r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
- NotifyEntry, \r
+ Link,\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+ NotifyEntry,\r
KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
);\r
- if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
- *NotifyHandle = CurrentNotify->NotifyHandle; \r
+ *NotifyHandle = CurrentNotify;\r
Status = EFI_SUCCESS;\r
goto Exit;\r
}\r
}\r
- } \r
- \r
+ }\r
+\r
//\r
// Allocate resource to save the notification function\r
- // \r
+ //\r
NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
if (NewNotify == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Exit;\r
}\r
\r
- NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE; \r
+ NewNotify->Signature = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);\r
\r
- //\r
- // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
- // \r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &NewNotify->NotifyHandle,\r
- &gSimpleTextInExNotifyGuid,\r
- NULL,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- *NotifyHandle = NewNotify->NotifyHandle; \r
+ *NotifyHandle = NewNotify;\r
Status = EFI_SUCCESS;\r
\r
Exit:\r
// Leave critical section and return\r
//\r
gBS->RestoreTPL (OldTpl);\r
- return Status; \r
+ return Status;\r
\r
}\r
\r
/**\r
Remove a registered notification function from a particular keystroke.\r
\r
- @param This - Protocol instance pointer. \r
- @param NotificationHandle - The handle of the notification function being unregistered.\r
+ @param This Protocol instance pointer.\r
+ @param NotificationHandle The handle of the notification function being unregistered.\r
\r
- \r
- @retval EFI_SUCCESS - The notification function was unregistered successfully.\r
- @retval EFI_INVALID_PARAMETER - The NotificationHandle is invalid.\r
- @retval EFI_NOT_FOUND - Can not find the matching entry in database. \r
- \r
-**/ \r
+\r
+ @retval EFI_SUCCESS The notification function was unregistered successfully.\r
+ @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
KeyboardUnregisterKeyNotify (\r
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
- IN EFI_HANDLE NotificationHandle\r
+ IN VOID *NotificationHandle\r
)\r
{\r
EFI_STATUS Status;\r
KEYBOARD_CONSOLE_IN_DEV *ConsoleInDev;\r
EFI_TPL OldTpl;\r
LIST_ENTRY *Link;\r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
\r
if (NotificationHandle == NULL) {\r
return EFI_INVALID_PARAMETER;\r
- } \r
- \r
- Status = gBS->OpenProtocol (\r
- NotificationHandle,\r
- &gSimpleTextInExNotifyGuid,\r
- NULL,\r
- NULL,\r
- NULL,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_INVALID_PARAMETER;\r
}\r
\r
ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);\r
- \r
+\r
//\r
// Enter critical section\r
//\r
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY); \r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
\r
for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {\r
CurrentNotify = CR (\r
- Link, \r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
- NotifyEntry, \r
+ Link,\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+ NotifyEntry,\r
KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
- ); \r
- if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ );\r
+ if (CurrentNotify == NotificationHandle) {\r
//\r
// Remove the notification function from NotifyList and free resources\r
//\r
- RemoveEntryList (&CurrentNotify->NotifyEntry); \r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- CurrentNotify->NotifyHandle,\r
- &gSimpleTextInExNotifyGuid,\r
- NULL,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- gBS->FreePool (CurrentNotify); \r
+ RemoveEntryList (&CurrentNotify->NotifyEntry);\r
+\r
+ gBS->FreePool (CurrentNotify);\r
Status = EFI_SUCCESS;\r
goto Exit;\r
}\r
//\r
// Can not find the specified Notification Handle\r
//\r
- Status = EFI_NOT_FOUND;\r
+ Status = EFI_INVALID_PARAMETER;\r
Exit:\r
//\r
// Leave critical section and return\r
return Status;\r
}\r
\r
+/**\r
+ Process key notify.\r
+\r
+ @param Event Indicates the event that invoke this function.\r
+ @param Context Indicates the calling context.\r
+**/\r
+VOID\r
+EFIAPI\r
+KeyNotifyProcessHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;\r
+ EFI_KEY_DATA KeyData;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NotifyList;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+ EFI_TPL OldTpl;\r
+\r
+ ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *) Context;\r
+\r
+ //\r
+ // Invoke notification functions.\r
+ //\r
+ NotifyList = &ConsoleIn->NotifyList;\r
+ while (TRUE) {\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ Status = PopEfikeyBufHead (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);\r
+ //\r
+ // Leave critical section\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {\r
+ CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+ CurrentNotify->KeyNotificationFn (&KeyData);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r