123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143 |
- /** @file
- VirtualKeyboard driver
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "VirtualKeyboard.h"
- //
- // RAM Keyboard Driver Binding Protocol Instance
- //
- EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding = {
- VirtualKeyboardDriverBindingSupported,
- VirtualKeyboardDriverBindingStart,
- VirtualKeyboardDriverBindingStop,
- 0x10,
- NULL,
- NULL
- };
- //
- // EFI Driver Binding Protocol Functions
- //
- /**
- Check whether the driver supports this device.
- @param This The Udriver binding protocol.
- @param Controller The controller handle to check.
- @param RemainingDevicePath The remaining device path.
- @retval EFI_SUCCESS The driver supports this controller.
- @retval other This device isn't supported.
- **/
- EFI_STATUS
- EFIAPI
- VirtualKeyboardDriverBindingSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
- {
- EFI_STATUS Status;
- PLATFORM_VIRTUAL_KBD_PROTOCOL *PlatformVirtual;
- Status = gBS->OpenProtocol (
- Controller,
- &gPlatformVirtualKeyboardProtocolGuid,
- (VOID **) &PlatformVirtual,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- gBS->CloseProtocol (
- Controller,
- &gPlatformVirtualKeyboardProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- return Status;
- }
- /**
- Starts the device with this driver.
- @param This The driver binding instance.
- @param Controller Handle of device to bind driver to.
- @param RemainingDevicePath Optional parameter use to pick a specific child
- device to start.
- @retval EFI_SUCCESS The controller is controlled by the driver.
- @retval Other This controller cannot be started.
- **/
- EFI_STATUS
- EFIAPI
- VirtualKeyboardDriverBindingStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
- {
- EFI_STATUS Status;
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- PLATFORM_VIRTUAL_KBD_PROTOCOL *PlatformVirtual;
- Status = gBS->OpenProtocol (
- Controller,
- &gPlatformVirtualKeyboardProtocolGuid,
- (VOID **) &PlatformVirtual,
- This->DriverBindingHandle,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Allocate the private device structure
- //
- VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_DEV));
- if (VirtualKeyboardPrivate == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- //
- // Initialize the private device structure
- //
- VirtualKeyboardPrivate->Signature = VIRTUAL_KEYBOARD_DEV_SIGNATURE;
- VirtualKeyboardPrivate->Handle = Controller;
- VirtualKeyboardPrivate->PlatformVirtual = PlatformVirtual;
- VirtualKeyboardPrivate->Queue.Front = 0;
- VirtualKeyboardPrivate->Queue.Rear = 0;
- VirtualKeyboardPrivate->QueueForNotify.Front = 0;
- VirtualKeyboardPrivate->QueueForNotify.Rear = 0;
- VirtualKeyboardPrivate->SimpleTextIn.Reset = VirtualKeyboardReset;
- VirtualKeyboardPrivate->SimpleTextIn.ReadKeyStroke = VirtualKeyboardReadKeyStroke;
- VirtualKeyboardPrivate->SimpleTextInputEx.Reset = VirtualKeyboardResetEx;
- VirtualKeyboardPrivate->SimpleTextInputEx.ReadKeyStrokeEx = VirtualKeyboardReadKeyStrokeEx;
- VirtualKeyboardPrivate->SimpleTextInputEx.SetState = VirtualKeyboardSetState;
- VirtualKeyboardPrivate->SimpleTextInputEx.RegisterKeyNotify = VirtualKeyboardRegisterKeyNotify;
- VirtualKeyboardPrivate->SimpleTextInputEx.UnregisterKeyNotify = VirtualKeyboardUnregisterKeyNotify;
- InitializeListHead (&VirtualKeyboardPrivate->NotifyList);
- Status = PlatformVirtual->Register ();
- if (EFI_ERROR (Status)) {
- goto Done;
- }
- //
- // Report that the keyboard is being enabled
- //
- REPORT_STATUS_CODE (
- EFI_PROGRESS_CODE,
- EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE
- );
- //
- // Setup the WaitForKey event
- //
- Status = gBS->CreateEvent (
- EVT_NOTIFY_WAIT,
- TPL_NOTIFY,
- VirtualKeyboardWaitForKey,
- &(VirtualKeyboardPrivate->SimpleTextIn),
- &((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey)
- );
- if (EFI_ERROR (Status)) {
- (VirtualKeyboardPrivate->SimpleTextIn).WaitForKey = NULL;
- goto Done;
- }
- Status = gBS->CreateEvent (
- EVT_NOTIFY_WAIT,
- TPL_NOTIFY,
- VirtualKeyboardWaitForKeyEx,
- &(VirtualKeyboardPrivate->SimpleTextInputEx),
- &(VirtualKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx)
- );
- if (EFI_ERROR (Status)) {
- VirtualKeyboardPrivate->SimpleTextInputEx.WaitForKeyEx = NULL;
- goto Done;
- }
- //
- // Setup a periodic timer, used for reading keystrokes at a fixed interval
- //
- Status = gBS->CreateEvent (
- EVT_TIMER | EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- VirtualKeyboardTimerHandler,
- VirtualKeyboardPrivate,
- &VirtualKeyboardPrivate->TimerEvent
- );
- if (EFI_ERROR (Status)) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- Status = gBS->SetTimer (
- VirtualKeyboardPrivate->TimerEvent,
- TimerPeriodic,
- KEYBOARD_TIMER_INTERVAL
- );
- if (EFI_ERROR (Status)) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- KeyNotifyProcessHandler,
- VirtualKeyboardPrivate,
- &VirtualKeyboardPrivate->KeyNotifyProcessEvent
- );
- if (EFI_ERROR (Status)) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Done;
- }
- //
- // Reset the keyboard device
- //
- Status = VirtualKeyboardPrivate->SimpleTextInputEx.Reset (
- &VirtualKeyboardPrivate->SimpleTextInputEx,
- FALSE
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "[KBD]Reset Failed. Status - %r\n", Status));
- goto Done;
- }
- //
- // Install protocol interfaces for the keyboard device.
- //
- Status = gBS->InstallMultipleProtocolInterfaces (
- &Controller,
- &gEfiSimpleTextInProtocolGuid,
- &VirtualKeyboardPrivate->SimpleTextIn,
- &gEfiSimpleTextInputExProtocolGuid,
- &VirtualKeyboardPrivate->SimpleTextInputEx,
- NULL
- );
- Done:
- if (EFI_ERROR (Status)) {
- if (VirtualKeyboardPrivate != NULL) {
- if ((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey != NULL) {
- gBS->CloseEvent ((VirtualKeyboardPrivate->SimpleTextIn).WaitForKey);
- }
- if ((VirtualKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx != NULL) {
- gBS->CloseEvent (
- (VirtualKeyboardPrivate->SimpleTextInputEx).WaitForKeyEx
- );
- }
- if (VirtualKeyboardPrivate->KeyNotifyProcessEvent != NULL) {
- gBS->CloseEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent);
- }
- VirtualKeyboardFreeNotifyList (&VirtualKeyboardPrivate->NotifyList);
- if (VirtualKeyboardPrivate->TimerEvent != NULL) {
- gBS->CloseEvent (VirtualKeyboardPrivate->TimerEvent);
- }
- FreePool (VirtualKeyboardPrivate);
- }
- }
- gBS->CloseProtocol (
- Controller,
- &gPlatformVirtualKeyboardProtocolGuid,
- This->DriverBindingHandle,
- Controller
- );
- return Status;
- }
- /**
- Stop the device handled by this driver.
- @param This The driver binding protocol.
- @param Controller The controller to release.
- @param NumberOfChildren The number of handles in ChildHandleBuffer.
- @param ChildHandleBuffer The array of child handle.
- @retval EFI_SUCCESS The device was stopped.
- @retval EFI_DEVICE_ERROR The device could not be stopped due to a
- device error.
- @retval Others Fail to uninstall protocols attached on the
- device.
- **/
- EFI_STATUS
- EFIAPI
- VirtualKeyboardDriverBindingStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE Controller,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer
- )
- {
- return EFI_SUCCESS;
- }
- /**
- Enqueue the key.
- @param Queue The queue to be enqueued.
- @param KeyData The key data to be enqueued.
- @retval EFI_NOT_READY The queue is full.
- @retval EFI_SUCCESS Successfully enqueued the key data.
- **/
- EFI_STATUS
- Enqueue (
- IN SIMPLE_QUEUE *Queue,
- IN EFI_KEY_DATA *KeyData
- )
- {
- if ((Queue->Rear + 1) % QUEUE_MAX_COUNT == Queue->Front) {
- return EFI_NOT_READY;
- }
- CopyMem (&Queue->Buffer[Queue->Rear], KeyData, sizeof (EFI_KEY_DATA));
- Queue->Rear = (Queue->Rear + 1) % QUEUE_MAX_COUNT;
- return EFI_SUCCESS;
- }
- /**
- Dequeue the key.
- @param Queue The queue to be dequeued.
- @param KeyData The key data to be dequeued.
- @retval EFI_NOT_READY The queue is empty.
- @retval EFI_SUCCESS Successfully dequeued the key data.
- **/
- EFI_STATUS
- Dequeue (
- IN SIMPLE_QUEUE *Queue,
- IN EFI_KEY_DATA *KeyData
- )
- {
- if (Queue->Front == Queue->Rear) {
- return EFI_NOT_READY;
- }
- CopyMem (KeyData, &Queue->Buffer[Queue->Front], sizeof (EFI_KEY_DATA));
- Queue->Front = (Queue->Front + 1) % QUEUE_MAX_COUNT;
- return EFI_SUCCESS;
- }
- /**
- Check whether the queue is empty.
- @param Queue The queue to be checked.
- @retval EFI_NOT_READY The queue is empty.
- @retval EFI_SUCCESS The queue is not empty.
- **/
- EFI_STATUS
- CheckQueue (
- IN SIMPLE_QUEUE *Queue
- )
- {
- if (Queue->Front == Queue->Rear) {
- return EFI_NOT_READY;
- }
- return EFI_SUCCESS;
- }
- /**
- Check key buffer to get the key stroke status.
- @param This Pointer of the protocol EFI_SIMPLE_TEXT_IN_PROTOCOL.
- @retval EFI_SUCCESS A key is being pressed now.
- @retval Other No key is now pressed.
- **/
- EFI_STATUS
- EFIAPI
- VirtualKeyboardCheckForKey (
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This
- )
- {
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
- return CheckQueue (&VirtualKeyboardPrivate->Queue);
- }
- /**
- Free keyboard notify list.
- @param ListHead The list head
- @retval EFI_SUCCESS Free the notify list successfully
- @retval EFI_INVALID_PARAMETER ListHead is invalid.
- **/
- EFI_STATUS
- VirtualKeyboardFreeNotifyList (
- IN OUT LIST_ENTRY *ListHead
- )
- {
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
- if (ListHead == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- while (!IsListEmpty (ListHead)) {
- NotifyNode = CR (
- ListHead->ForwardLink,
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
- NotifyEntry,
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
- );
- RemoveEntryList (ListHead->ForwardLink);
- gBS->FreePool (NotifyNode);
- }
- 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;
- }
- /**
- 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
- VirtualKeyboardWaitForKey (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- //
- // Stall 1ms to give a chance to let other driver interrupt this routine
- // for their timer event.
- // e.g. UI setup or Shell, other drivers which are driven by timer event
- // will have a bad performance during this period,
- // e.g. usb keyboard driver.
- // Add a stall period can greatly increate other driver performance during
- // the WaitForKey is recursivly invoked. 1ms delay will make little impact
- // to the thunk keyboard driver, and user can not feel the delay at all when
- // input.
- //
- gBS->Stall (1000);
- //
- // Use TimerEvent callback function to check whether there's any key pressed
- //
- VirtualKeyboardTimerHandler (NULL, VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context));
- if (!EFI_ERROR (VirtualKeyboardCheckForKey (Context))) {
- gBS->SignalEvent (Event);
- }
- }
- /**
- 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
- VirtualKeyboardWaitForKeyEx (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (Context);
- VirtualKeyboardWaitForKey (Event, &VirtualKeyboardPrivate->SimpleTextIn);
- }
- //
- // EFI Simple Text In Protocol Functions
- //
- /**
- Reset the Keyboard and do BAT test for it, if (ExtendedVerification == TRUE)
- then do some extra keyboard validations.
- @param This Pointer of simple text Protocol.
- @param ExtendedVerification Whether perform the extra validation of
- keyboard. True: perform; FALSE: skip.
- @retval EFI_SUCCESS The command byte is written successfully.
- @retval EFI_DEVICE_ERROR Errors occurred during resetting keyboard.
- **/
- EFI_STATUS
- EFIAPI
- VirtualKeyboardReset (
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
- IN BOOLEAN ExtendedVerification
- )
- {
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
- //
- // Raise TPL to avoid mouse operation impact
- //
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- if (VirtualKeyboardPrivate->PlatformVirtual &&
- VirtualKeyboardPrivate->PlatformVirtual->Reset) {
- Status = VirtualKeyboardPrivate->PlatformVirtual->Reset ();
- } else {
- Status = EFI_INVALID_PARAMETER;
- }
- //
- // resume priority of task level
- //
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- 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
- VirtualKeyboardResetEx (
- IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- IN BOOLEAN ExtendedVerification
- )
- {
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
- Status = VirtualKeyboardPrivate->SimpleTextIn.Reset (
- &VirtualKeyboardPrivate->SimpleTextIn,
- ExtendedVerification
- );
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- 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 VirtualKeyboardPrivate Virtualkeyboard driver 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 VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate,
- OUT EFI_KEY_DATA *KeyData
- )
- {
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- if (KeyData == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- //
- // Use TimerEvent callback function to check whether there's any key pressed
- //
- //
- // Stall 1ms to give a chance to let other driver interrupt this routine for
- // their timer event.
- // e.g. OS loader, other drivers which are driven by timer event will have a
- // bad performance during this period,
- // e.g. usb keyboard driver.
- // Add a stall period can greatly increate other driver performance during
- // the WaitForKey is recursivly invoked. 1ms delay will make little impact
- // to the thunk keyboard driver, and user can not feel the delay at all when
- // input.
- //
- gBS->Stall (1000);
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- VirtualKeyboardTimerHandler (NULL, VirtualKeyboardPrivate);
- //
- // If there's no key, just return
- //
- Status = CheckQueue (&VirtualKeyboardPrivate->Queue);
- if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (OldTpl);
- return EFI_NOT_READY;
- }
- Status = Dequeue (&VirtualKeyboardPrivate->Queue, KeyData);
- gBS->RestoreTPL (OldTpl);
- return EFI_SUCCESS;
- }
- /**
- Read out the scan code of the key that has just been stroked.
- @param This Pointer of simple text Protocol.
- @param Key Pointer for store the key that read out.
- @retval EFI_SUCCESS The key is read out successfully.
- @retval other The key reading failed.
- **/
- EFI_STATUS
- EFIAPI
- VirtualKeyboardReadKeyStroke (
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
- OUT EFI_INPUT_KEY *Key
- )
- {
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- EFI_STATUS Status;
- EFI_KEY_DATA KeyData;
- VirtualKeyboardPrivate = VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
- Status = KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, &KeyData);
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Convert the Ctrl+[a-z] to Ctrl+[1-26]
- //
- if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {
- if (KeyData.Key.UnicodeChar >= L'a' &&
- KeyData.Key.UnicodeChar <= L'z') {
- KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);
- } else if (KeyData.Key.UnicodeChar >= L'A' &&
- KeyData.Key.UnicodeChar <= L'Z') {
- KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);
- }
- }
- CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));
- return EFI_SUCCESS;
- }
- /**
- 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
- VirtualKeyboardReadKeyStrokeEx (
- IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- OUT EFI_KEY_DATA *KeyData
- )
- {
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- if (KeyData == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
- return KeyboardReadKeyStrokeWorker (VirtualKeyboardPrivate, 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
- VirtualKeyboardSetState (
- IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- IN EFI_KEY_TOGGLE_STATE *KeyToggleState
- )
- {
- if (KeyToggleState == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- return EFI_SUCCESS;
- }
- /**
- 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 is NULL.
- **/
- EFI_STATUS
- EFIAPI
- VirtualKeyboardRegisterKeyNotify (
- IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- IN EFI_KEY_DATA *KeyData,
- IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,
- OUT VOID **NotifyHandle
- )
- {
- EFI_STATUS Status;
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- EFI_TPL OldTpl;
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;
- LIST_ENTRY *Link;
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
- if (KeyData == NULL ||
- NotifyHandle == NULL ||
- KeyNotificationFunction == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
- //
- // Enter critical section
- //
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- //
- // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already
- // registered.
- //
- for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink;
- Link != &VirtualKeyboardPrivate->NotifyList;
- Link = Link->ForwardLink) {
- CurrentNotify = CR (
- Link,
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
- NotifyEntry,
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
- );
- if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {
- if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {
- *NotifyHandle = CurrentNotify;
- Status = EFI_SUCCESS;
- goto Exit;
- }
- }
- }
- //
- // Allocate resource to save the notification function
- //
- NewNotify = (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY));
- if (NewNotify == NULL) {
- Status = EFI_OUT_OF_RESOURCES;
- goto Exit;
- }
- NewNotify->Signature = VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE;
- NewNotify->KeyNotificationFn = KeyNotificationFunction;
- CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));
- InsertTailList (&VirtualKeyboardPrivate->NotifyList, &NewNotify->NotifyEntry);
- *NotifyHandle = NewNotify;
- Status = EFI_SUCCESS;
- Exit:
- //
- // Leave critical section and return
- //
- gBS->RestoreTPL (OldTpl);
- return Status;
- }
- /**
- Remove a registered notification function from a particular keystroke.
- @param This Protocol instance pointer.
- @param NotificationHandle The handle of the notification function
- being unregistered.
- @retval EFI_SUCCESS The notification function was unregistered
- successfully.
- @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid.
- **/
- EFI_STATUS
- EFIAPI
- VirtualKeyboardUnregisterKeyNotify (
- IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
- IN VOID *NotificationHandle
- )
- {
- EFI_STATUS Status;
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- EFI_TPL OldTpl;
- LIST_ENTRY *Link;
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
- //
- // Check incoming notification handle
- //
- if (NotificationHandle == NULL) {
- return EFI_INVALID_PARAMETER;
- }
- if (((VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *) NotificationHandle)->Signature !=
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
- VirtualKeyboardPrivate = TEXT_INPUT_EX_VIRTUAL_KEYBOARD_DEV_FROM_THIS (This);
- //
- // Enter critical section
- //
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink;
- Link != &VirtualKeyboardPrivate->NotifyList;
- Link = Link->ForwardLink) {
- CurrentNotify = CR (
- Link,
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
- NotifyEntry,
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
- );
- if (CurrentNotify == NotificationHandle) {
- //
- // Remove the notification function from NotifyList and free resources
- //
- RemoveEntryList (&CurrentNotify->NotifyEntry);
- 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;
- }
- /**
- Timer event handler: read a series of scancodes from 8042
- and put them into memory scancode buffer.
- it read as much scancodes to either fill
- the memory buffer or empty the keyboard buffer.
- It is registered as running under TPL_NOTIFY
- @param Event The timer event
- @param Context A KEYBOARD_CONSOLE_IN_DEV pointer
- **/
- VOID
- EFIAPI
- VirtualKeyboardTimerHandler (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- EFI_TPL OldTpl;
- LIST_ENTRY *Link;
- EFI_KEY_DATA KeyData;
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- VIRTUAL_KBD_KEY VirtualKey;
- VirtualKeyboardPrivate = Context;
- //
- // Enter critical section
- //
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- if (VirtualKeyboardPrivate->PlatformVirtual &&
- VirtualKeyboardPrivate->PlatformVirtual->Query) {
- if (VirtualKeyboardPrivate->PlatformVirtual->Query (&VirtualKey) ==
- FALSE) {
- goto Exit;
- }
- // Found key
- KeyData.Key.ScanCode = VirtualKey.Key.ScanCode;
- KeyData.Key.UnicodeChar = VirtualKey.Key.UnicodeChar;
- KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;
- KeyData.KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;
- if (VirtualKeyboardPrivate->PlatformVirtual->Clear) {
- VirtualKeyboardPrivate->PlatformVirtual->Clear (&VirtualKey);
- }
- } else {
- goto Exit;
- }
- //
- // Signal KeyNotify process event if this key pressed matches any key registered.
- //
- for (Link = VirtualKeyboardPrivate->NotifyList.ForwardLink;
- Link != &VirtualKeyboardPrivate->NotifyList;
- Link = Link->ForwardLink) {
- CurrentNotify = CR (
- Link,
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
- NotifyEntry,
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
- );
- if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
- //
- // The key notification function needs to run at TPL_CALLBACK
- // while current TPL is TPL_NOTIFY. It will be invoked in
- // KeyNotifyProcessHandler() which runs at TPL_CALLBACK.
- //
- Enqueue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData);
- gBS->SignalEvent (VirtualKeyboardPrivate->KeyNotifyProcessEvent);
- break;
- }
- }
- Enqueue (&VirtualKeyboardPrivate->Queue, &KeyData);
- Exit:
- //
- // Leave critical section and return
- //
- gBS->RestoreTPL (OldTpl);
- }
- /**
- Process key notify.
- @param Event Indicates the event that invoke this function.
- @param Context Indicates the calling context.
- **/
- VOID
- EFIAPI
- KeyNotifyProcessHandler (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- EFI_STATUS Status;
- VIRTUAL_KEYBOARD_DEV *VirtualKeyboardPrivate;
- EFI_KEY_DATA KeyData;
- LIST_ENTRY *Link;
- LIST_ENTRY *NotifyList;
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;
- EFI_TPL OldTpl;
- VirtualKeyboardPrivate = (VIRTUAL_KEYBOARD_DEV *) Context;
- //
- // Invoke notification functions.
- //
- NotifyList = &VirtualKeyboardPrivate->NotifyList;
- while (TRUE) {
- //
- // Enter critical section
- //
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- Status = Dequeue (&VirtualKeyboardPrivate->QueueForNotify, &KeyData);
- //
- // Leave critical section
- //
- gBS->RestoreTPL (OldTpl);
- if (EFI_ERROR (Status)) {
- break;
- }
- for (Link = GetFirstNode (NotifyList);
- !IsNull (NotifyList, Link);
- Link = GetNextNode (NotifyList, Link)) {
- CurrentNotify = CR (Link,
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY,
- NotifyEntry,
- VIRTUAL_KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
- );
- if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {
- CurrentNotify->KeyNotificationFn (&KeyData);
- }
- }
- }
- }
- /**
- The user Entry Point for module VirtualKeyboard. The user code starts with
- this function.
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval other Some error occurs when executing this entry point.
- **/
- EFI_STATUS
- EFIAPI
- InitializeVirtualKeyboard(
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- //
- // Install driver model protocol(s).
- //
- Status = EfiLibInstallDriverBindingComponentName2 (
- ImageHandle,
- SystemTable,
- &gVirtualKeyboardDriverBinding,
- ImageHandle,
- &gVirtualKeyboardComponentName,
- &gVirtualKeyboardComponentName2
- );
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
|