4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions
9 of the BSD License which accompanies this distribution. The
10 full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "VirtualKeyboard.h"
21 // RAM Keyboard Driver Binding Protocol Instance
23 EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding
= {
24 VirtualKeyboardDriverBindingSupported
,
25 VirtualKeyboardDriverBindingStart
,
26 VirtualKeyboardDriverBindingStop
,
33 // EFI Driver Binding Protocol Functions
37 Check whether the driver supports this device.
39 @param This The Udriver binding protocol.
40 @param Controller The controller handle to check.
41 @param RemainingDevicePath The remaining device path.
43 @retval EFI_SUCCESS The driver supports this controller.
44 @retval other This device isn't supported.
49 VirtualKeyboardDriverBindingSupported (
50 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
51 IN EFI_HANDLE Controller
,
52 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
56 PLATFORM_VIRTUAL_KBD_PROTOCOL
*PlatformVirtual
;
58 Status
= gBS
->OpenProtocol (
60 &gPlatformVirtualKeyboardProtocolGuid
,
61 (VOID
**) &PlatformVirtual
,
62 This
->DriverBindingHandle
,
64 EFI_OPEN_PROTOCOL_BY_DRIVER
66 if (EFI_ERROR (Status
)) {
71 &gPlatformVirtualKeyboardProtocolGuid
,
72 This
->DriverBindingHandle
,
79 Starts the device with this driver.
81 @param This The driver binding instance.
82 @param Controller Handle of device to bind driver to.
83 @param RemainingDevicePath Optional parameter use to pick a specific child
86 @retval EFI_SUCCESS The controller is controlled by the driver.
87 @retval Other This controller cannot be started.
92 VirtualKeyboardDriverBindingStart (
93 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
94 IN EFI_HANDLE Controller
,
95 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
99 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
100 PLATFORM_VIRTUAL_KBD_PROTOCOL
*PlatformVirtual
;
102 Status
= gBS
->OpenProtocol (
104 &gPlatformVirtualKeyboardProtocolGuid
,
105 (VOID
**) &PlatformVirtual
,
106 This
->DriverBindingHandle
,
108 EFI_OPEN_PROTOCOL_BY_DRIVER
110 if (EFI_ERROR (Status
)) {
115 // Allocate the private device structure
117 VirtualKeyboardPrivate
= (VIRTUAL_KEYBOARD_DEV
*) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_DEV
));
118 if (VirtualKeyboardPrivate
== NULL
) {
119 Status
= EFI_OUT_OF_RESOURCES
;
124 // Initialize the private device structure
126 VirtualKeyboardPrivate
->Signature
= VIRTUAL_KEYBOARD_DEV_SIGNATURE
;
127 VirtualKeyboardPrivate
->Handle
= Controller
;
128 VirtualKeyboardPrivate
->PlatformVirtual
= PlatformVirtual
;
129 VirtualKeyboardPrivate
->Queue
.Front
= 0;
130 VirtualKeyboardPrivate
->Queue
.Rear
= 0;
131 VirtualKeyboardPrivate
->QueueForNotify
.Front
= 0;
132 VirtualKeyboardPrivate
->QueueForNotify
.Rear
= 0;
134 VirtualKeyboardPrivate
->SimpleTextIn
.Reset
= VirtualKeyboardReset
;
135 VirtualKeyboardPrivate
->SimpleTextIn
.ReadKeyStroke
= VirtualKeyboardReadKeyStroke
;
137 VirtualKeyboardPrivate
->SimpleTextInputEx
.Reset
= VirtualKeyboardResetEx
;
138 VirtualKeyboardPrivate
->SimpleTextInputEx
.ReadKeyStrokeEx
= VirtualKeyboardReadKeyStrokeEx
;
139 VirtualKeyboardPrivate
->SimpleTextInputEx
.SetState
= VirtualKeyboardSetState
;
141 VirtualKeyboardPrivate
->SimpleTextInputEx
.RegisterKeyNotify
= VirtualKeyboardRegisterKeyNotify
;
142 VirtualKeyboardPrivate
->SimpleTextInputEx
.UnregisterKeyNotify
= VirtualKeyboardUnregisterKeyNotify
;
143 InitializeListHead (&VirtualKeyboardPrivate
->NotifyList
);
145 Status
= PlatformVirtual
->Register ();
146 if (EFI_ERROR (Status
)) {
151 // Report that the keyboard is being enabled
155 EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_ENABLE
159 // Setup the WaitForKey event
161 Status
= gBS
->CreateEvent (
164 VirtualKeyboardWaitForKey
,
165 &(VirtualKeyboardPrivate
->SimpleTextIn
),
166 &((VirtualKeyboardPrivate
->SimpleTextIn
).WaitForKey
)
168 if (EFI_ERROR (Status
)) {
169 (VirtualKeyboardPrivate
->SimpleTextIn
).WaitForKey
= NULL
;
172 Status
= gBS
->CreateEvent (
175 VirtualKeyboardWaitForKeyEx
,
176 &(VirtualKeyboardPrivate
->SimpleTextInputEx
),
177 &(VirtualKeyboardPrivate
->SimpleTextInputEx
.WaitForKeyEx
)
179 if (EFI_ERROR (Status
)) {
180 VirtualKeyboardPrivate
->SimpleTextInputEx
.WaitForKeyEx
= NULL
;
185 // Setup a periodic timer, used for reading keystrokes at a fixed interval
187 Status
= gBS
->CreateEvent (
188 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
190 VirtualKeyboardTimerHandler
,
191 VirtualKeyboardPrivate
,
192 &VirtualKeyboardPrivate
->TimerEvent
194 if (EFI_ERROR (Status
)) {
195 Status
= EFI_OUT_OF_RESOURCES
;
199 Status
= gBS
->SetTimer (
200 VirtualKeyboardPrivate
->TimerEvent
,
202 KEYBOARD_TIMER_INTERVAL
204 if (EFI_ERROR (Status
)) {
205 Status
= EFI_OUT_OF_RESOURCES
;
209 Status
= gBS
->CreateEvent (
212 KeyNotifyProcessHandler
,
213 VirtualKeyboardPrivate
,
214 &VirtualKeyboardPrivate
->KeyNotifyProcessEvent
216 if (EFI_ERROR (Status
)) {
217 Status
= EFI_OUT_OF_RESOURCES
;
222 // Reset the keyboard device
224 Status
= VirtualKeyboardPrivate
->SimpleTextInputEx
.Reset (
225 &VirtualKeyboardPrivate
->SimpleTextInputEx
,
228 if (EFI_ERROR (Status
)) {
229 DEBUG ((DEBUG_ERROR
, "[KBD]Reset Failed. Status - %r\n", Status
));
233 // Install protocol interfaces for the keyboard device.
235 Status
= gBS
->InstallMultipleProtocolInterfaces (
237 &gEfiSimpleTextInProtocolGuid
,
238 &VirtualKeyboardPrivate
->SimpleTextIn
,
239 &gEfiSimpleTextInputExProtocolGuid
,
240 &VirtualKeyboardPrivate
->SimpleTextInputEx
,
245 if (EFI_ERROR (Status
)) {
246 if (VirtualKeyboardPrivate
!= NULL
) {
247 if ((VirtualKeyboardPrivate
->SimpleTextIn
).WaitForKey
!= NULL
) {
248 gBS
->CloseEvent ((VirtualKeyboardPrivate
->SimpleTextIn
).WaitForKey
);
251 if ((VirtualKeyboardPrivate
->SimpleTextInputEx
).WaitForKeyEx
!= NULL
) {
253 (VirtualKeyboardPrivate
->SimpleTextInputEx
).WaitForKeyEx
257 if (VirtualKeyboardPrivate
->KeyNotifyProcessEvent
!= NULL
) {
258 gBS
->CloseEvent (VirtualKeyboardPrivate
->KeyNotifyProcessEvent
);
261 VirtualKeyboardFreeNotifyList (&VirtualKeyboardPrivate
->NotifyList
);
263 if (VirtualKeyboardPrivate
->TimerEvent
!= NULL
) {
264 gBS
->CloseEvent (VirtualKeyboardPrivate
->TimerEvent
);
266 FreePool (VirtualKeyboardPrivate
);
272 &gPlatformVirtualKeyboardProtocolGuid
,
273 This
->DriverBindingHandle
,
281 Stop the device handled by this driver.
283 @param This The driver binding protocol.
284 @param Controller The controller to release.
285 @param NumberOfChildren The number of handles in ChildHandleBuffer.
286 @param ChildHandleBuffer The array of child handle.
288 @retval EFI_SUCCESS The device was stopped.
289 @retval EFI_DEVICE_ERROR The device could not be stopped due to a
291 @retval Others Fail to uninstall protocols attached on the
297 VirtualKeyboardDriverBindingStop (
298 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
299 IN EFI_HANDLE Controller
,
300 IN UINTN NumberOfChildren
,
301 IN EFI_HANDLE
*ChildHandleBuffer
311 @param Queue The queue to be enqueued.
312 @param KeyData The key data to be enqueued.
314 @retval EFI_NOT_READY The queue is full.
315 @retval EFI_SUCCESS Successfully enqueued the key data.
320 IN SIMPLE_QUEUE
*Queue
,
321 IN EFI_KEY_DATA
*KeyData
324 if ((Queue
->Rear
+ 1) % QUEUE_MAX_COUNT
== Queue
->Front
) {
325 return EFI_NOT_READY
;
328 CopyMem (&Queue
->Buffer
[Queue
->Rear
], KeyData
, sizeof (EFI_KEY_DATA
));
329 Queue
->Rear
= (Queue
->Rear
+ 1) % QUEUE_MAX_COUNT
;
337 @param Queue The queue to be dequeued.
338 @param KeyData The key data to be dequeued.
340 @retval EFI_NOT_READY The queue is empty.
341 @retval EFI_SUCCESS Successfully dequeued the key data.
346 IN SIMPLE_QUEUE
*Queue
,
347 IN EFI_KEY_DATA
*KeyData
350 if (Queue
->Front
== Queue
->Rear
) {
351 return EFI_NOT_READY
;
354 CopyMem (KeyData
, &Queue
->Buffer
[Queue
->Front
], sizeof (EFI_KEY_DATA
));
355 Queue
->Front
= (Queue
->Front
+ 1) % QUEUE_MAX_COUNT
;
361 Check whether the queue is empty.
363 @param Queue The queue to be checked.
365 @retval EFI_NOT_READY The queue is empty.
366 @retval EFI_SUCCESS The queue is not empty.
371 IN SIMPLE_QUEUE
*Queue
374 if (Queue
->Front
== Queue
->Rear
) {
375 return EFI_NOT_READY
;
382 Check key buffer to get the key stroke status.
384 @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.
386 @retval EFI_SUCCESS A key is being pressed now.
387 @retval Other No key is now pressed.
392 VirtualKeyboardCheckForKey (
393 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
396 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
398 VirtualKeyboardPrivate
= VIRTUAL_KEYBOARD_DEV_FROM_THIS (This
);
400 return CheckQueue (&VirtualKeyboardPrivate
->Queue
);
404 Free keyboard notify list.
406 @param ListHead The list head
408 @retval EFI_SUCCESS Free the notify list successfully
409 @retval EFI_INVALID_PARAMETER ListHead is invalid.
413 VirtualKeyboardFreeNotifyList (
414 IN OUT LIST_ENTRY
*ListHead
417 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
419 if (ListHead
== NULL
) {
420 return EFI_INVALID_PARAMETER
;
422 while (!IsListEmpty (ListHead
)) {
424 ListHead
->ForwardLink
,
425 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
427 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
429 RemoveEntryList (ListHead
->ForwardLink
);
430 gBS
->FreePool (NotifyNode
);
437 Judge whether is a registed key
439 @param RegsiteredData A pointer to a buffer that is filled in with
440 the keystroke state data for the key that was
442 @param InputData A pointer to a buffer that is filled in with
443 the keystroke state data for the key that was
446 @retval TRUE Key be pressed matches a registered key.
447 @retval FLASE Match failed.
452 IN EFI_KEY_DATA
*RegsiteredData
,
453 IN EFI_KEY_DATA
*InputData
457 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
459 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
460 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
465 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means
466 // these state could be ignored.
468 if ((RegsiteredData
->KeyState
.KeyShiftState
!= 0) &&
469 (RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
)) {
472 if ((RegsiteredData
->KeyState
.KeyToggleState
!= 0) &&
473 (RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
)) {
482 Event notification function for SIMPLE_TEXT_IN.WaitForKey event
483 Signal the event if there is key available
485 @param Event the event object
486 @param Context waitting context
491 VirtualKeyboardWaitForKey (
497 // Stall 1ms to give a chance to let other driver interrupt this routine
498 // for their timer event.
499 // e.g. UI setup or Shell, other drivers which are driven by timer event
500 // will have a bad performance during this period,
501 // e.g. usb keyboard driver.
502 // Add a stall period can greatly increate other driver performance during
503 // the WaitForKey is recursivly invoked. 1ms delay will make little impact
504 // to the thunk keyboard driver, and user can not feel the delay at all when
509 // Use TimerEvent callback function to check whether there's any key pressed
511 VirtualKeyboardTimerHandler (NULL
, VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context
));
513 if (!EFI_ERROR (VirtualKeyboardCheckForKey (Context
))) {
514 gBS
->SignalEvent (Event
);
519 Event notification function for SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
520 event. Signal the event if there is key available
522 @param Event event object
523 @param Context waiting context
528 VirtualKeyboardWaitForKeyEx (
534 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
536 VirtualKeyboardPrivate
= TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context
);
537 VirtualKeyboardWaitForKey (Event
, &VirtualKeyboardPrivate
->SimpleTextIn
);
542 // EFI Simple Text In Protocol Functions
545 Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE)
546 then do some extra keyboard validations.
548 @param This Pointer of simple text Protocol.
549 @param ExtendedVerification Whether perform the extra validation of
550 keyboard. True: perform; FALSE: skip.
552 @retval EFI_SUCCESS The command byte is written successfully.
553 @retval EFI_DEVICE_ERROR Errors occurred during resetting keyboard.
558 VirtualKeyboardReset (
559 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
560 IN BOOLEAN ExtendedVerification
563 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
567 VirtualKeyboardPrivate
= VIRTUAL_KEYBOARD_DEV_FROM_THIS (This
);
570 // Raise TPL to avoid mouse operation impact
572 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
574 if (VirtualKeyboardPrivate
->PlatformVirtual
&&
575 VirtualKeyboardPrivate
->PlatformVirtual
->Reset
) {
576 Status
= VirtualKeyboardPrivate
->PlatformVirtual
->Reset ();
578 Status
= EFI_INVALID_PARAMETER
;
582 // resume priority of task level
584 gBS
->RestoreTPL (OldTpl
);
590 Reset the input device and optionaly run diagnostics
592 @param This Protocol instance pointer.
593 @param ExtendedVerification Driver may perform diagnostics on reset.
595 @retval EFI_SUCCESS The device was reset.
596 @retval EFI_DEVICE_ERROR The device is not functioning properly and
602 VirtualKeyboardResetEx (
603 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
604 IN BOOLEAN ExtendedVerification
607 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
611 VirtualKeyboardPrivate
= TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This
);
613 Status
= VirtualKeyboardPrivate
->SimpleTextIn
.Reset (
614 &VirtualKeyboardPrivate
->SimpleTextIn
,
617 if (EFI_ERROR (Status
)) {
618 return EFI_DEVICE_ERROR
;
621 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
623 gBS
->RestoreTPL (OldTpl
);
630 Reads the next keystroke from the input device. The WaitForKey Event can
631 be used to test for existance of a keystroke via WaitForEvent () call.
633 @param VirtualKeyboardPrivate Virtualkeyboard driver private structure.
634 @param KeyData A pointer to a buffer that is filled in
635 with the keystroke state data for the key
638 @retval EFI_SUCCESS The keystroke information was returned.
639 @retval EFI_NOT_READY There was no keystroke data availiable.
640 @retval EFI_DEVICE_ERROR The keystroke information was not returned
641 due to hardware errors.
642 @retval EFI_INVALID_PARAMETER KeyData is NULL.
646 KeyboardReadKeyStrokeWorker (
647 IN VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
,
648 OUT EFI_KEY_DATA
*KeyData
653 if (KeyData
== NULL
) {
654 return EFI_INVALID_PARAMETER
;
658 // Use TimerEvent callback function to check whether there's any key pressed
662 // Stall 1ms to give a chance to let other driver interrupt this routine for
663 // their timer event.
664 // e.g. OS loader, other drivers which are driven by timer event will have a
665 // bad performance during this period,
666 // e.g. usb keyboard driver.
667 // Add a stall period can greatly increate other driver performance during
668 // the WaitForKey is recursivly invoked. 1ms delay will make little impact
669 // to the thunk keyboard driver, and user can not feel the delay at all when
674 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
676 VirtualKeyboardTimerHandler (NULL
, VirtualKeyboardPrivate
);
678 // If there's no key, just return
680 Status
= CheckQueue (&VirtualKeyboardPrivate
->Queue
);
681 if (EFI_ERROR (Status
)) {
682 gBS
->RestoreTPL (OldTpl
);
683 return EFI_NOT_READY
;
686 Status
= Dequeue (&VirtualKeyboardPrivate
->Queue
, KeyData
);
688 gBS
->RestoreTPL (OldTpl
);
694 Read out the scan code of the key that has just been stroked.
696 @param This Pointer of simple text Protocol.
697 @param Key Pointer for store the key that read out.
699 @retval EFI_SUCCESS The key is read out successfully.
700 @retval other The key reading failed.
705 VirtualKeyboardReadKeyStroke (
706 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
707 OUT EFI_INPUT_KEY
*Key
710 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
712 EFI_KEY_DATA KeyData
;
714 VirtualKeyboardPrivate
= VIRTUAL_KEYBOARD_DEV_FROM_THIS (This
);
716 Status
= KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate
, &KeyData
);
717 if (EFI_ERROR (Status
)) {
722 // Convert the Ctrl+[a-z] to Ctrl+[1-26]
724 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
725 if (KeyData
.Key
.UnicodeChar
>= L
'a' &&
726 KeyData
.Key
.UnicodeChar
<= L
'z') {
727 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'a' + 1);
728 } else if (KeyData
.Key
.UnicodeChar
>= L
'A' &&
729 KeyData
.Key
.UnicodeChar
<= L
'Z') {
730 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'A' + 1);
734 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
740 Reads the next keystroke from the input device. The WaitForKey Event can
741 be used to test for existance of a keystroke via WaitForEvent () call.
743 @param This Protocol instance pointer.
744 @param KeyData A pointer to a buffer that is filled in with the
745 keystroke state data for the key that was pressed.
747 @retval EFI_SUCCESS The keystroke information was returned.
748 @retval EFI_NOT_READY There was no keystroke data availiable.
749 @retval EFI_DEVICE_ERROR The keystroke information was not returned
750 due to hardware errors.
751 @retval EFI_INVALID_PARAMETER KeyData is NULL.
756 VirtualKeyboardReadKeyStrokeEx (
757 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
758 OUT EFI_KEY_DATA
*KeyData
761 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
763 if (KeyData
== NULL
) {
764 return EFI_INVALID_PARAMETER
;
767 VirtualKeyboardPrivate
= TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This
);
769 return KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate
, KeyData
);
774 Set certain state for the input device.
776 @param This Protocol instance pointer.
777 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
778 state for the input device.
780 @retval EFI_SUCCESS The device state was set successfully.
781 @retval EFI_DEVICE_ERROR The device is not functioning correctly and
782 could not have the setting adjusted.
783 @retval EFI_UNSUPPORTED The device does not have the ability to set
785 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
790 VirtualKeyboardSetState (
791 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
792 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
795 if (KeyToggleState
== NULL
) {
796 return EFI_INVALID_PARAMETER
;
803 Register a notification function for a particular keystroke for the
806 @param This Protocol instance pointer.
807 @param KeyData A pointer to a buffer that is filled in with
808 the keystroke information data for the key
810 @param KeyNotificationFunction Points to the function to be called when the
811 key sequence is typed specified by KeyData.
812 @param NotifyHandle Points to the unique handle assigned to the
813 registered notification.
816 @retval EFI_SUCCESS The notification function was registered
818 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary
820 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
825 VirtualKeyboardRegisterKeyNotify (
826 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
827 IN EFI_KEY_DATA
*KeyData
,
828 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
829 OUT VOID
**NotifyHandle
833 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
835 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
837 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
839 if (KeyData
== NULL
||
840 NotifyHandle
== NULL
||
841 KeyNotificationFunction
== NULL
) {
842 return EFI_INVALID_PARAMETER
;
845 VirtualKeyboardPrivate
= TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This
);
848 // Enter critical section
850 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
853 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already
856 for (Link
= VirtualKeyboardPrivate
->NotifyList
.ForwardLink
;
857 Link
!= &VirtualKeyboardPrivate
->NotifyList
;
858 Link
= Link
->ForwardLink
) {
861 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
863 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
865 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
866 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
867 *NotifyHandle
= CurrentNotify
;
868 Status
= EFI_SUCCESS
;
875 // Allocate resource to save the notification function
878 NewNotify
= (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
879 if (NewNotify
== NULL
) {
880 Status
= EFI_OUT_OF_RESOURCES
;
884 NewNotify
->Signature
= VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
885 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
886 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
887 InsertTailList (&VirtualKeyboardPrivate
->NotifyList
, &NewNotify
->NotifyEntry
);
889 *NotifyHandle
= NewNotify
;
890 Status
= EFI_SUCCESS
;
894 // Leave critical section and return
896 gBS
->RestoreTPL (OldTpl
);
902 Remove a registered notification function from a particular keystroke.
904 @param This Protocol instance pointer.
905 @param NotificationHandle The handle of the notification function
908 @retval EFI_SUCCESS The notification function was unregistered
910 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
915 VirtualKeyboardUnregisterKeyNotify (
916 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
917 IN VOID
*NotificationHandle
921 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
924 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
927 // Check incoming notification handle
929 if (NotificationHandle
== NULL
) {
930 return EFI_INVALID_PARAMETER
;
933 if (((VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!=
934 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
935 return EFI_INVALID_PARAMETER
;
938 VirtualKeyboardPrivate
= TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This
);
941 // Enter critical section
943 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
945 for (Link
= VirtualKeyboardPrivate
->NotifyList
.ForwardLink
;
946 Link
!= &VirtualKeyboardPrivate
->NotifyList
;
947 Link
= Link
->ForwardLink
) {
950 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
952 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
954 if (CurrentNotify
== NotificationHandle
) {
956 // Remove the notification function from NotifyList and free resources
958 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
960 Status
= EFI_SUCCESS
;
966 // Can not find the specified Notification Handle
968 Status
= EFI_INVALID_PARAMETER
;
972 // Leave critical section and return
974 gBS
->RestoreTPL (OldTpl
);
979 Timer event handler: read a series of scancodes from 8042
980 and put them into memory scancode buffer.
981 it read as much scancodes to either fill
982 the memory buffer or empty the keyboard buffer.
983 It is registered as running under TPL_NOTIFY
985 @param Event The timer event
986 @param Context A KEYBOARD_CONSOLE_IN_DEV pointer
991 VirtualKeyboardTimerHandler (
998 EFI_KEY_DATA KeyData
;
999 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1000 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
1001 VIRTUAL_KBD_KEY VirtualKey
;
1003 VirtualKeyboardPrivate
= Context
;
1006 // Enter critical section
1008 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1010 if (VirtualKeyboardPrivate
->PlatformVirtual
&&
1011 VirtualKeyboardPrivate
->PlatformVirtual
->Query
) {
1012 if (VirtualKeyboardPrivate
->PlatformVirtual
->Query (&VirtualKey
) ==
1017 KeyData
.Key
.ScanCode
= VirtualKey
.Key
.ScanCode
;
1018 KeyData
.Key
.UnicodeChar
= VirtualKey
.Key
.UnicodeChar
;
1019 KeyData
.KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
1020 KeyData
.KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
1021 if (VirtualKeyboardPrivate
->PlatformVirtual
->Clear
) {
1022 VirtualKeyboardPrivate
->PlatformVirtual
->Clear (&VirtualKey
);
1029 // Signal KeyNotify process event if this key pressed matches any key registered.
1031 for (Link
= VirtualKeyboardPrivate
->NotifyList
.ForwardLink
;
1032 Link
!= &VirtualKeyboardPrivate
->NotifyList
;
1033 Link
= Link
->ForwardLink
) {
1034 CurrentNotify
= CR (
1036 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1038 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1040 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
1042 // The key notification function needs to run at TPL_CALLBACK
1043 // while current TPL is TPL_NOTIFY. It will be invoked in
1044 // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
1046 Enqueue (&VirtualKeyboardPrivate
->QueueForNotify
, &KeyData
);
1047 gBS
->SignalEvent (VirtualKeyboardPrivate
->KeyNotifyProcessEvent
);
1052 Enqueue (&VirtualKeyboardPrivate
->Queue
, &KeyData
);
1056 // Leave critical section and return
1058 gBS
->RestoreTPL (OldTpl
);
1064 @param Event Indicates the event that invoke this function.
1065 @param Context Indicates the calling context.
1069 KeyNotifyProcessHandler (
1075 VIRTUAL_KEYBOARD_DEV
*VirtualKeyboardPrivate
;
1076 EFI_KEY_DATA KeyData
;
1078 LIST_ENTRY
*NotifyList
;
1079 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1082 VirtualKeyboardPrivate
= (VIRTUAL_KEYBOARD_DEV
*) Context
;
1085 // Invoke notification functions.
1087 NotifyList
= &VirtualKeyboardPrivate
->NotifyList
;
1090 // Enter critical section
1092 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1093 Status
= Dequeue (&VirtualKeyboardPrivate
->QueueForNotify
, &KeyData
);
1095 // Leave critical section
1097 gBS
->RestoreTPL (OldTpl
);
1098 if (EFI_ERROR (Status
)) {
1101 for (Link
= GetFirstNode (NotifyList
);
1102 !IsNull (NotifyList
, Link
);
1103 Link
= GetNextNode (NotifyList
, Link
)) {
1104 CurrentNotify
= CR (Link
,
1105 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1107 VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1109 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
1110 CurrentNotify
->KeyNotificationFn (&KeyData
);
1117 The user Entry Point for module VirtualKeyboard. The user code starts with
1120 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1121 @param[in] SystemTable A pointer to the EFI System Table.
1123 @retval EFI_SUCCESS The entry point is executed successfully.
1124 @retval other Some error occurs when executing this entry point.
1129 InitializeVirtualKeyboard(
1130 IN EFI_HANDLE ImageHandle
,
1131 IN EFI_SYSTEM_TABLE
*SystemTable
1137 // Install driver model protocol(s).
1139 Status
= EfiLibInstallDriverBindingComponentName2 (
1142 &gVirtualKeyboardDriverBinding
,
1144 &gVirtualKeyboardComponentName
,
1145 &gVirtualKeyboardComponentName2
1147 ASSERT_EFI_ERROR (Status
);