Home | History | Annotate | Download | only in EmuGopDxe
      1 /*++ @file
      2 
      3 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      4 Portions copyright (c) 2010 0 2011,Apple Inc. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 
     14 **/
     15 
     16 #include "Gop.h"
     17 
     18 
     19 BOOLEAN
     20 GopPrivateIsKeyRegistered (
     21   IN EFI_KEY_DATA  *RegsiteredData,
     22   IN EFI_KEY_DATA  *InputData
     23   )
     24 /*++
     25 
     26 Routine Description:
     27 
     28 Arguments:
     29 
     30   RegsiteredData    - A pointer to a buffer that is filled in with the keystroke
     31                       state data for the key that was registered.
     32   InputData         - A pointer to a buffer that is filled in with the keystroke
     33                       state data for the key that was pressed.
     34 
     35 Returns:
     36   TRUE              - Key be pressed matches a registered key.
     37   FLASE             - Match failed.
     38 
     39 **/
     40 {
     41   ASSERT (RegsiteredData != NULL && InputData != NULL);
     42 
     43   if ((RegsiteredData->Key.ScanCode    != InputData->Key.ScanCode) ||
     44       (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {
     45     return FALSE;
     46   }
     47 
     48   //
     49   // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
     50   //
     51   if (RegsiteredData->KeyState.KeyShiftState != 0 &&
     52       RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {
     53     return FALSE;
     54   }
     55   if (RegsiteredData->KeyState.KeyToggleState != 0 &&
     56       RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {
     57     return FALSE;
     58   }
     59 
     60   return TRUE;
     61 
     62 }
     63 
     64 
     65 VOID
     66 EFIAPI
     67 GopPrivateMakeCallbackFunction (
     68   IN VOID           *Context,
     69   IN EFI_KEY_DATA   *KeyData
     70   )
     71 {
     72   LIST_ENTRY                        *Link;
     73   EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY  *CurrentNotify;
     74   GOP_PRIVATE_DATA                  *Private = (GOP_PRIVATE_DATA *)Context;
     75 
     76   KeyMapMake (KeyData);
     77 
     78   for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
     79     CurrentNotify = CR (
     80                       Link,
     81                       EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY,
     82                       NotifyEntry,
     83                       EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
     84                       );
     85     if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
     86       // We could be called at a high TPL so signal an event to call the registered function
     87       // at a lower TPL.
     88       gBS->SignalEvent (CurrentNotify->Event);
     89     }
     90   }
     91 }
     92 
     93 
     94 VOID
     95 EFIAPI
     96 GopPrivateBreakCallbackFunction (
     97   IN VOID           *Context,
     98   IN EFI_KEY_DATA   *KeyData
     99   )
    100 {
    101   KeyMapBreak (KeyData);
    102 }
    103 
    104 
    105 
    106 //
    107 // Simple Text In implementation.
    108 //
    109 
    110 /**
    111   Reset the input device and optionally run diagnostics
    112 
    113   @param  This                 Protocol instance pointer.
    114   @param  ExtendedVerification Driver may perform diagnostics on reset.
    115 
    116   @retval EFI_SUCCESS          The device was reset.
    117   @retval EFI_DEVICE_ERROR     The device is not functioning properly and could not be reset.
    118 
    119 **/
    120 EFI_STATUS
    121 EFIAPI
    122 EmuGopSimpleTextInReset (
    123   IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL       *This,
    124   IN BOOLEAN                              ExtendedVerification
    125   )
    126 {
    127   GOP_PRIVATE_DATA  *Private;
    128   EFI_KEY_DATA      KeyData;
    129   EFI_TPL           OldTpl;
    130 
    131   Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This);
    132   if (Private->EmuGraphicsWindow == NULL) {
    133     return EFI_SUCCESS;
    134   }
    135 
    136   //
    137   // Enter critical section
    138   //
    139   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    140 
    141   //
    142   // A reset is draining the Queue
    143   //
    144   while (Private->EmuGraphicsWindow->GetKey (Private->EmuGraphicsWindow, &KeyData) == EFI_SUCCESS)
    145     ;
    146 
    147   //
    148   // Leave critical section and return
    149   //
    150   gBS->RestoreTPL (OldTpl);
    151   return EFI_SUCCESS;
    152 }
    153 
    154 
    155 /**
    156   Reads the next keystroke from the input device. The WaitForKey Event can
    157   be used to test for existence of a keystroke via WaitForEvent () call.
    158 
    159   @param  This  Protocol instance pointer.
    160   @param  Key   A pointer to a buffer that is filled in with the keystroke
    161                 information for the key that was pressed.
    162 
    163   @retval EFI_SUCCESS      The keystroke information was returned.
    164   @retval EFI_NOT_READY    There was no keystroke data available.
    165   @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
    166                            hardware errors.
    167 
    168 **/
    169 EFI_STATUS
    170 EFIAPI
    171 EmuGopSimpleTextInReadKeyStroke (
    172   IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL       *This,
    173   OUT EFI_INPUT_KEY                       *Key
    174   )
    175 {
    176   GOP_PRIVATE_DATA  *Private;
    177   EFI_STATUS        Status;
    178   EFI_TPL           OldTpl;
    179   EFI_KEY_DATA      KeyData;
    180 
    181   Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This);
    182   if (Private->EmuGraphicsWindow == NULL) {
    183     return EFI_NOT_READY;
    184   }
    185 
    186   //
    187   // Enter critical section
    188   //
    189   OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
    190 
    191   Status  = Private->EmuGraphicsWindow->GetKey (Private->EmuGraphicsWindow, &KeyData);
    192   if (!EFI_ERROR (Status)) {
    193     if ((KeyData.Key.ScanCode == 0) && (KeyData.Key.UnicodeChar == 0)) {
    194       // Modifier key was pressed
    195       Status = EFI_NOT_READY;
    196     } else {
    197       CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
    198     }
    199   }
    200 
    201   //
    202   // Leave critical section and return
    203   //
    204   gBS->RestoreTPL (OldTpl);
    205 
    206   return Status;
    207 }
    208 
    209 
    210 
    211 /**
    212   SimpleTextIn and SimpleTextInEx Notify Wait Event
    213 
    214   @param  Event                 Event whose notification function is being invoked.
    215   @param  Context               Pointer to GOP_PRIVATE_DATA.
    216 
    217 **/
    218 VOID
    219 EFIAPI
    220 EmuGopSimpleTextInWaitForKey (
    221   IN EFI_EVENT          Event,
    222   IN VOID               *Context
    223   )
    224 {
    225   GOP_PRIVATE_DATA  *Private;
    226   EFI_STATUS        Status;
    227   EFI_TPL           OldTpl;
    228 
    229   Private = (GOP_PRIVATE_DATA *) Context;
    230   if (Private->EmuGraphicsWindow == NULL) {
    231     return;
    232   }
    233 
    234   //
    235   // Enter critical section
    236   //
    237   OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
    238 
    239   Status  = Private->EmuGraphicsWindow->CheckKey (Private->EmuGraphicsWindow);
    240   if (!EFI_ERROR (Status)) {
    241     //
    242     // If a there is a key in the queue signal our event.
    243     //
    244     gBS->SignalEvent (Event);
    245   }
    246   //
    247   // Leave critical section and return
    248   //
    249   gBS->RestoreTPL (OldTpl);
    250 }
    251 
    252 
    253 //
    254 // Simple Text Input Ex protocol functions
    255 //
    256 
    257 
    258 /**
    259   The Reset() function resets the input device hardware. As part
    260   of initialization process, the firmware/device will make a quick
    261   but reasonable attempt to verify that the device is functioning.
    262   If the ExtendedVerification flag is TRUE the firmware may take
    263   an extended amount of time to verify the device is operating on
    264   reset. Otherwise the reset operation is to occur as quickly as
    265   possible. The hardware verification process is not defined by
    266   this specification and is left up to the platform firmware or
    267   driver to implement.
    268 
    269   @param This                 A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
    270 
    271   @param ExtendedVerification Indicates that the driver may
    272                               perform a more exhaustive
    273                               verification operation of the
    274                               device during reset.
    275 
    276 
    277   @retval EFI_SUCCESS       The device was reset.
    278 
    279   @retval EFI_DEVICE_ERROR  The device is not functioning
    280                             correctly and could not be reset.
    281 
    282 **/
    283 EFI_STATUS
    284 EFIAPI
    285 EmuGopSimpleTextInExResetEx (
    286   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
    287   IN BOOLEAN                            ExtendedVerification
    288   )
    289 /*++
    290 
    291   Routine Description:
    292     Reset the input device and optionaly run diagnostics
    293 
    294   Arguments:
    295     This                 - Protocol instance pointer.
    296     ExtendedVerification - Driver may perform diagnostics on reset.
    297 
    298   Returns:
    299     EFI_SUCCESS           - The device was reset.
    300 
    301 **/
    302 {
    303   return EFI_SUCCESS;
    304 }
    305 
    306 
    307 
    308 /**
    309   The function reads the next keystroke from the input device. If
    310   there is no pending keystroke the function returns
    311   EFI_NOT_READY. If there is a pending keystroke, then
    312   KeyData.Key.ScanCode is the EFI scan code defined in Error!
    313   Reference source not found. The KeyData.Key.UnicodeChar is the
    314   actual printable character or is zero if the key does not
    315   represent a printable character (control key, function key,
    316   etc.). The KeyData.KeyState is shift state for the character
    317   reflected in KeyData.Key.UnicodeChar or KeyData.Key.ScanCode .
    318   When interpreting the data from this function, it should be
    319   noted that if a class of printable characters that are
    320   normally adjusted by shift modifiers (e.g. Shift Key + "f"
    321   key) would be presented solely as a KeyData.Key.UnicodeChar
    322   without the associated shift state. So in the previous example
    323   of a Shift Key + "f" key being pressed, the only pertinent
    324   data returned would be KeyData.Key.UnicodeChar with the value
    325   of "F". This of course would not typically be the case for
    326   non-printable characters such as the pressing of the Right
    327   Shift Key + F10 key since the corresponding returned data
    328   would be reflected both in the KeyData.KeyState.KeyShiftState
    329   and KeyData.Key.ScanCode values. UEFI drivers which implement
    330   the EFI_SIMPLE_TEXT_INPUT_EX protocol are required to return
    331   KeyData.Key and KeyData.KeyState values. These drivers must
    332   always return the most current state of
    333   KeyData.KeyState.KeyShiftState and
    334   KeyData.KeyState.KeyToggleState. It should also be noted that
    335   certain input devices may not be able to produce shift or toggle
    336   state information, and in those cases the high order bit in the
    337   respective Toggle and Shift state fields should not be active.
    338 
    339 
    340   @param This     A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
    341 
    342   @param KeyData  A pointer to a buffer that is filled in with
    343                   the keystroke state data for the key that was
    344                   pressed.
    345 
    346 
    347   @retval EFI_SUCCESS     The keystroke information was
    348                           returned.
    349 
    350   @retval EFI_NOT_READY   There was no keystroke data available.
    351                           EFI_DEVICE_ERROR The keystroke
    352                           information was not returned due to
    353                           hardware errors.
    354 
    355 
    356 **/
    357 EFI_STATUS
    358 EFIAPI
    359 EmuGopSimpleTextInExReadKeyStrokeEx (
    360   IN  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
    361   OUT EFI_KEY_DATA                      *KeyData
    362   )
    363 /*++
    364 
    365   Routine Description:
    366     Reads the next keystroke from the input device. The WaitForKey Event can
    367     be used to test for existance of a keystroke via WaitForEvent () call.
    368 
    369   Arguments:
    370     This       - Protocol instance pointer.
    371     KeyData    - A pointer to a buffer that is filled in with the keystroke
    372                  state data for the key that was pressed.
    373 
    374   Returns:
    375     EFI_SUCCESS           - The keystroke information was returned.
    376     EFI_NOT_READY         - There was no keystroke data availiable.
    377     EFI_DEVICE_ERROR      - The keystroke information was not returned due to
    378                             hardware errors.
    379     EFI_INVALID_PARAMETER - KeyData is NULL.
    380 
    381 **/
    382 {
    383   EFI_STATUS        Status;
    384   GOP_PRIVATE_DATA  *Private;
    385   EFI_TPL           OldTpl;
    386 
    387 
    388   if (KeyData == NULL) {
    389     return EFI_INVALID_PARAMETER;
    390   }
    391 
    392   Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);
    393   if (Private->EmuGraphicsWindow == NULL) {
    394     return EFI_NOT_READY;
    395   }
    396 
    397   //
    398   // Enter critical section
    399   //
    400   OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
    401 
    402   Status  = Private->EmuGraphicsWindow->GetKey(Private->EmuGraphicsWindow, KeyData);
    403 
    404   //
    405   // Leave critical section and return
    406   //
    407   gBS->RestoreTPL (OldTpl);
    408 
    409   return Status;
    410 }
    411 
    412 
    413 
    414 /**
    415   The SetState() function allows the input device hardware to
    416   have state settings adjusted.
    417 
    418   @param This           A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
    419 
    420   @param KeyToggleState Pointer to the EFI_KEY_TOGGLE_STATE to
    421                         set the state for the input device.
    422 
    423 
    424   @retval EFI_SUCCESS       The device state was set appropriately.
    425 
    426   @retval EFI_DEVICE_ERROR  The device is not functioning
    427                             correctly and could not have the
    428                             setting adjusted.
    429 
    430   @retval EFI_UNSUPPORTED   The device does not support the
    431                             ability to have its state set.
    432 
    433 **/
    434 EFI_STATUS
    435 EFIAPI
    436 EmuGopSimpleTextInExSetState (
    437   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
    438   IN EFI_KEY_TOGGLE_STATE               *KeyToggleState
    439   )
    440 {
    441   GOP_PRIVATE_DATA  *Private;
    442   EFI_STATUS        Status;
    443   EFI_TPL           OldTpl;
    444 
    445   Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);
    446   if (Private->EmuGraphicsWindow == NULL) {
    447     return EFI_NOT_READY;
    448   }
    449 
    450   //
    451   // Enter critical section
    452   //
    453   OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
    454 
    455   Status  = Private->EmuGraphicsWindow->KeySetState (Private->EmuGraphicsWindow, KeyToggleState);
    456   //
    457   // Leave critical section and return
    458   //
    459   gBS->RestoreTPL (OldTpl);
    460 
    461   return Status;
    462 }
    463 
    464 
    465 /**
    466   SimpleTextIn and SimpleTextInEx Notify Wait Event
    467 
    468   @param  Event                 Event whose notification function is being invoked.
    469   @param  Context               Pointer to GOP_PRIVATE_DATA.
    470 
    471 **/
    472 VOID
    473 EFIAPI
    474 EmuGopRegisterKeyCallback (
    475   IN EFI_EVENT          Event,
    476   IN VOID               *Context
    477   )
    478 {
    479   EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY *ExNotify = (EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY *)Context;
    480 
    481   ExNotify->KeyNotificationFn (&ExNotify->KeyData);
    482 }
    483 
    484 
    485 
    486 /**
    487   The RegisterKeystrokeNotify() function registers a function
    488   which will be called when a specified keystroke will occur.
    489 
    490   @param This                     A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
    491 
    492   @param KeyData                  A pointer to a buffer that is filled in with
    493                                   the keystroke information for the key that was
    494                                   pressed.
    495 
    496   @param KeyNotificationFunction  Points to the function to be
    497                                   called when the key sequence
    498                                   is typed specified by KeyData.
    499 
    500 
    501   @param NotifyHandle             Points to the unique handle assigned to
    502                                   the registered notification.
    503 
    504   @retval EFI_SUCCESS           The device state was set
    505                                 appropriately.
    506 
    507   @retval EFI_OUT_OF_RESOURCES  Unable to allocate necessary
    508                                 data structures.
    509 
    510 **/
    511 EFI_STATUS
    512 EFIAPI
    513 EmuGopSimpleTextInExRegisterKeyNotify (
    514   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
    515   IN EFI_KEY_DATA                       *KeyData,
    516   IN EFI_KEY_NOTIFY_FUNCTION            KeyNotificationFunction,
    517   OUT EFI_HANDLE                        *NotifyHandle
    518   )
    519 {
    520   EFI_STATUS                          Status;
    521   GOP_PRIVATE_DATA                    *Private;
    522   EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY     *CurrentNotify;
    523   LIST_ENTRY                          *Link;
    524   EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY     *NewNotify;
    525 
    526   if (KeyData == NULL || KeyNotificationFunction == NULL || NotifyHandle == NULL) {
    527     return EFI_INVALID_PARAMETER;
    528   }
    529 
    530   Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);
    531 
    532   //
    533   // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
    534   //
    535   for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
    536     CurrentNotify = CR (
    537                       Link,
    538                       EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY,
    539                       NotifyEntry,
    540                       EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
    541                       );
    542     if (GopPrivateIsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
    543       if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
    544         *NotifyHandle = CurrentNotify->NotifyHandle;
    545         return EFI_SUCCESS;
    546       }
    547     }
    548   }
    549 
    550   //
    551   // Allocate resource to save the notification function
    552   //
    553   NewNotify = (EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) AllocateZeroPool (sizeof (EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY));
    554   if (NewNotify == NULL) {
    555     return EFI_OUT_OF_RESOURCES;
    556   }
    557 
    558   NewNotify->Signature         = EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE;
    559   NewNotify->KeyNotificationFn = KeyNotificationFunction;
    560   NewNotify->NotifyHandle      = (EFI_HANDLE) NewNotify;
    561   CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));
    562   InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);
    563 
    564   Status = gBS->CreateEvent (
    565                   EVT_NOTIFY_SIGNAL,
    566                   TPL_NOTIFY,
    567                   EmuGopRegisterKeyCallback,
    568                   NewNotify,
    569                   &NewNotify->Event
    570                   );
    571   ASSERT_EFI_ERROR (Status);
    572 
    573 
    574   *NotifyHandle = NewNotify->NotifyHandle;
    575 
    576   return EFI_SUCCESS;
    577 
    578 }
    579 
    580 
    581 /**
    582   The UnregisterKeystrokeNotify() function removes the
    583   notification which was previously registered.
    584 
    585   @param This               A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
    586 
    587   @param NotificationHandle The handle of the notification
    588                             function being unregistered.
    589 
    590   @retval EFI_SUCCESS The device state was set appropriately.
    591 
    592   @retval EFI_INVALID_PARAMETER The NotificationHandle is
    593                                 invalid.
    594 
    595 **/
    596 EFI_STATUS
    597 EFIAPI
    598 EmuGopSimpleTextInExUnregisterKeyNotify (
    599   IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL  *This,
    600   IN EFI_HANDLE                         NotificationHandle
    601   )
    602 /*++
    603 
    604   Routine Description:
    605     Remove a registered notification function from a particular keystroke.
    606 
    607   Arguments:
    608     This                    - Protocol instance pointer.
    609     NotificationHandle      - The handle of the notification function being unregistered.
    610 
    611   Returns:
    612     EFI_SUCCESS             - The notification function was unregistered successfully.
    613     EFI_INVALID_PARAMETER   - The NotificationHandle is invalid.
    614 
    615 **/
    616 {
    617   GOP_PRIVATE_DATA                   *Private;
    618   LIST_ENTRY                         *Link;
    619   EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY *CurrentNotify;
    620 
    621   if (NotificationHandle == NULL) {
    622     return EFI_INVALID_PARAMETER;
    623   }
    624 
    625   if (((EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY *) NotificationHandle)->Signature != EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE) {
    626     return EFI_INVALID_PARAMETER;
    627   }
    628 
    629   Private = GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This);
    630 
    631   for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {
    632     CurrentNotify = CR (
    633                       Link,
    634                       EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY,
    635                       NotifyEntry,
    636                       EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
    637                       );
    638     if (CurrentNotify->NotifyHandle == NotificationHandle) {
    639       //
    640       // Remove the notification function from NotifyList and free resources
    641       //
    642       RemoveEntryList (&CurrentNotify->NotifyEntry);
    643 
    644       gBS->CloseEvent (CurrentNotify->Event);
    645 
    646       gBS->FreePool (CurrentNotify);
    647       return EFI_SUCCESS;
    648     }
    649   }
    650 
    651   //
    652   // Can not find the specified Notification Handle
    653   //
    654   return EFI_INVALID_PARAMETER;
    655 }
    656 
    657 
    658 
    659 /**
    660   Initialize SimplelTextIn and SimpleTextInEx protocols in the Private
    661   context structure.
    662 
    663   @param  Private               Context structure to fill in.
    664 
    665   @return EFI_SUCCESS           Initialization was a success
    666 
    667 **/
    668 EFI_STATUS
    669 EmuGopInitializeSimpleTextInForWindow (
    670   IN  GOP_PRIVATE_DATA    *Private
    671   )
    672 {
    673   EFI_STATUS  Status;
    674 
    675   //
    676   // Initialize Simple Text In protoocol
    677   //
    678   Private->SimpleTextIn.Reset         = EmuGopSimpleTextInReset;
    679   Private->SimpleTextIn.ReadKeyStroke = EmuGopSimpleTextInReadKeyStroke;
    680 
    681   Status = gBS->CreateEvent (
    682                   EVT_NOTIFY_WAIT,
    683                   TPL_NOTIFY,
    684                   EmuGopSimpleTextInWaitForKey,
    685                   Private,
    686                   &Private->SimpleTextIn.WaitForKey
    687                   );
    688   ASSERT_EFI_ERROR (Status);
    689 
    690 
    691   //
    692   // Initialize Simple Text In Ex
    693   //
    694 
    695   Private->SimpleTextInEx.Reset               = EmuGopSimpleTextInExResetEx;
    696   Private->SimpleTextInEx.ReadKeyStrokeEx     = EmuGopSimpleTextInExReadKeyStrokeEx;
    697   Private->SimpleTextInEx.SetState            = EmuGopSimpleTextInExSetState;
    698   Private->SimpleTextInEx.RegisterKeyNotify   = EmuGopSimpleTextInExRegisterKeyNotify;
    699   Private->SimpleTextInEx.UnregisterKeyNotify = EmuGopSimpleTextInExUnregisterKeyNotify;
    700 
    701   Private->SimpleTextInEx.Reset (&Private->SimpleTextInEx, FALSE);
    702 
    703   InitializeListHead (&Private->NotifyList);
    704 
    705   Status = gBS->CreateEvent (
    706                   EVT_NOTIFY_WAIT,
    707                   TPL_NOTIFY,
    708                   EmuGopSimpleTextInWaitForKey,
    709                   Private,
    710                   &Private->SimpleTextInEx.WaitForKeyEx
    711                   );
    712   ASSERT_EFI_ERROR (Status);
    713 
    714 
    715   return Status;
    716 }
    717 
    718 
    719 
    720 
    721 
    722 
    723 
    724 //
    725 // Simple Pointer implementation.
    726 //
    727 
    728 
    729 /**
    730   Resets the pointer device hardware.
    731 
    732   @param  This                  A pointer to the EFI_SIMPLE_POINTER_PROTOCOL
    733                                 instance.
    734   @param  ExtendedVerification  Indicates that the driver may perform a more exhaustive
    735                                 verification operation of the device during reset.
    736 
    737   @retval EFI_SUCCESS           The device was reset.
    738   @retval EFI_DEVICE_ERROR      The device is not functioning correctly and could not be reset.
    739 
    740 **/
    741 EFI_STATUS
    742 EFIAPI
    743 EmuGopSimplePointerReset (
    744   IN EFI_SIMPLE_POINTER_PROTOCOL          *This,
    745   IN BOOLEAN                              ExtendedVerification
    746   )
    747 {
    748   GOP_PRIVATE_DATA             *Private;
    749   EFI_SIMPLE_POINTER_STATE     State;
    750   EFI_TPL                      OldTpl;
    751 
    752   Private = GOP_PRIVATE_DATA_FROM_POINTER_MODE_THIS (This);
    753   if (Private->EmuGraphicsWindow == NULL) {
    754     return EFI_SUCCESS;
    755   }
    756 
    757   //
    758   // Enter critical section
    759   //
    760   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
    761 
    762   //
    763   // A reset is draining the Queue
    764   //
    765   while (Private->EmuGraphicsWindow->GetPointerState (Private->EmuGraphicsWindow, &State) == EFI_SUCCESS)
    766     ;
    767 
    768   //
    769   // Leave critical section and return
    770   //
    771   gBS->RestoreTPL (OldTpl);
    772   return EFI_SUCCESS;
    773 }
    774 
    775 
    776 /**
    777   Retrieves the current state of a pointer device.
    778 
    779   @param  This                  A pointer to the EFI_SIMPLE_POINTER_PROTOCOL
    780                                 instance.
    781   @param  State                 A pointer to the state information on the pointer device.
    782 
    783   @retval EFI_SUCCESS           The state of the pointer device was returned in State.
    784   @retval EFI_NOT_READY         The state of the pointer device has not changed since the last call to
    785                                 GetState().
    786   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to retrieve the pointer device's
    787                                 current state.
    788 
    789 **/
    790 EFI_STATUS
    791 EFIAPI
    792 EmuGopSimplePointerGetState (
    793   IN EFI_SIMPLE_POINTER_PROTOCOL          *This,
    794   IN OUT EFI_SIMPLE_POINTER_STATE         *State
    795   )
    796 {
    797   GOP_PRIVATE_DATA  *Private;
    798   EFI_STATUS        Status;
    799   EFI_TPL           OldTpl;
    800 
    801   Private = GOP_PRIVATE_DATA_FROM_POINTER_MODE_THIS (This);
    802   if (Private->EmuGraphicsWindow == NULL) {
    803     return EFI_NOT_READY;
    804   }
    805 
    806   //
    807   // Enter critical section
    808   //
    809   OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
    810 
    811   Status  = Private->EmuGraphicsWindow->GetPointerState (Private->EmuGraphicsWindow, State);
    812   //
    813   // Leave critical section and return
    814   //
    815   gBS->RestoreTPL (OldTpl);
    816 
    817   return Status;
    818 }
    819 
    820 
    821 /**
    822   SimplePointer Notify Wait Event
    823 
    824   @param  Event                 Event whose notification function is being invoked.
    825   @param  Context               Pointer to GOP_PRIVATE_DATA.
    826 
    827 **/
    828 VOID
    829 EFIAPI
    830 EmuGopSimplePointerWaitForInput (
    831   IN EFI_EVENT          Event,
    832   IN VOID               *Context
    833   )
    834 {
    835   GOP_PRIVATE_DATA  *Private;
    836   EFI_STATUS        Status;
    837   EFI_TPL           OldTpl;
    838 
    839   Private = (GOP_PRIVATE_DATA *) Context;
    840   if (Private->EmuGraphicsWindow == NULL) {
    841     return;
    842   }
    843 
    844   //
    845   // Enter critical section
    846   //
    847   OldTpl  = gBS->RaiseTPL (TPL_NOTIFY);
    848 
    849   Status  = Private->EmuGraphicsWindow->CheckPointer (Private->EmuGraphicsWindow);
    850   if (!EFI_ERROR (Status)) {
    851     //
    852     // If the pointer state has changed, signal our event.
    853     //
    854     gBS->SignalEvent (Event);
    855   }
    856   //
    857   // Leave critical section and return
    858   //
    859   gBS->RestoreTPL (OldTpl);
    860 }
    861 
    862 
    863 /**
    864   SimplePointer constructor
    865 
    866   @param  Private Context structure to fill in.
    867 
    868   @retval EFI_SUCCESS Constructor had success
    869 
    870 **/
    871 EFI_STATUS
    872 EmuGopInitializeSimplePointerForWindow (
    873   IN  GOP_PRIVATE_DATA    *Private
    874   )
    875 {
    876   EFI_STATUS  Status;
    877 
    878   //
    879   // Initialize Simple Pointer protoocol
    880   //
    881   Private->PointerMode.ResolutionX = 1;
    882   Private->PointerMode.ResolutionY = 1;
    883   Private->PointerMode.ResolutionZ = 1;
    884   Private->PointerMode.LeftButton  = TRUE;
    885   Private->PointerMode.RightButton = TRUE;
    886 
    887   Private->SimplePointer.Reset     = EmuGopSimplePointerReset;
    888   Private->SimplePointer.GetState  = EmuGopSimplePointerGetState;
    889   Private->SimplePointer.Mode      = &Private->PointerMode;
    890 
    891   Status = gBS->CreateEvent (
    892                   EVT_NOTIFY_WAIT,
    893                   TPL_NOTIFY,
    894                   EmuGopSimplePointerWaitForInput,
    895                   Private,
    896                   &Private->SimplePointer.WaitForInput
    897                   );
    898 
    899   return Status;
    900 }
    901