3 Copyright (c) 2006 - 2011, 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
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.
20 GopPrivateIsKeyRegistered (
21 IN EFI_KEY_DATA
*RegsiteredData
,
22 IN EFI_KEY_DATA
*InputData
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.
36 TRUE - Key be pressed matches a registered key.
41 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
43 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
44 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
49 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
51 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
52 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
55 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
56 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
67 GopPrivateMakeCallbackFunction (
69 IN EFI_KEY_DATA
*KeyData
73 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
*CurrentNotify
;
74 GOP_PRIVATE_DATA
*Private
= (GOP_PRIVATE_DATA
*)Context
;
78 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
81 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
,
83 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
85 if (GopPrivateIsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
86 // We could be called at a high TPL so signal an event to call the registered function
88 gBS
->SignalEvent (CurrentNotify
->Event
);
96 GopPrivateBreakCallbackFunction (
98 IN EFI_KEY_DATA
*KeyData
101 KeyMapBreak (KeyData
);
107 // Simple Text In implementation.
111 Reset the input device and optionally run diagnostics
113 @param This Protocol instance pointer.
114 @param ExtendedVerification Driver may perform diagnostics on reset.
116 @retval EFI_SUCCESS The device was reset.
117 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
122 EmuGopSimpleTextInReset (
123 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
124 IN BOOLEAN ExtendedVerification
127 GOP_PRIVATE_DATA
*Private
;
128 EFI_KEY_DATA KeyData
;
131 Private
= GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This
);
132 if (Private
->EmuGraphicsWindow
== NULL
) {
137 // Enter critical section
139 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
142 // A reset is draining the Queue
144 while (Private
->EmuGraphicsWindow
->GetKey (Private
->EmuGraphicsWindow
, &KeyData
) == EFI_SUCCESS
)
148 // Leave critical section and return
150 gBS
->RestoreTPL (OldTpl
);
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.
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.
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
171 EmuGopSimpleTextInReadKeyStroke (
172 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
173 OUT EFI_INPUT_KEY
*Key
176 GOP_PRIVATE_DATA
*Private
;
179 EFI_KEY_DATA KeyData
;
181 Private
= GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This
);
182 if (Private
->EmuGraphicsWindow
== NULL
) {
183 return EFI_NOT_READY
;
187 // Enter critical section
189 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
191 Status
= Private
->EmuGraphicsWindow
->GetKey (Private
->EmuGraphicsWindow
, &KeyData
);
192 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
195 // Leave critical section and return
197 gBS
->RestoreTPL (OldTpl
);
205 SimpleTextIn and SimpleTextInEx Notify Wait Event
207 @param Event Event whose notification function is being invoked.
208 @param Context Pointer to GOP_PRIVATE_DATA.
213 EmuGopSimpleTextInWaitForKey (
218 GOP_PRIVATE_DATA
*Private
;
222 Private
= (GOP_PRIVATE_DATA
*) Context
;
223 if (Private
->EmuGraphicsWindow
== NULL
) {
228 // Enter critical section
230 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
232 Status
= Private
->EmuGraphicsWindow
->CheckKey (Private
->EmuGraphicsWindow
);
233 if (!EFI_ERROR (Status
)) {
235 // If a there is a key in the queue signal our event.
237 gBS
->SignalEvent (Event
);
240 // Leave critical section and return
242 gBS
->RestoreTPL (OldTpl
);
247 // Simple Text Input Ex protocol functions
252 The Reset() function resets the input device hardware. As part
253 of initialization process, the firmware/device will make a quick
254 but reasonable attempt to verify that the device is functioning.
255 If the ExtendedVerification flag is TRUE the firmware may take
256 an extended amount of time to verify the device is operating on
257 reset. Otherwise the reset operation is to occur as quickly as
258 possible. The hardware verification process is not defined by
259 this specification and is left up to the platform firmware or
262 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
264 @param ExtendedVerification Indicates that the driver may
265 perform a more exhaustive
266 verification operation of the
270 @retval EFI_SUCCESS The device was reset.
272 @retval EFI_DEVICE_ERROR The device is not functioning
273 correctly and could not be reset.
278 EmuGopSimpleTextInExResetEx (
279 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
280 IN BOOLEAN ExtendedVerification
285 Reset the input device and optionaly run diagnostics
288 This - Protocol instance pointer.
289 ExtendedVerification - Driver may perform diagnostics on reset.
292 EFI_SUCCESS - The device was reset.
296 GOP_PRIVATE_DATA
*Private
;
298 Private
= GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This
);
306 The function reads the next keystroke from the input device. If
307 there is no pending keystroke the function returns
308 EFI_NOT_READY. If there is a pending keystroke, then
309 KeyData.Key.ScanCode is the EFI scan code defined in Error!
310 Reference source not found. The KeyData.Key.UnicodeChar is the
311 actual printable character or is zero if the key does not
312 represent a printable character (control key, function key,
313 etc.). The KeyData.KeyState is shift state for the character
314 reflected in KeyData.Key.UnicodeChar or KeyData.Key.ScanCode .
315 When interpreting the data from this function, it should be
316 noted that if a class of printable characters that are
317 normally adjusted by shift modifiers (e.g. Shift Key + "f"
318 key) would be presented solely as a KeyData.Key.UnicodeChar
319 without the associated shift state. So in the previous example
320 of a Shift Key + "f" key being pressed, the only pertinent
321 data returned would be KeyData.Key.UnicodeChar with the value
322 of "F". This of course would not typically be the case for
323 non-printable characters such as the pressing of the Right
324 Shift Key + F10 key since the corresponding returned data
325 would be reflected both in the KeyData.KeyState.KeyShiftState
326 and KeyData.Key.ScanCode values. UEFI drivers which implement
327 the EFI_SIMPLE_TEXT_INPUT_EX protocol are required to return
328 KeyData.Key and KeyData.KeyState values. These drivers must
329 always return the most current state of
330 KeyData.KeyState.KeyShiftState and
331 KeyData.KeyState.KeyToggleState. It should also be noted that
332 certain input devices may not be able to produce shift or toggle
333 state information, and in those cases the high order bit in the
334 respective Toggle and Shift state fields should not be active.
337 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
339 @param KeyData A pointer to a buffer that is filled in with
340 the keystroke state data for the key that was
344 @retval EFI_SUCCESS The keystroke information was
347 @retval EFI_NOT_READY There was no keystroke data available.
348 EFI_DEVICE_ERROR The keystroke
349 information was not returned due to
356 EmuGopSimpleTextInExReadKeyStrokeEx (
357 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
358 OUT EFI_KEY_DATA
*KeyData
363 Reads the next keystroke from the input device. The WaitForKey Event can
364 be used to test for existance of a keystroke via WaitForEvent () call.
367 This - Protocol instance pointer.
368 KeyData - A pointer to a buffer that is filled in with the keystroke
369 state data for the key that was pressed.
372 EFI_SUCCESS - The keystroke information was returned.
373 EFI_NOT_READY - There was no keystroke data availiable.
374 EFI_DEVICE_ERROR - The keystroke information was not returned due to
376 EFI_INVALID_PARAMETER - KeyData is NULL.
381 GOP_PRIVATE_DATA
*Private
;
385 if (KeyData
== NULL
) {
386 return EFI_INVALID_PARAMETER
;
389 Private
= GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This
);
390 if (Private
->EmuGraphicsWindow
== NULL
) {
391 return EFI_NOT_READY
;
395 // Enter critical section
397 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
399 Status
= Private
->EmuGraphicsWindow
->GetKey(Private
->EmuGraphicsWindow
, KeyData
);
402 // Leave critical section and return
404 gBS
->RestoreTPL (OldTpl
);
412 The SetState() function allows the input device hardware to
413 have state settings adjusted.
415 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
417 @param KeyToggleState Pointer to the EFI_KEY_TOGGLE_STATE to
418 set the state for the input device.
421 @retval EFI_SUCCESS The device state was set appropriately.
423 @retval EFI_DEVICE_ERROR The device is not functioning
424 correctly and could not have the
427 @retval EFI_UNSUPPORTED The device does not support the
428 ability to have its state set.
433 EmuGopSimpleTextInExSetState (
434 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
435 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
438 GOP_PRIVATE_DATA
*Private
;
442 Private
= GOP_PRIVATE_DATA_FROM_TEXT_IN_THIS (This
);
443 if (Private
->EmuGraphicsWindow
== NULL
) {
444 return EFI_NOT_READY
;
448 // Enter critical section
450 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
452 Status
= Private
->EmuGraphicsWindow
->KeySetState (Private
->EmuGraphicsWindow
, KeyToggleState
);
454 // Leave critical section and return
456 gBS
->RestoreTPL (OldTpl
);
463 SimpleTextIn and SimpleTextInEx Notify Wait Event
465 @param Event Event whose notification function is being invoked.
466 @param Context Pointer to GOP_PRIVATE_DATA.
471 EmuGopRegisterKeyCallback (
476 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
*ExNotify
= (EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
*)Context
;
478 ExNotify
->KeyNotificationFn (&ExNotify
->KeyData
);
484 The RegisterKeystrokeNotify() function registers a function
485 which will be called when a specified keystroke will occur.
487 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
489 @param KeyData A pointer to a buffer that is filled in with
490 the keystroke information for the key that was
493 @param KeyNotificationFunction Points to the function to be
494 called when the key sequence
495 is typed specified by KeyData.
498 @param NotifyHandle Points to the unique handle assigned to
499 the registered notification.
501 @retval EFI_SUCCESS The device state was set
504 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary
510 EmuGopSimpleTextInExRegisterKeyNotify (
511 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
512 IN EFI_KEY_DATA
*KeyData
,
513 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
514 OUT EFI_HANDLE
*NotifyHandle
518 GOP_PRIVATE_DATA
*Private
;
519 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
*CurrentNotify
;
521 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
*NewNotify
;
523 if (KeyData
== NULL
|| KeyNotificationFunction
== NULL
|| NotifyHandle
== NULL
) {
524 return EFI_INVALID_PARAMETER
;
527 Private
= GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This
);
530 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
532 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
535 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
,
537 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
539 if (GopPrivateIsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
540 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
541 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
548 // Allocate resource to save the notification function
550 NewNotify
= (EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
*) AllocateZeroPool (sizeof (EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
));
551 if (NewNotify
== NULL
) {
552 return EFI_OUT_OF_RESOURCES
;
555 NewNotify
->Signature
= EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
;
556 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
557 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
558 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (KeyData
));
559 InsertTailList (&Private
->NotifyList
, &NewNotify
->NotifyEntry
);
561 Status
= gBS
->CreateEvent (
564 EmuGopRegisterKeyCallback
,
568 ASSERT_EFI_ERROR (Status
);
571 *NotifyHandle
= NewNotify
->NotifyHandle
;
579 The UnregisterKeystrokeNotify() function removes the
580 notification which was previously registered.
582 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
584 @param NotificationHandle The handle of the notification
585 function being unregistered.
587 @retval EFI_SUCCESS The device state was set appropriately.
589 @retval EFI_INVALID_PARAMETER The NotificationHandle is
595 EmuGopSimpleTextInExUnregisterKeyNotify (
596 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
597 IN EFI_HANDLE NotificationHandle
602 Remove a registered notification function from a particular keystroke.
605 This - Protocol instance pointer.
606 NotificationHandle - The handle of the notification function being unregistered.
609 EFI_SUCCESS - The notification function was unregistered successfully.
610 EFI_INVALID_PARAMETER - The NotificationHandle is invalid.
614 GOP_PRIVATE_DATA
*Private
;
616 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
*CurrentNotify
;
618 if (NotificationHandle
== NULL
) {
619 return EFI_INVALID_PARAMETER
;
622 if (((EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
) {
623 return EFI_INVALID_PARAMETER
;
626 Private
= GOP_PRIVATE_DATA_FROM_TEXT_IN_EX_THIS (This
);
628 for (Link
= Private
->NotifyList
.ForwardLink
; Link
!= &Private
->NotifyList
; Link
= Link
->ForwardLink
) {
631 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY
,
633 EMU_GOP_SIMPLE_TEXTIN_EX_NOTIFY_SIGNATURE
635 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
637 // Remove the notification function from NotifyList and free resources
639 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
641 gBS
->CloseEvent (CurrentNotify
->Event
);
643 gBS
->FreePool (CurrentNotify
);
649 // Can not find the specified Notification Handle
651 return EFI_INVALID_PARAMETER
;
657 Initialize SimplelTextIn and SimpleTextInEx protocols in the Private
660 @param Private Context structure to fill in.
662 @return EFI_SUCCESS Initialization was a success
666 EmuGopInitializeSimpleTextInForWindow (
667 IN GOP_PRIVATE_DATA
*Private
673 // Initialize Simple Text In protoocol
675 Private
->SimpleTextIn
.Reset
= EmuGopSimpleTextInReset
;
676 Private
->SimpleTextIn
.ReadKeyStroke
= EmuGopSimpleTextInReadKeyStroke
;
678 Status
= gBS
->CreateEvent (
681 EmuGopSimpleTextInWaitForKey
,
683 &Private
->SimpleTextIn
.WaitForKey
685 ASSERT_EFI_ERROR (Status
);
689 // Initialize Simple Text In Ex
692 Private
->SimpleTextInEx
.Reset
= EmuGopSimpleTextInExResetEx
;
693 Private
->SimpleTextInEx
.ReadKeyStrokeEx
= EmuGopSimpleTextInExReadKeyStrokeEx
;
694 Private
->SimpleTextInEx
.SetState
= EmuGopSimpleTextInExSetState
;
695 Private
->SimpleTextInEx
.RegisterKeyNotify
= EmuGopSimpleTextInExRegisterKeyNotify
;
696 Private
->SimpleTextInEx
.UnregisterKeyNotify
= EmuGopSimpleTextInExUnregisterKeyNotify
;
698 Private
->SimpleTextInEx
.Reset (&Private
->SimpleTextInEx
, FALSE
);
700 InitializeListHead (&Private
->NotifyList
);
702 Status
= gBS
->CreateEvent (
705 EmuGopSimpleTextInWaitForKey
,
707 &Private
->SimpleTextInEx
.WaitForKeyEx
709 ASSERT_EFI_ERROR (Status
);
722 // Simple Pointer implementation.
727 Resets the pointer device hardware.
729 @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL
731 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
732 verification operation of the device during reset.
734 @retval EFI_SUCCESS The device was reset.
735 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
740 EmuGopSimplePointerReset (
741 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
742 IN BOOLEAN ExtendedVerification
745 GOP_PRIVATE_DATA
*Private
;
746 EFI_SIMPLE_POINTER_STATE State
;
749 Private
= GOP_PRIVATE_DATA_FROM_POINTER_MODE_THIS (This
);
750 if (Private
->EmuGraphicsWindow
== NULL
) {
755 // Enter critical section
757 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
760 // A reset is draining the Queue
762 while (Private
->EmuGraphicsWindow
->GetPointerState (Private
->EmuGraphicsWindow
, &State
) == EFI_SUCCESS
)
766 // Leave critical section and return
768 gBS
->RestoreTPL (OldTpl
);
774 Retrieves the current state of a pointer device.
776 @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL
778 @param State A pointer to the state information on the pointer device.
780 @retval EFI_SUCCESS The state of the pointer device was returned in State.
781 @retval EFI_NOT_READY The state of the pointer device has not changed since the last call to
783 @retval EFI_DEVICE_ERROR A device error occurred while attempting to retrieve the pointer device's
789 EmuGopSimplePointerGetState (
790 IN EFI_SIMPLE_POINTER_PROTOCOL
*This
,
791 IN OUT EFI_SIMPLE_POINTER_STATE
*State
794 GOP_PRIVATE_DATA
*Private
;
798 Private
= GOP_PRIVATE_DATA_FROM_POINTER_MODE_THIS (This
);
799 if (Private
->EmuGraphicsWindow
== NULL
) {
800 return EFI_NOT_READY
;
804 // Enter critical section
806 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
808 Status
= Private
->EmuGraphicsWindow
->GetPointerState (Private
->EmuGraphicsWindow
, State
);
810 // Leave critical section and return
812 gBS
->RestoreTPL (OldTpl
);
819 SimplePointer Notify Wait Event
821 @param Event Event whose notification function is being invoked.
822 @param Context Pointer to GOP_PRIVATE_DATA.
827 EmuGopSimplePointerWaitForInput (
832 GOP_PRIVATE_DATA
*Private
;
836 Private
= (GOP_PRIVATE_DATA
*) Context
;
837 if (Private
->EmuGraphicsWindow
== NULL
) {
842 // Enter critical section
844 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
846 Status
= Private
->EmuGraphicsWindow
->CheckPointer (Private
->EmuGraphicsWindow
);
847 if (!EFI_ERROR (Status
)) {
849 // If the pointer state has changed, signal our event.
851 gBS
->SignalEvent (Event
);
854 // Leave critical section and return
856 gBS
->RestoreTPL (OldTpl
);
861 SimplePointer constructor
863 @param Private Context structure to fill in.
865 @retval EFI_SUCCESS Constructor had success
869 EmuGopInitializeSimplePointerForWindow (
870 IN GOP_PRIVATE_DATA
*Private
876 // Initialize Simple Pointer protoocol
878 Private
->PointerMode
.ResolutionX
= 1;
879 Private
->PointerMode
.ResolutionY
= 1;
880 Private
->PointerMode
.ResolutionZ
= 1;
881 Private
->PointerMode
.LeftButton
= TRUE
;
882 Private
->PointerMode
.RightButton
= TRUE
;
884 Private
->SimplePointer
.Reset
= EmuGopSimplePointerReset
;
885 Private
->SimplePointer
.GetState
= EmuGopSimplePointerGetState
;
886 Private
->SimplePointer
.Mode
= &Private
->PointerMode
;
888 Status
= gBS
->CreateEvent (
891 EmuGopSimplePointerWaitForInput
,
893 &Private
->SimplePointer
.WaitForInput