REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			745 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			745 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces
 | |
|   provided by Ps2KbdCtrller.c.
 | |
| 
 | |
| Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "Ps2Keyboard.h"
 | |
| 
 | |
| /**
 | |
|   Check whether the EFI key buffer is empty.
 | |
| 
 | |
|   @param Queue     Pointer to instance of EFI_KEY_QUEUE.
 | |
| 
 | |
|   @retval TRUE    The EFI key buffer is empty.
 | |
|   @retval FALSE   The EFI key buffer isn't empty.
 | |
| **/
 | |
| BOOLEAN
 | |
| IsEfikeyBufEmpty (
 | |
|   IN  EFI_KEY_QUEUE  *Queue
 | |
|   )
 | |
| {
 | |
|   return (BOOLEAN)(Queue->Head == Queue->Tail);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Read & remove one key data from the EFI key buffer.
 | |
| 
 | |
|   @param Queue     Pointer to instance of EFI_KEY_QUEUE.
 | |
|   @param KeyData   Receive the key data.
 | |
| 
 | |
|   @retval EFI_SUCCESS   The key data is popped successfully.
 | |
|   @retval EFI_NOT_READY There is no key data available.
 | |
| **/
 | |
| EFI_STATUS
 | |
| PopEfikeyBufHead (
 | |
|   IN  EFI_KEY_QUEUE  *Queue,
 | |
|   OUT EFI_KEY_DATA   *KeyData OPTIONAL
 | |
|   )
 | |
| {
 | |
|   if (IsEfikeyBufEmpty (Queue)) {
 | |
|     return EFI_NOT_READY;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Retrieve and remove the values
 | |
|   //
 | |
|   if (KeyData != NULL) {
 | |
|     CopyMem (KeyData, &Queue->Buffer[Queue->Head], sizeof (EFI_KEY_DATA));
 | |
|   }
 | |
| 
 | |
|   Queue->Head = (Queue->Head + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Push one key data to the EFI key buffer.
 | |
| 
 | |
|   @param Queue     Pointer to instance of EFI_KEY_QUEUE.
 | |
|   @param KeyData   The key data to push.
 | |
| **/
 | |
| VOID
 | |
| PushEfikeyBufTail (
 | |
|   IN  EFI_KEY_QUEUE  *Queue,
 | |
|   IN  EFI_KEY_DATA   *KeyData
 | |
|   )
 | |
| {
 | |
|   if ((Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT == Queue->Head) {
 | |
|     //
 | |
|     // If Queue is full, pop the one from head.
 | |
|     //
 | |
|     PopEfikeyBufHead (Queue, NULL);
 | |
|   }
 | |
| 
 | |
|   CopyMem (&Queue->Buffer[Queue->Tail], KeyData, sizeof (EFI_KEY_DATA));
 | |
|   Queue->Tail = (Queue->Tail + 1) % KEYBOARD_EFI_KEY_MAX_COUNT;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Judge whether is a registered key
 | |
| 
 | |
|   @param RegsiteredData       A pointer to a buffer that is filled in with the keystroke
 | |
|                               state data for the key that was registered.
 | |
|   @param InputData            A pointer to a buffer that is filled in with the keystroke
 | |
|                               state data for the key that was pressed.
 | |
| 
 | |
|   @retval TRUE                Key be pressed matches a registered key.
 | |
|   @retval FALSE               Match failed.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsKeyRegistered (
 | |
|   IN EFI_KEY_DATA  *RegsiteredData,
 | |
|   IN EFI_KEY_DATA  *InputData
 | |
|   )
 | |
| 
 | |
| {
 | |
|   ASSERT (RegsiteredData != NULL && InputData != NULL);
 | |
| 
 | |
|   if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||
 | |
|       (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar))
 | |
|   {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
 | |
|   //
 | |
|   if ((RegsiteredData->KeyState.KeyShiftState != 0) &&
 | |
|       (RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState))
 | |
|   {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if ((RegsiteredData->KeyState.KeyToggleState != 0) &&
 | |
|       (RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState))
 | |
|   {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|     Reads the next keystroke from the input device. The WaitForKey Event can
 | |
|     be used to test for existence of a keystroke via WaitForEvent () call.
 | |
| 
 | |
|     @param ConsoleInDev          Ps2 Keyboard private structure
 | |
|     @param KeyData               A pointer to a buffer that is filled in with the keystroke
 | |
|                                  state data for the key that was pressed.
 | |
| 
 | |
| 
 | |
|     @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.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| KeyboardReadKeyStrokeWorker (
 | |
|   IN  KEYBOARD_CONSOLE_IN_DEV  *ConsoleInDev,
 | |
|   OUT EFI_KEY_DATA             *KeyData
 | |
|   )
 | |
| 
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   EFI_TPL     OldTpl;
 | |
| 
 | |
|   if (KeyData == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Enter critical section
 | |
|   //
 | |
|   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | |
| 
 | |
|   KeyboardTimerHandler (NULL, ConsoleInDev);
 | |
| 
 | |
|   if (ConsoleInDev->KeyboardErr) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   } else {
 | |
|     Status = PopEfikeyBufHead (&ConsoleInDev->EfiKeyQueue, KeyData);
 | |
|     if (Status == EFI_NOT_READY) {
 | |
|       ZeroMem (&KeyData->Key, sizeof (KeyData->Key));
 | |
|       InitializeKeyState (ConsoleInDev, &KeyData->KeyState);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Perform 8042 controller and keyboard initialization which implement SIMPLE_TEXT_IN.Reset()
 | |
| 
 | |
|   @param This                 Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
 | |
|   @param ExtendedVerification Indicate that the driver may perform a more
 | |
|                               exhaustive verification operation of the device during
 | |
|                               reset, now this par is ignored in this driver
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| KeyboardEfiReset (
 | |
|   IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
 | |
|   IN  BOOLEAN                         ExtendedVerification
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS               Status;
 | |
|   KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn;
 | |
|   EFI_TPL                  OldTpl;
 | |
| 
 | |
|   ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | |
|   if (ConsoleIn->KeyboardErr) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | |
|     EFI_PROGRESS_CODE,
 | |
|     EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET,
 | |
|     ConsoleIn->DevicePath
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Enter critical section
 | |
|   //
 | |
|   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | |
| 
 | |
|   //
 | |
|   // Call InitKeyboard to initialize the keyboard
 | |
|   //
 | |
|   Status = InitKeyboard (ConsoleIn, ExtendedVerification);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     //
 | |
|     // Leave critical section and return
 | |
|     //
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Leave critical section and return
 | |
|   //
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   //
 | |
|   // Report the status If a stuck key was detected
 | |
|   //
 | |
|   if (KeyReadStatusRegister (ConsoleIn) & 0x01) {
 | |
|     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | |
|       EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | |
|       EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_STUCK_KEY,
 | |
|       ConsoleIn->DevicePath
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Report the status If keyboard is locked
 | |
|   //
 | |
|   if ((KeyReadStatusRegister (ConsoleIn) & 0x10) == 0) {
 | |
|     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | |
|       EFI_ERROR_CODE | EFI_ERROR_MINOR,
 | |
|       EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_EC_LOCKED,
 | |
|       ConsoleIn->DevicePath
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Retrieve key values for driver user which implement SIMPLE_TEXT_IN.ReadKeyStroke().
 | |
| 
 | |
|   @param This    Pointer to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
 | |
|   @param Key     The output buffer for key value
 | |
| 
 | |
|   @retval EFI_SUCCESS success to read key stroke
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| KeyboardReadKeyStroke (
 | |
|   IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *This,
 | |
|   OUT EFI_INPUT_KEY                   *Key
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS               Status;
 | |
|   KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn;
 | |
|   EFI_KEY_DATA             KeyData;
 | |
| 
 | |
|   ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // Considering if the partial keystroke is enabled, there maybe a partial
 | |
|   // keystroke in the queue, so here skip the partial keystroke and get the
 | |
|   // next key from the queue
 | |
|   //
 | |
|   while (1) {
 | |
|     //
 | |
|     // If there is no pending key, then return.
 | |
|     //
 | |
|     Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // If it is partial keystroke, skip it.
 | |
|     //
 | |
|     if ((KeyData.Key.ScanCode == SCAN_NULL) && (KeyData.Key.UnicodeChar == CHAR_NULL)) {
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Translate the CTRL-Alpha characters to their corresponding control value
 | |
|     // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
 | |
|     //
 | |
|     if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
 | |
|       if ((KeyData.Key.UnicodeChar >= L'a') && (KeyData.Key.UnicodeChar <= L'z')) {
 | |
|         KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar - L'a' + 1);
 | |
|       } else if ((KeyData.Key.UnicodeChar >= L'A') && (KeyData.Key.UnicodeChar <= L'Z')) {
 | |
|         KeyData.Key.UnicodeChar = (CHAR16)(KeyData.Key.UnicodeChar - L'A' + 1);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Event notification function for SIMPLE_TEXT_IN.WaitForKey event
 | |
|   Signal the event if there is key available
 | |
| 
 | |
|   @param Event    the event object
 | |
|   @param Context  waiting context
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| KeyboardWaitForKey (
 | |
|   IN  EFI_EVENT  Event,
 | |
|   IN  VOID       *Context
 | |
|   )
 | |
| {
 | |
|   EFI_TPL                  OldTpl;
 | |
|   KEYBOARD_CONSOLE_IN_DEV  *ConsoleIn;
 | |
|   EFI_KEY_DATA             KeyData;
 | |
| 
 | |
|   ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *)Context;
 | |
| 
 | |
|   //
 | |
|   // Enter critical section
 | |
|   //
 | |
|   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | |
| 
 | |
|   KeyboardTimerHandler (NULL, ConsoleIn);
 | |
| 
 | |
|   if (!ConsoleIn->KeyboardErr) {
 | |
|     //
 | |
|     // WaitforKey doesn't support the partial key.
 | |
|     // Considering if the partial keystroke is enabled, there maybe a partial
 | |
|     // keystroke in the queue, so here skip the partial keystroke and get the
 | |
|     // next key from the queue
 | |
|     //
 | |
|     while (!IsEfikeyBufEmpty (&ConsoleIn->EfiKeyQueue)) {
 | |
|       CopyMem (
 | |
|         &KeyData,
 | |
|         &(ConsoleIn->EfiKeyQueue.Buffer[ConsoleIn->EfiKeyQueue.Head]),
 | |
|         sizeof (EFI_KEY_DATA)
 | |
|         );
 | |
|       if ((KeyData.Key.ScanCode == SCAN_NULL) && (KeyData.Key.UnicodeChar == CHAR_NULL)) {
 | |
|         PopEfikeyBufHead (&ConsoleIn->EfiKeyQueue, &KeyData);
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // if there is pending value key, signal the event.
 | |
|       //
 | |
|       gBS->SignalEvent (Event);
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Leave critical section and return
 | |
|   //
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx event
 | |
|   Signal the event if there is key available
 | |
| 
 | |
|   @param Event    event object
 | |
|   @param Context  waiting context
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| KeyboardWaitForKeyEx (
 | |
|   IN  EFI_EVENT  Event,
 | |
|   IN  VOID       *Context
 | |
|   )
 | |
| 
 | |
| {
 | |
|   KeyboardWaitForKey (Event, Context);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Reset the input device and optionally run diagnostics
 | |
| 
 | |
|   @param This                     Protocol instance pointer.
 | |
|   @param ExtendedVerification     Driver may perform diagnostics on reset.
 | |
| 
 | |
|   @retval EFI_SUCCESS             The device was reset.
 | |
|   @retval EFI_DEVICE_ERROR        The device is not functioning properly and could
 | |
|                                   not be reset.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| KeyboardEfiResetEx (
 | |
|   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | |
|   IN BOOLEAN                            ExtendedVerification
 | |
|   )
 | |
| 
 | |
| {
 | |
|   KEYBOARD_CONSOLE_IN_DEV  *ConsoleInDev;
 | |
| 
 | |
|   ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | |
| 
 | |
|   return ConsoleInDev->ConIn.Reset (
 | |
|                                &ConsoleInDev->ConIn,
 | |
|                                ExtendedVerification
 | |
|                                );
 | |
| }
 | |
| 
 | |
| /**
 | |
|     Reads the next keystroke from the input device. The WaitForKey Event can
 | |
|     be used to test for existence of a keystroke via WaitForEvent () call.
 | |
| 
 | |
| 
 | |
|     @param This         Protocol instance pointer.
 | |
|     @param KeyData      A pointer to a buffer that is filled in with the keystroke
 | |
|                         state data for the key that was pressed.
 | |
| 
 | |
|     @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.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| KeyboardReadKeyStrokeEx (
 | |
|   IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | |
|   OUT EFI_KEY_DATA                       *KeyData
 | |
|   )
 | |
| 
 | |
| {
 | |
|   KEYBOARD_CONSOLE_IN_DEV  *ConsoleInDev;
 | |
| 
 | |
|   if (KeyData == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | |
|   return KeyboardReadKeyStrokeWorker (ConsoleInDev, KeyData);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set certain state for the input device.
 | |
| 
 | |
|   @param This               Protocol instance pointer.
 | |
|   @param KeyToggleState     A pointer to the EFI_KEY_TOGGLE_STATE to set the
 | |
|                             state for the input device.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The device state was set successfully.
 | |
|   @retval EFI_DEVICE_ERROR      The device is not functioning correctly and could
 | |
|                                 not have the setting adjusted.
 | |
|   @retval EFI_UNSUPPORTED       The device does not have the ability to set its state.
 | |
|   @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| KeyboardSetState (
 | |
|   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | |
|   IN EFI_KEY_TOGGLE_STATE               *KeyToggleState
 | |
|   )
 | |
| 
 | |
| {
 | |
|   EFI_STATUS               Status;
 | |
|   KEYBOARD_CONSOLE_IN_DEV  *ConsoleInDev;
 | |
|   EFI_TPL                  OldTpl;
 | |
| 
 | |
|   if (KeyToggleState == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // Enter critical section
 | |
|   //
 | |
|   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | |
| 
 | |
|   if (ConsoleInDev->KeyboardErr) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   if ((*KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) {
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Update the status light
 | |
|   //
 | |
|   ConsoleInDev->ScrollLock          = FALSE;
 | |
|   ConsoleInDev->NumLock             = FALSE;
 | |
|   ConsoleInDev->CapsLock            = FALSE;
 | |
|   ConsoleInDev->IsSupportPartialKey = FALSE;
 | |
| 
 | |
|   if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {
 | |
|     ConsoleInDev->ScrollLock = TRUE;
 | |
|   }
 | |
| 
 | |
|   if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {
 | |
|     ConsoleInDev->NumLock = TRUE;
 | |
|   }
 | |
| 
 | |
|   if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {
 | |
|     ConsoleInDev->CapsLock = TRUE;
 | |
|   }
 | |
| 
 | |
|   if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {
 | |
|     ConsoleInDev->IsSupportPartialKey = TRUE;
 | |
|   }
 | |
| 
 | |
|   Status = UpdateStatusLights (ConsoleInDev);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
| Exit:
 | |
|   //
 | |
|   // Leave critical section and return
 | |
|   //
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|     Register a notification function for a particular keystroke for the input device.
 | |
| 
 | |
|     @param This                       Protocol instance pointer.
 | |
|     @param KeyData                    A pointer to a buffer that is filled in with the keystroke
 | |
|                                       information data for the key that was pressed. If KeyData.Key,
 | |
|                                       KeyData.KeyState.KeyToggleState and KeyData.KeyState.KeyShiftState are 0,
 | |
|                                       then any incomplete keystroke will trigger a notification of the KeyNotificationFunction.
 | |
|     @param KeyNotificationFunction    Points to the function to be called when the key
 | |
|                                       sequence is typed specified by KeyData. This notification function
 | |
|                                       should be called at <=TPL_CALLBACK.
 | |
|     @param NotifyHandle               Points to the unique handle assigned to the registered notification.
 | |
| 
 | |
|     @retval EFI_SUCCESS               The notification function was registered successfully.
 | |
|     @retval EFI_OUT_OF_RESOURCES      Unable to allocate resources for necessary data structures.
 | |
|     @retval EFI_INVALID_PARAMETER     KeyData or NotifyHandle or KeyNotificationFunction is NULL.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| KeyboardRegisterKeyNotify (
 | |
|   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | |
|   IN EFI_KEY_DATA                       *KeyData,
 | |
|   IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,
 | |
|   OUT VOID                              **NotifyHandle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                     Status;
 | |
|   KEYBOARD_CONSOLE_IN_DEV        *ConsoleInDev;
 | |
|   EFI_TPL                        OldTpl;
 | |
|   LIST_ENTRY                     *Link;
 | |
|   KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;
 | |
|   KEYBOARD_CONSOLE_IN_EX_NOTIFY  *NewNotify;
 | |
| 
 | |
|   if ((KeyData == NULL) || (NotifyHandle == NULL) || (KeyNotificationFunction == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // Enter critical section
 | |
|   //
 | |
|   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | |
| 
 | |
|   //
 | |
|   // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
 | |
|   //
 | |
|   for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
 | |
|     CurrentNotify = CR (
 | |
|                       Link,
 | |
|                       KEYBOARD_CONSOLE_IN_EX_NOTIFY,
 | |
|                       NotifyEntry,
 | |
|                       KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
 | |
|                       );
 | |
|     if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
 | |
|       if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
 | |
|         *NotifyHandle = CurrentNotify;
 | |
|         Status        = EFI_SUCCESS;
 | |
|         goto Exit;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Allocate resource to save the notification function
 | |
|   //
 | |
|   NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *)AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));
 | |
|   if (NewNotify == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   NewNotify->Signature         = KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
 | |
|   NewNotify->KeyNotificationFn = KeyNotificationFunction;
 | |
|   CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
 | |
|   InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);
 | |
| 
 | |
|   *NotifyHandle = NewNotify;
 | |
|   Status        = EFI_SUCCESS;
 | |
| 
 | |
| Exit:
 | |
|   //
 | |
|   // Leave critical section and return
 | |
|   //
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|     Remove a registered notification function from a particular keystroke.
 | |
| 
 | |
|     @param This                       Protocol instance pointer.
 | |
|     @param NotificationHandle         The handle of the notification function being unregistered.
 | |
| 
 | |
| 
 | |
|     @retval EFI_SUCCESS               The notification function was unregistered successfully.
 | |
|     @retval EFI_INVALID_PARAMETER     The NotificationHandle is invalid.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| KeyboardUnregisterKeyNotify (
 | |
|   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
 | |
|   IN VOID                               *NotificationHandle
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                     Status;
 | |
|   KEYBOARD_CONSOLE_IN_DEV        *ConsoleInDev;
 | |
|   EFI_TPL                        OldTpl;
 | |
|   LIST_ENTRY                     *Link;
 | |
|   KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;
 | |
| 
 | |
|   if (NotificationHandle == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // Enter critical section
 | |
|   //
 | |
|   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | |
| 
 | |
|   for (Link = ConsoleInDev->NotifyList.ForwardLink; Link != &ConsoleInDev->NotifyList; Link = Link->ForwardLink) {
 | |
|     CurrentNotify = CR (
 | |
|                       Link,
 | |
|                       KEYBOARD_CONSOLE_IN_EX_NOTIFY,
 | |
|                       NotifyEntry,
 | |
|                       KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
 | |
|                       );
 | |
|     if (CurrentNotify == NotificationHandle) {
 | |
|       //
 | |
|       // Remove the notification function from NotifyList and free resources
 | |
|       //
 | |
|       RemoveEntryList (&CurrentNotify->NotifyEntry);
 | |
| 
 | |
|       gBS->FreePool (CurrentNotify);
 | |
|       Status = EFI_SUCCESS;
 | |
|       goto Exit;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Can not find the specified Notification Handle
 | |
|   //
 | |
|   Status = EFI_INVALID_PARAMETER;
 | |
| Exit:
 | |
|   //
 | |
|   // Leave critical section and return
 | |
|   //
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Process key notify.
 | |
| 
 | |
|   @param  Event                 Indicates the event that invoke this function.
 | |
|   @param  Context               Indicates the calling context.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| KeyNotifyProcessHandler (
 | |
|   IN  EFI_EVENT  Event,
 | |
|   IN  VOID       *Context
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                     Status;
 | |
|   KEYBOARD_CONSOLE_IN_DEV        *ConsoleIn;
 | |
|   EFI_KEY_DATA                   KeyData;
 | |
|   LIST_ENTRY                     *Link;
 | |
|   LIST_ENTRY                     *NotifyList;
 | |
|   KEYBOARD_CONSOLE_IN_EX_NOTIFY  *CurrentNotify;
 | |
|   EFI_TPL                        OldTpl;
 | |
| 
 | |
|   ConsoleIn = (KEYBOARD_CONSOLE_IN_DEV *)Context;
 | |
| 
 | |
|   //
 | |
|   // Invoke notification functions.
 | |
|   //
 | |
|   NotifyList = &ConsoleIn->NotifyList;
 | |
|   while (TRUE) {
 | |
|     //
 | |
|     // Enter critical section
 | |
|     //
 | |
|     OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | |
|     Status = PopEfikeyBufHead (&ConsoleIn->EfiKeyQueueForNotify, &KeyData);
 | |
|     //
 | |
|     // Leave critical section
 | |
|     //
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {
 | |
|       CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE);
 | |
|       if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
 | |
|         CurrentNotify->KeyNotificationFn (&KeyData);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 |