git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10414 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			683 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			683 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Routines implements SIMPLE_TEXT_IN protocol's interfaces based on 8042 interfaces
 | |
|   provided by Ps2KbdCtrller.c.
 | |
| 
 | |
| Copyright (c) 2006 - 2009, 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
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| 
 | |
| #include "Ps2Keyboard.h"
 | |
| 
 | |
| /**
 | |
|   Check keyboard for given key value.
 | |
|   
 | |
|   @param  This  Point to instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL
 | |
|   
 | |
|   @retval EFI_SUCCESS   success check keyboard value
 | |
|   @retval !EFI_SUCCESS  Fail to get char from keyboard
 | |
| **/
 | |
| EFI_STATUS
 | |
| KeyboardCheckForKey (
 | |
|   IN  EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
 | |
|   )
 | |
| {
 | |
|   KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
 | |
| 
 | |
|   ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // If ready to read next key, check it
 | |
|   //
 | |
|   if (ConsoleIn->Key.ScanCode == SCAN_NULL && ConsoleIn->Key.UnicodeChar == 0x00) {
 | |
|     return KeyGetchar (ConsoleIn);
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Judge whether is a registed 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 FLASE               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 existance 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 availiable.
 | |
|     @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;
 | |
|   LIST_ENTRY                            *Link;
 | |
|   KEYBOARD_CONSOLE_IN_EX_NOTIFY         *CurrentNotify;
 | |
|   EFI_KEY_DATA                          OriginalKeyData;
 | |
|   
 | |
|   if (KeyData == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   
 | |
|   //
 | |
|   // Enter critical section
 | |
|   //
 | |
|   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | |
| 
 | |
|   if (ConsoleInDev->KeyboardErr) {
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // If there's no key, just return
 | |
|   //
 | |
|   Status = KeyboardCheckForKey (&ConsoleInDev->ConIn);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return EFI_NOT_READY;
 | |
|   }
 | |
|   
 | |
|   CopyMem (&KeyData->Key, &ConsoleInDev->Key, sizeof (EFI_INPUT_KEY));
 | |
| 
 | |
|   ConsoleInDev->Key.ScanCode    = SCAN_NULL;          
 | |
|   ConsoleInDev->Key.UnicodeChar = 0x0000;     
 | |
|   CopyMem (&KeyData->KeyState, &ConsoleInDev->KeyState, sizeof (EFI_KEY_STATE));
 | |
|                                           
 | |
|   ConsoleInDev->KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;
 | |
|   ConsoleInDev->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
|   //
 | |
|   //Switch the control value to their original characters. In KeyGetchar() the  CTRL-Alpha characters have been switched to 
 | |
|   // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.
 | |
|   //
 | |
|   CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));
 | |
|   if (ConsoleInDev->Ctrled) {
 | |
|     if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {
 | |
|       if (ConsoleInDev->CapsLock) {
 | |
|         OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + L'A' - 1);
 | |
|       } else {
 | |
|         OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + L'a' - 1);
 | |
|       } 
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Invoke notification functions if exist
 | |
|   //
 | |
|   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, &OriginalKeyData)) { 
 | |
|       CurrentNotify->KeyNotificationFn (&OriginalKeyData);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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;
 | |
|   }
 | |
|   //
 | |
|   // Clear the status of ConsoleIn.Key
 | |
|   //
 | |
|   ConsoleIn->Key.ScanCode     = SCAN_NULL;
 | |
|   ConsoleIn->Key.UnicodeChar  = 0x0000;
 | |
| 
 | |
|   //
 | |
|   // 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);
 | |
|   Status = KeyboardReadKeyStrokeWorker (ConsoleIn, &KeyData);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   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  waitting context
 | |
| 
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| KeyboardWaitForKey (
 | |
|   IN  EFI_EVENT               Event,
 | |
|   IN  VOID                    *Context
 | |
|   )
 | |
| {
 | |
|   EFI_TPL                 OldTpl;
 | |
|   KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
 | |
| 
 | |
|   ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context);
 | |
| 
 | |
|   //
 | |
|   // Enter critical section
 | |
|   //
 | |
|   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | |
| 
 | |
|   if (ConsoleIn->KeyboardErr) {
 | |
|     //
 | |
|     // Leave critical section and return
 | |
|     //
 | |
|     gBS->RestoreTPL (OldTpl);
 | |
|     return ;
 | |
|   }
 | |
|   //
 | |
|   // Someone is waiting on the keyboard event, if there's
 | |
|   // a key pending, signal the event
 | |
|   //
 | |
|   if (!EFI_ERROR (KeyboardCheckForKey (Context))) {
 | |
|     gBS->SignalEvent (Event);
 | |
|   }
 | |
|   //
 | |
|   // Leave critical section and return
 | |
|   //
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   return ;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   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
 | |
|   )
 | |
| 
 | |
| {
 | |
|   KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
 | |
| 
 | |
|   ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (Context); 
 | |
|   KeyboardWaitForKey (Event, &ConsoleInDev->ConIn);
 | |
|   
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Reset the input device and optionaly 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
 | |
|   )
 | |
| 
 | |
| {
 | |
|   EFI_STATUS                            Status;
 | |
|   KEYBOARD_CONSOLE_IN_DEV               *ConsoleInDev;
 | |
|   EFI_TPL                               OldTpl;
 | |
| 
 | |
|   ConsoleInDev = TEXT_INPUT_EX_KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (This); 
 | |
|   if (ConsoleInDev->KeyboardErr) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   Status = ConsoleInDev->ConIn.Reset (
 | |
|                                  &ConsoleInDev->ConIn, 
 | |
|                                  ExtendedVerification
 | |
|                                  );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
 | |
| 
 | |
|   ConsoleInDev->KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID;
 | |
|   ConsoleInDev->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);  
 | |
|   
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|     Reads the next keystroke from the input device. The WaitForKey Event can 
 | |
|     be used to test for existance 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 availiable.
 | |
|     @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 (((ConsoleInDev->KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != EFI_TOGGLE_STATE_VALID) ||
 | |
|       ((*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;
 | |
| 
 | |
|   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;
 | |
|   }
 | |
| 
 | |
|   Status = UpdateStatusLights (ConsoleInDev);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     Status = EFI_DEVICE_ERROR;    
 | |
|   }
 | |
| 
 | |
|   ConsoleInDev->KeyState.KeyToggleState = *KeyToggleState;
 | |
|   
 | |
| 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.
 | |
|     @param KeyNotificationFunction    Points to the function to be called when the key 
 | |
|                                       sequence is typed specified by KeyData.                        
 | |
|     @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 necesssary 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 EFI_HANDLE                        *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->NotifyHandle;        
 | |
|         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;
 | |
|   NewNotify->NotifyHandle      = (EFI_HANDLE) NewNotify;
 | |
|   CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
 | |
|   InsertTailList (&ConsoleInDev->NotifyList, &NewNotify->NotifyEntry);
 | |
| 
 | |
|   *NotifyHandle                = NewNotify->NotifyHandle;  
 | |
|   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 EFI_HANDLE                         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;
 | |
|   } 
 | |
| 
 | |
|   if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature != KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {
 | |
|     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->NotifyHandle == 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;
 | |
| }
 | |
| 
 |