2 USB Keyboard Driver that manages USB keyboard and produces Simple Text Input
3 Protocol and Simple Text Input Ex Protocol.
5 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 // USB Keyboard Driver Global Variables
22 EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding
= {
23 USBKeyboardDriverBindingSupported
,
24 USBKeyboardDriverBindingStart
,
25 USBKeyboardDriverBindingStop
,
32 Entrypoint of USB Keyboard Driver.
34 This function is the entrypoint of USB Keyboard Driver. It installs Driver Binding
35 Protocols together with Component Name Protocols.
37 @param ImageHandle The firmware allocated handle for the EFI image.
38 @param SystemTable A pointer to the EFI System Table.
40 @retval EFI_SUCCESS The entry point is executed successfully.
45 USBKeyboardDriverBindingEntryPoint (
46 IN EFI_HANDLE ImageHandle
,
47 IN EFI_SYSTEM_TABLE
*SystemTable
52 Status
= EfiLibInstallDriverBindingComponentName2 (
55 &gUsbKeyboardDriverBinding
,
57 &gUsbKeyboardComponentName
,
58 &gUsbKeyboardComponentName2
60 ASSERT_EFI_ERROR (Status
);
66 Check whether USB keyboard driver supports this device.
68 @param This The USB keyboard driver binding protocol.
69 @param Controller The controller handle to check.
70 @param RemainingDevicePath The remaining device path.
72 @retval EFI_SUCCESS The driver supports this controller.
73 @retval other This device isn't supported.
78 USBKeyboardDriverBindingSupported (
79 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
80 IN EFI_HANDLE Controller
,
81 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
85 EFI_USB_IO_PROTOCOL
*UsbIo
;
88 // Check if USB I/O Protocol is attached on the controller handle.
90 Status
= gBS
->OpenProtocol (
92 &gEfiUsbIoProtocolGuid
,
94 This
->DriverBindingHandle
,
96 EFI_OPEN_PROTOCOL_BY_DRIVER
98 if (EFI_ERROR (Status
)) {
103 // Use the USB I/O Protocol interface to check whether Controller is
104 // a keyboard device that can be managed by this driver.
106 Status
= EFI_SUCCESS
;
108 if (!IsUSBKeyboard (UsbIo
)) {
109 Status
= EFI_UNSUPPORTED
;
114 &gEfiUsbIoProtocolGuid
,
115 This
->DriverBindingHandle
,
123 Starts the keyboard device with this driver.
125 This function produces Simple Text Input Protocol and Simple Text Input Ex Protocol,
126 initializes the keyboard device, and submit Asynchronous Interrupt Transfer to manage
127 this keyboard device.
129 @param This The USB keyboard driver binding instance.
130 @param Controller Handle of device to bind driver to.
131 @param RemainingDevicePath Optional parameter use to pick a specific child
134 @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.
135 @retval EFI_UNSUPPORTED No interrupt endpoint can be found.
136 @retval Other This controller cannot be started.
141 USBKeyboardDriverBindingStart (
142 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
143 IN EFI_HANDLE Controller
,
144 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
148 EFI_USB_IO_PROTOCOL
*UsbIo
;
149 USB_KB_DEV
*UsbKeyboardDevice
;
150 UINT8 EndpointNumber
;
151 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
154 UINT8 PollingInterval
;
159 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
161 // Open USB I/O Protocol
163 Status
= gBS
->OpenProtocol (
165 &gEfiUsbIoProtocolGuid
,
167 This
->DriverBindingHandle
,
169 EFI_OPEN_PROTOCOL_BY_DRIVER
171 if (EFI_ERROR (Status
)) {
175 UsbKeyboardDevice
= AllocateZeroPool (sizeof (USB_KB_DEV
));
176 ASSERT (UsbKeyboardDevice
!= NULL
);
179 // Get the Device Path Protocol on Controller's handle
181 Status
= gBS
->OpenProtocol (
183 &gEfiDevicePathProtocolGuid
,
184 (VOID
**) &UsbKeyboardDevice
->DevicePath
,
185 This
->DriverBindingHandle
,
187 EFI_OPEN_PROTOCOL_GET_PROTOCOL
190 if (EFI_ERROR (Status
)) {
194 // Report that the USB keyboard is being enabled
196 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
198 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_ENABLE
),
199 UsbKeyboardDevice
->DevicePath
203 // This is pretty close to keyboard detection, so log progress
205 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
207 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_PRESENCE_DETECT
),
208 UsbKeyboardDevice
->DevicePath
211 UsbKeyboardDevice
->UsbIo
= UsbIo
;
214 // Get interface & endpoint descriptor
216 UsbIo
->UsbGetInterfaceDescriptor (
218 &UsbKeyboardDevice
->InterfaceDescriptor
221 EndpointNumber
= UsbKeyboardDevice
->InterfaceDescriptor
.NumEndpoints
;
224 // Traverse endpoints to find interrupt endpoint
227 for (Index
= 0; Index
< EndpointNumber
; Index
++) {
229 UsbIo
->UsbGetEndpointDescriptor (
235 if ((EndpointDescriptor
.Attributes
& (BIT0
| BIT1
)) == USB_ENDPOINT_INTERRUPT
) {
237 // We only care interrupt endpoint here
239 CopyMem(&UsbKeyboardDevice
->IntEndpointDescriptor
, &EndpointDescriptor
, sizeof(EndpointDescriptor
));
247 // Report Status Code to indicate that there is no USB keyboard
250 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
251 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_NOT_DETECTED
)
254 // No interrupt endpoint found, then return unsupported.
256 Status
= EFI_UNSUPPORTED
;
260 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
262 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DETECTED
),
263 UsbKeyboardDevice
->DevicePath
266 UsbKeyboardDevice
->Signature
= USB_KB_DEV_SIGNATURE
;
267 UsbKeyboardDevice
->SimpleInput
.Reset
= USBKeyboardReset
;
268 UsbKeyboardDevice
->SimpleInput
.ReadKeyStroke
= USBKeyboardReadKeyStroke
;
270 UsbKeyboardDevice
->SimpleInputEx
.Reset
= USBKeyboardResetEx
;
271 UsbKeyboardDevice
->SimpleInputEx
.ReadKeyStrokeEx
= USBKeyboardReadKeyStrokeEx
;
272 UsbKeyboardDevice
->SimpleInputEx
.SetState
= USBKeyboardSetState
;
273 UsbKeyboardDevice
->SimpleInputEx
.RegisterKeyNotify
= USBKeyboardRegisterKeyNotify
;
274 UsbKeyboardDevice
->SimpleInputEx
.UnregisterKeyNotify
= USBKeyboardUnregisterKeyNotify
;
276 InitializeListHead (&UsbKeyboardDevice
->NotifyList
);
278 Status
= gBS
->CreateEvent (
279 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
281 USBKeyboardTimerHandler
,
283 &UsbKeyboardDevice
->TimerEvent
285 if (!EFI_ERROR (Status
)) {
286 Status
= gBS
->SetTimer (UsbKeyboardDevice
->TimerEvent
, TimerPeriodic
, KEYBOARD_TIMER_INTERVAL
);
288 if (EFI_ERROR (Status
)) {
292 Status
= gBS
->CreateEvent (
295 USBKeyboardWaitForKey
,
297 &(UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
)
300 if (EFI_ERROR (Status
)) {
304 Status
= gBS
->CreateEvent (
307 USBKeyboardWaitForKey
,
309 &(UsbKeyboardDevice
->SimpleInput
.WaitForKey
)
311 if (EFI_ERROR (Status
)) {
315 Status
= gBS
->CreateEvent (
318 KeyNotifyProcessHandler
,
320 &UsbKeyboardDevice
->KeyNotifyProcessEvent
322 if (EFI_ERROR (Status
)) {
327 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol
328 // for the USB keyboard device.
329 // USB keyboard is a hot plug device, and expected to work immediately
330 // when plugging into system, other conventional console devices could
331 // distinguish it by its device path.
333 Status
= gBS
->InstallMultipleProtocolInterfaces (
335 &gEfiSimpleTextInProtocolGuid
,
336 &UsbKeyboardDevice
->SimpleInput
,
337 &gEfiSimpleTextInputExProtocolGuid
,
338 &UsbKeyboardDevice
->SimpleInputEx
,
341 if (EFI_ERROR (Status
)) {
345 UsbKeyboardDevice
->ControllerHandle
= Controller
;
346 Status
= InitKeyboardLayout (UsbKeyboardDevice
);
347 if (EFI_ERROR (Status
)) {
348 gBS
->UninstallMultipleProtocolInterfaces (
350 &gEfiSimpleTextInProtocolGuid
,
351 &UsbKeyboardDevice
->SimpleInput
,
352 &gEfiSimpleTextInputExProtocolGuid
,
353 &UsbKeyboardDevice
->SimpleInputEx
,
361 // Reset USB Keyboard Device exhaustively.
363 Status
= UsbKeyboardDevice
->SimpleInputEx
.Reset (
364 &UsbKeyboardDevice
->SimpleInputEx
,
367 if (EFI_ERROR (Status
)) {
368 gBS
->UninstallMultipleProtocolInterfaces (
370 &gEfiSimpleTextInProtocolGuid
,
371 &UsbKeyboardDevice
->SimpleInput
,
372 &gEfiSimpleTextInputExProtocolGuid
,
373 &UsbKeyboardDevice
->SimpleInputEx
,
380 // Submit Asynchronous Interrupt Transfer to manage this device.
382 EndpointAddr
= UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
;
383 PollingInterval
= UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
;
384 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
386 Status
= UsbIo
->UsbAsyncInterruptTransfer (
396 if (EFI_ERROR (Status
)) {
397 gBS
->UninstallMultipleProtocolInterfaces (
399 &gEfiSimpleTextInProtocolGuid
,
400 &UsbKeyboardDevice
->SimpleInput
,
401 &gEfiSimpleTextInputExProtocolGuid
,
402 &UsbKeyboardDevice
->SimpleInputEx
,
408 UsbKeyboardDevice
->ControllerNameTable
= NULL
;
411 gUsbKeyboardComponentName
.SupportedLanguages
,
412 &UsbKeyboardDevice
->ControllerNameTable
,
413 L
"Generic Usb Keyboard",
418 gUsbKeyboardComponentName2
.SupportedLanguages
,
419 &UsbKeyboardDevice
->ControllerNameTable
,
420 L
"Generic Usb Keyboard",
424 gBS
->RestoreTPL (OldTpl
);
431 if (UsbKeyboardDevice
!= NULL
) {
432 if (UsbKeyboardDevice
->TimerEvent
!= NULL
) {
433 gBS
->CloseEvent (UsbKeyboardDevice
->TimerEvent
);
435 if (UsbKeyboardDevice
->SimpleInput
.WaitForKey
!= NULL
) {
436 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
438 if (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
439 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
441 if (UsbKeyboardDevice
->KeyNotifyProcessEvent
!= NULL
) {
442 gBS
->CloseEvent (UsbKeyboardDevice
->KeyNotifyProcessEvent
);
444 if (UsbKeyboardDevice
->KeyboardLayoutEvent
!= NULL
) {
445 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
446 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
448 FreePool (UsbKeyboardDevice
);
449 UsbKeyboardDevice
= NULL
;
453 &gEfiUsbIoProtocolGuid
,
454 This
->DriverBindingHandle
,
459 gBS
->RestoreTPL (OldTpl
);
467 Stop the USB keyboard device handled by this driver.
469 @param This The USB keyboard driver binding protocol.
470 @param Controller The controller to release.
471 @param NumberOfChildren The number of handles in ChildHandleBuffer.
472 @param ChildHandleBuffer The array of child handle.
474 @retval EFI_SUCCESS The device was stopped.
475 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
476 is not installed on Controller.
477 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
478 @retval Others Fail to uninstall protocols attached on the device.
483 USBKeyboardDriverBindingStop (
484 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
485 IN EFI_HANDLE Controller
,
486 IN UINTN NumberOfChildren
,
487 IN EFI_HANDLE
*ChildHandleBuffer
491 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
492 USB_KB_DEV
*UsbKeyboardDevice
;
494 Status
= gBS
->OpenProtocol (
496 &gEfiSimpleTextInProtocolGuid
,
497 (VOID
**) &SimpleInput
,
498 This
->DriverBindingHandle
,
500 EFI_OPEN_PROTOCOL_GET_PROTOCOL
502 if (EFI_ERROR (Status
)) {
503 return EFI_UNSUPPORTED
;
506 Status
= gBS
->OpenProtocol (
508 &gEfiSimpleTextInputExProtocolGuid
,
510 This
->DriverBindingHandle
,
512 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
514 if (EFI_ERROR (Status
)) {
515 return EFI_UNSUPPORTED
;
518 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
521 // The key data input from this device will be disabled.
523 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
525 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DISABLE
),
526 UsbKeyboardDevice
->DevicePath
530 // Delete the Asynchronous Interrupt Transfer from this device
532 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
533 UsbKeyboardDevice
->UsbIo
,
534 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
536 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
544 &gEfiUsbIoProtocolGuid
,
545 This
->DriverBindingHandle
,
549 Status
= gBS
->UninstallMultipleProtocolInterfaces (
551 &gEfiSimpleTextInProtocolGuid
,
552 &UsbKeyboardDevice
->SimpleInput
,
553 &gEfiSimpleTextInputExProtocolGuid
,
554 &UsbKeyboardDevice
->SimpleInputEx
,
558 // Free all resources.
560 gBS
->CloseEvent (UsbKeyboardDevice
->TimerEvent
);
561 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
562 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
563 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
564 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
565 gBS
->CloseEvent (UsbKeyboardDevice
->KeyNotifyProcessEvent
);
566 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
568 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
569 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
571 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
572 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
575 DestroyQueue (&UsbKeyboardDevice
->UsbKeyQueue
);
576 DestroyQueue (&UsbKeyboardDevice
->EfiKeyQueue
);
577 DestroyQueue (&UsbKeyboardDevice
->EfiKeyQueueForNotify
);
579 FreePool (UsbKeyboardDevice
);
585 Internal function to read the next keystroke from the keyboard buffer.
587 @param UsbKeyboardDevice USB keyboard's private structure.
588 @param KeyData A pointer to buffer to hold the keystroke
589 data for the key that was pressed.
591 @retval EFI_SUCCESS The keystroke information was returned.
592 @retval EFI_NOT_READY There was no keystroke data availiable.
593 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
595 @retval EFI_INVALID_PARAMETER KeyData is NULL.
596 @retval Others Fail to translate keycode into EFI_INPUT_KEY
600 USBKeyboardReadKeyStrokeWorker (
601 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
602 OUT EFI_KEY_DATA
*KeyData
605 if (KeyData
== NULL
) {
606 return EFI_INVALID_PARAMETER
;
609 if (IsQueueEmpty (&UsbKeyboardDevice
->EfiKeyQueue
)) {
610 return EFI_NOT_READY
;
613 Dequeue (&UsbKeyboardDevice
->EfiKeyQueue
, KeyData
, sizeof (*KeyData
));
619 Reset the input device and optionally run diagnostics
621 There are 2 types of reset for USB keyboard.
622 For non-exhaustive reset, only keyboard buffer is cleared.
623 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
624 is also re-initialized.
626 @param This Protocol instance pointer.
627 @param ExtendedVerification Driver may perform diagnostics on reset.
629 @retval EFI_SUCCESS The device was reset.
630 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
636 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
637 IN BOOLEAN ExtendedVerification
641 USB_KB_DEV
*UsbKeyboardDevice
;
643 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
645 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
647 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
),
648 UsbKeyboardDevice
->DevicePath
652 // Non-exhaustive reset:
653 // only reset private data structures.
655 if (!ExtendedVerification
) {
656 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
658 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
),
659 UsbKeyboardDevice
->DevicePath
662 // Clear the key buffer of this USB keyboard
664 InitQueue (&UsbKeyboardDevice
->UsbKeyQueue
, sizeof (USB_KEY
));
665 InitQueue (&UsbKeyboardDevice
->EfiKeyQueue
, sizeof (EFI_KEY_DATA
));
666 InitQueue (&UsbKeyboardDevice
->EfiKeyQueueForNotify
, sizeof (EFI_KEY_DATA
));
674 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
675 if (EFI_ERROR (Status
)) {
676 return EFI_DEVICE_ERROR
;
684 Reads the next keystroke from the input device.
686 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
687 @param Key A pointer to a buffer that is filled in with the keystroke
688 information for the key that was pressed.
690 @retval EFI_SUCCESS The keystroke information was returned.
691 @retval EFI_NOT_READY There was no keystroke data availiable.
692 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
698 USBKeyboardReadKeyStroke (
699 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
700 OUT EFI_INPUT_KEY
*Key
703 USB_KB_DEV
*UsbKeyboardDevice
;
705 EFI_KEY_DATA KeyData
;
707 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
710 // Considering if the partial keystroke is enabled, there maybe a partial
711 // keystroke in the queue, so here skip the partial keystroke and get the
712 // next key from the queue
715 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
716 if (EFI_ERROR (Status
)) {
720 // SimpleTextIn Protocol doesn't support partial keystroke;
722 if (KeyData
.Key
.ScanCode
== CHAR_NULL
&& KeyData
.Key
.UnicodeChar
== SCAN_NULL
) {
726 // Translate the CTRL-Alpha characters to their corresponding control value
727 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
729 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
730 if (KeyData
.Key
.UnicodeChar
>= L
'a' && KeyData
.Key
.UnicodeChar
<= L
'z') {
731 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'a' + 1);
732 } else if (KeyData
.Key
.UnicodeChar
>= L
'A' && KeyData
.Key
.UnicodeChar
<= L
'Z') {
733 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'A' + 1);
737 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
744 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
745 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.
747 @param Event Event to be signaled when a key is pressed.
748 @param Context Points to USB_KB_DEV instance.
753 USBKeyboardWaitForKey (
758 USB_KB_DEV
*UsbKeyboardDevice
;
759 EFI_KEY_DATA KeyData
;
762 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
765 // Enter critical section
767 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
770 // WaitforKey doesn't suppor the partial key.
771 // Considering if the partial keystroke is enabled, there maybe a partial
772 // keystroke in the queue, so here skip the partial keystroke and get the
773 // next key from the queue
775 while (!IsQueueEmpty (&UsbKeyboardDevice
->EfiKeyQueue
)) {
777 // If there is pending key, signal the event.
781 UsbKeyboardDevice
->EfiKeyQueue
.Buffer
[UsbKeyboardDevice
->EfiKeyQueue
.Head
],
782 sizeof (EFI_KEY_DATA
)
784 if (KeyData
.Key
.ScanCode
== SCAN_NULL
&& KeyData
.Key
.UnicodeChar
== CHAR_NULL
) {
785 Dequeue (&UsbKeyboardDevice
->EfiKeyQueue
, &KeyData
, sizeof (EFI_KEY_DATA
));
788 gBS
->SignalEvent (Event
);
792 // Leave critical section and return
794 gBS
->RestoreTPL (OldTpl
);
798 Timer handler to convert the key from USB.
800 @param Event Indicates the event that invoke this function.
801 @param Context Indicates the calling context.
805 USBKeyboardTimerHandler (
811 USB_KB_DEV
*UsbKeyboardDevice
;
813 EFI_KEY_DATA KeyData
;
815 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
818 // Fetch raw data from the USB keyboard buffer,
819 // and translate it into USB keycode.
821 Status
= USBParseKey (UsbKeyboardDevice
, &KeyCode
);
822 if (EFI_ERROR (Status
)) {
827 // Translate saved USB keycode into EFI_INPUT_KEY
829 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyCode
, &KeyData
);
830 if (EFI_ERROR (Status
)) {
835 // Insert to the EFI Key queue
837 Enqueue (&UsbKeyboardDevice
->EfiKeyQueue
, &KeyData
, sizeof (KeyData
));
841 Free keyboard notify list.
843 @param NotifyList The keyboard notify list to free.
845 @retval EFI_SUCCESS Free the notify list successfully.
846 @retval EFI_INVALID_PARAMETER NotifyList is NULL.
851 IN OUT LIST_ENTRY
*NotifyList
854 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
857 if (NotifyList
== NULL
) {
858 return EFI_INVALID_PARAMETER
;
860 while (!IsListEmpty (NotifyList
)) {
861 Link
= GetFirstNode (NotifyList
);
862 NotifyNode
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
863 RemoveEntryList (Link
);
864 FreePool (NotifyNode
);
871 Check whether the pressed key matches a registered key or not.
873 @param RegsiteredData A pointer to keystroke data for the key that was registered.
874 @param InputData A pointer to keystroke data for the key that was pressed.
876 @retval TRUE Key pressed matches a registered key.
877 @retval FLASE Key pressed does not matches a registered key.
882 IN EFI_KEY_DATA
*RegsiteredData
,
883 IN EFI_KEY_DATA
*InputData
886 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
888 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
889 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
894 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
896 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
897 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
900 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
901 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
909 // Simple Text Input Ex protocol functions
912 Resets the input device hardware.
914 The Reset() function resets the input device hardware. As part
915 of initialization process, the firmware/device will make a quick
916 but reasonable attempt to verify that the device is functioning.
917 If the ExtendedVerification flag is TRUE the firmware may take
918 an extended amount of time to verify the device is operating on
919 reset. Otherwise the reset operation is to occur as quickly as
920 possible. The hardware verification process is not defined by
921 this specification and is left up to the platform firmware or
924 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
926 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
927 verification operation of the device during reset.
929 @retval EFI_SUCCESS The device was reset.
930 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
936 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
937 IN BOOLEAN ExtendedVerification
941 USB_KB_DEV
*UsbKeyboardDevice
;
943 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
945 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
946 if (EFI_ERROR (Status
)) {
947 return EFI_DEVICE_ERROR
;
950 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
951 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
958 Reads the next keystroke from the input device.
960 @param This Protocol instance pointer.
961 @param KeyData A pointer to a buffer that is filled in with the keystroke
962 state data for the key that was pressed.
964 @retval EFI_SUCCESS The keystroke information was returned.
965 @retval EFI_NOT_READY There was no keystroke data available.
966 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
968 @retval EFI_INVALID_PARAMETER KeyData is NULL.
973 USBKeyboardReadKeyStrokeEx (
974 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
975 OUT EFI_KEY_DATA
*KeyData
978 USB_KB_DEV
*UsbKeyboardDevice
;
980 if (KeyData
== NULL
) {
981 return EFI_INVALID_PARAMETER
;
984 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
986 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, KeyData
);
991 Set certain state for the input device.
993 @param This Protocol instance pointer.
994 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
995 state for the input device.
997 @retval EFI_SUCCESS The device state was set appropriately.
998 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
999 not have the setting adjusted.
1000 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.
1001 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
1006 USBKeyboardSetState (
1007 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1008 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
1011 USB_KB_DEV
*UsbKeyboardDevice
;
1013 if (KeyToggleState
== NULL
) {
1014 return EFI_INVALID_PARAMETER
;
1017 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1019 if (((UsbKeyboardDevice
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
1020 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
1021 return EFI_UNSUPPORTED
;
1025 // Update the status light
1028 UsbKeyboardDevice
->ScrollOn
= FALSE
;
1029 UsbKeyboardDevice
->NumLockOn
= FALSE
;
1030 UsbKeyboardDevice
->CapsOn
= FALSE
;
1031 UsbKeyboardDevice
->IsSupportPartialKey
= FALSE
;
1033 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
1034 UsbKeyboardDevice
->ScrollOn
= TRUE
;
1036 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
1037 UsbKeyboardDevice
->NumLockOn
= TRUE
;
1039 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
1040 UsbKeyboardDevice
->CapsOn
= TRUE
;
1042 if ((*KeyToggleState
& EFI_KEY_STATE_EXPOSED
) == EFI_KEY_STATE_EXPOSED
) {
1043 UsbKeyboardDevice
->IsSupportPartialKey
= TRUE
;
1046 SetKeyLED (UsbKeyboardDevice
);
1048 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
1055 Register a notification function for a particular keystroke for the input device.
1057 @param This Protocol instance pointer.
1058 @param KeyData A pointer to a buffer that is filled in with the keystroke
1059 information data for the key that was pressed.
1060 @param KeyNotificationFunction Points to the function to be called when the key
1061 sequence is typed specified by KeyData.
1062 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1064 @retval EFI_SUCCESS The notification function was registered successfully.
1065 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.
1066 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
1071 USBKeyboardRegisterKeyNotify (
1072 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1073 IN EFI_KEY_DATA
*KeyData
,
1074 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
1075 OUT VOID
**NotifyHandle
1078 USB_KB_DEV
*UsbKeyboardDevice
;
1079 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
1081 LIST_ENTRY
*NotifyList
;
1082 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1084 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
1085 return EFI_INVALID_PARAMETER
;
1088 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1091 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1093 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1095 for (Link
= GetFirstNode (NotifyList
);
1096 !IsNull (NotifyList
, Link
);
1097 Link
= GetNextNode (NotifyList
, Link
)) {
1098 CurrentNotify
= CR (
1100 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1102 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1104 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
1105 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
1106 *NotifyHandle
= CurrentNotify
;
1113 // Allocate resource to save the notification function
1115 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
1116 if (NewNotify
== NULL
) {
1117 return EFI_OUT_OF_RESOURCES
;
1120 NewNotify
->Signature
= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
1121 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
1122 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
1123 InsertTailList (&UsbKeyboardDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
1126 *NotifyHandle
= NewNotify
;
1133 Remove a registered notification function from a particular keystroke.
1135 @param This Protocol instance pointer.
1136 @param NotificationHandle The handle of the notification function being unregistered.
1138 @retval EFI_SUCCESS The notification function was unregistered successfully.
1139 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid
1144 USBKeyboardUnregisterKeyNotify (
1145 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1146 IN VOID
*NotificationHandle
1149 USB_KB_DEV
*UsbKeyboardDevice
;
1150 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1152 LIST_ENTRY
*NotifyList
;
1154 if (NotificationHandle
== NULL
) {
1155 return EFI_INVALID_PARAMETER
;
1158 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1161 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1163 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1164 for (Link
= GetFirstNode (NotifyList
);
1165 !IsNull (NotifyList
, Link
);
1166 Link
= GetNextNode (NotifyList
, Link
)) {
1167 CurrentNotify
= CR (
1169 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1171 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1173 if (CurrentNotify
== NotificationHandle
) {
1175 // Remove the notification function from NotifyList and free resources
1177 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
1179 FreePool (CurrentNotify
);
1185 // Cannot find the matching entry in database.
1187 return EFI_INVALID_PARAMETER
;
1193 @param Event Indicates the event that invoke this function.
1194 @param Context Indicates the calling context.
1198 KeyNotifyProcessHandler (
1204 USB_KB_DEV
*UsbKeyboardDevice
;
1205 EFI_KEY_DATA KeyData
;
1207 LIST_ENTRY
*NotifyList
;
1208 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1211 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
1214 // Invoke notification functions.
1216 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1219 // Enter critical section
1221 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1222 Status
= Dequeue (&UsbKeyboardDevice
->EfiKeyQueueForNotify
, &KeyData
, sizeof (KeyData
));
1224 // Leave critical section
1226 gBS
->RestoreTPL (OldTpl
);
1227 if (EFI_ERROR (Status
)) {
1230 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
1231 CurrentNotify
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
1232 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
1233 CurrentNotify
->KeyNotificationFn (&KeyData
);