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 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
14 // USB Keyboard Driver Global Variables
16 EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding
= {
17 USBKeyboardDriverBindingSupported
,
18 USBKeyboardDriverBindingStart
,
19 USBKeyboardDriverBindingStop
,
26 Entrypoint of USB Keyboard Driver.
28 This function is the entrypoint of USB Keyboard Driver. It installs Driver Binding
29 Protocols together with Component Name Protocols.
31 @param ImageHandle The firmware allocated handle for the EFI image.
32 @param SystemTable A pointer to the EFI System Table.
34 @retval EFI_SUCCESS The entry point is executed successfully.
39 USBKeyboardDriverBindingEntryPoint (
40 IN EFI_HANDLE ImageHandle
,
41 IN EFI_SYSTEM_TABLE
*SystemTable
46 Status
= EfiLibInstallDriverBindingComponentName2 (
49 &gUsbKeyboardDriverBinding
,
51 &gUsbKeyboardComponentName
,
52 &gUsbKeyboardComponentName2
54 ASSERT_EFI_ERROR (Status
);
60 Check whether USB keyboard driver supports this device.
62 @param This The USB keyboard driver binding protocol.
63 @param Controller The controller handle to check.
64 @param RemainingDevicePath The remaining device path.
66 @retval EFI_SUCCESS The driver supports this controller.
67 @retval other This device isn't supported.
72 USBKeyboardDriverBindingSupported (
73 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
74 IN EFI_HANDLE Controller
,
75 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
79 EFI_USB_IO_PROTOCOL
*UsbIo
;
82 // Check if USB I/O Protocol is attached on the controller handle.
84 Status
= gBS
->OpenProtocol (
86 &gEfiUsbIoProtocolGuid
,
88 This
->DriverBindingHandle
,
90 EFI_OPEN_PROTOCOL_BY_DRIVER
92 if (EFI_ERROR (Status
)) {
97 // Use the USB I/O Protocol interface to check whether Controller is
98 // a keyboard device that can be managed by this driver.
100 Status
= EFI_SUCCESS
;
102 if (!IsUSBKeyboard (UsbIo
)) {
103 Status
= EFI_UNSUPPORTED
;
108 &gEfiUsbIoProtocolGuid
,
109 This
->DriverBindingHandle
,
117 Starts the keyboard device with this driver.
119 This function produces Simple Text Input Protocol and Simple Text Input Ex Protocol,
120 initializes the keyboard device, and submit Asynchronous Interrupt Transfer to manage
121 this keyboard device.
123 @param This The USB keyboard driver binding instance.
124 @param Controller Handle of device to bind driver to.
125 @param RemainingDevicePath Optional parameter use to pick a specific child
128 @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.
129 @retval EFI_UNSUPPORTED No interrupt endpoint can be found.
130 @retval Other This controller cannot be started.
135 USBKeyboardDriverBindingStart (
136 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
137 IN EFI_HANDLE Controller
,
138 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
142 EFI_USB_IO_PROTOCOL
*UsbIo
;
143 USB_KB_DEV
*UsbKeyboardDevice
;
144 UINT8 EndpointNumber
;
145 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
148 UINT8 PollingInterval
;
153 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
155 // Open USB I/O Protocol
157 Status
= gBS
->OpenProtocol (
159 &gEfiUsbIoProtocolGuid
,
161 This
->DriverBindingHandle
,
163 EFI_OPEN_PROTOCOL_BY_DRIVER
165 if (EFI_ERROR (Status
)) {
169 UsbKeyboardDevice
= AllocateZeroPool (sizeof (USB_KB_DEV
));
170 ASSERT (UsbKeyboardDevice
!= NULL
);
173 // Get the Device Path Protocol on Controller's handle
175 Status
= gBS
->OpenProtocol (
177 &gEfiDevicePathProtocolGuid
,
178 (VOID
**) &UsbKeyboardDevice
->DevicePath
,
179 This
->DriverBindingHandle
,
181 EFI_OPEN_PROTOCOL_GET_PROTOCOL
184 if (EFI_ERROR (Status
)) {
188 // Report that the USB keyboard is being enabled
190 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
192 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_ENABLE
),
193 UsbKeyboardDevice
->DevicePath
197 // This is pretty close to keyboard detection, so log progress
199 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
201 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_PRESENCE_DETECT
),
202 UsbKeyboardDevice
->DevicePath
205 UsbKeyboardDevice
->UsbIo
= UsbIo
;
208 // Get interface & endpoint descriptor
210 UsbIo
->UsbGetInterfaceDescriptor (
212 &UsbKeyboardDevice
->InterfaceDescriptor
215 EndpointNumber
= UsbKeyboardDevice
->InterfaceDescriptor
.NumEndpoints
;
218 // Traverse endpoints to find interrupt endpoint
221 for (Index
= 0; Index
< EndpointNumber
; Index
++) {
223 UsbIo
->UsbGetEndpointDescriptor (
229 if ((EndpointDescriptor
.Attributes
& (BIT0
| BIT1
)) == USB_ENDPOINT_INTERRUPT
) {
231 // We only care interrupt endpoint here
233 CopyMem(&UsbKeyboardDevice
->IntEndpointDescriptor
, &EndpointDescriptor
, sizeof(EndpointDescriptor
));
241 // Report Status Code to indicate that there is no USB keyboard
244 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
245 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_NOT_DETECTED
)
248 // No interrupt endpoint found, then return unsupported.
250 Status
= EFI_UNSUPPORTED
;
254 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
256 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DETECTED
),
257 UsbKeyboardDevice
->DevicePath
260 UsbKeyboardDevice
->Signature
= USB_KB_DEV_SIGNATURE
;
261 UsbKeyboardDevice
->SimpleInput
.Reset
= USBKeyboardReset
;
262 UsbKeyboardDevice
->SimpleInput
.ReadKeyStroke
= USBKeyboardReadKeyStroke
;
264 UsbKeyboardDevice
->SimpleInputEx
.Reset
= USBKeyboardResetEx
;
265 UsbKeyboardDevice
->SimpleInputEx
.ReadKeyStrokeEx
= USBKeyboardReadKeyStrokeEx
;
266 UsbKeyboardDevice
->SimpleInputEx
.SetState
= USBKeyboardSetState
;
267 UsbKeyboardDevice
->SimpleInputEx
.RegisterKeyNotify
= USBKeyboardRegisterKeyNotify
;
268 UsbKeyboardDevice
->SimpleInputEx
.UnregisterKeyNotify
= USBKeyboardUnregisterKeyNotify
;
270 InitializeListHead (&UsbKeyboardDevice
->NotifyList
);
272 Status
= gBS
->CreateEvent (
273 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
275 USBKeyboardTimerHandler
,
277 &UsbKeyboardDevice
->TimerEvent
279 if (!EFI_ERROR (Status
)) {
280 Status
= gBS
->SetTimer (UsbKeyboardDevice
->TimerEvent
, TimerPeriodic
, KEYBOARD_TIMER_INTERVAL
);
282 if (EFI_ERROR (Status
)) {
286 Status
= gBS
->CreateEvent (
289 USBKeyboardWaitForKey
,
291 &(UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
)
294 if (EFI_ERROR (Status
)) {
298 Status
= gBS
->CreateEvent (
301 USBKeyboardWaitForKey
,
303 &(UsbKeyboardDevice
->SimpleInput
.WaitForKey
)
305 if (EFI_ERROR (Status
)) {
309 Status
= gBS
->CreateEvent (
312 KeyNotifyProcessHandler
,
314 &UsbKeyboardDevice
->KeyNotifyProcessEvent
316 if (EFI_ERROR (Status
)) {
321 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol
322 // for the USB keyboard device.
323 // USB keyboard is a hot plug device, and expected to work immediately
324 // when plugging into system, other conventional console devices could
325 // distinguish it by its device path.
327 Status
= gBS
->InstallMultipleProtocolInterfaces (
329 &gEfiSimpleTextInProtocolGuid
,
330 &UsbKeyboardDevice
->SimpleInput
,
331 &gEfiSimpleTextInputExProtocolGuid
,
332 &UsbKeyboardDevice
->SimpleInputEx
,
335 if (EFI_ERROR (Status
)) {
339 UsbKeyboardDevice
->ControllerHandle
= Controller
;
340 Status
= InitKeyboardLayout (UsbKeyboardDevice
);
341 if (EFI_ERROR (Status
)) {
342 gBS
->UninstallMultipleProtocolInterfaces (
344 &gEfiSimpleTextInProtocolGuid
,
345 &UsbKeyboardDevice
->SimpleInput
,
346 &gEfiSimpleTextInputExProtocolGuid
,
347 &UsbKeyboardDevice
->SimpleInputEx
,
355 // Reset USB Keyboard Device exhaustively.
357 Status
= UsbKeyboardDevice
->SimpleInputEx
.Reset (
358 &UsbKeyboardDevice
->SimpleInputEx
,
361 if (EFI_ERROR (Status
)) {
362 gBS
->UninstallMultipleProtocolInterfaces (
364 &gEfiSimpleTextInProtocolGuid
,
365 &UsbKeyboardDevice
->SimpleInput
,
366 &gEfiSimpleTextInputExProtocolGuid
,
367 &UsbKeyboardDevice
->SimpleInputEx
,
374 // Submit Asynchronous Interrupt Transfer to manage this device.
376 EndpointAddr
= UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
;
377 PollingInterval
= UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
;
378 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
380 Status
= UsbIo
->UsbAsyncInterruptTransfer (
390 if (EFI_ERROR (Status
)) {
391 gBS
->UninstallMultipleProtocolInterfaces (
393 &gEfiSimpleTextInProtocolGuid
,
394 &UsbKeyboardDevice
->SimpleInput
,
395 &gEfiSimpleTextInputExProtocolGuid
,
396 &UsbKeyboardDevice
->SimpleInputEx
,
402 UsbKeyboardDevice
->ControllerNameTable
= NULL
;
405 gUsbKeyboardComponentName
.SupportedLanguages
,
406 &UsbKeyboardDevice
->ControllerNameTable
,
407 L
"Generic Usb Keyboard",
412 gUsbKeyboardComponentName2
.SupportedLanguages
,
413 &UsbKeyboardDevice
->ControllerNameTable
,
414 L
"Generic Usb Keyboard",
418 gBS
->RestoreTPL (OldTpl
);
425 if (UsbKeyboardDevice
!= NULL
) {
426 if (UsbKeyboardDevice
->TimerEvent
!= NULL
) {
427 gBS
->CloseEvent (UsbKeyboardDevice
->TimerEvent
);
429 if (UsbKeyboardDevice
->SimpleInput
.WaitForKey
!= NULL
) {
430 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
432 if (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
433 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
435 if (UsbKeyboardDevice
->KeyNotifyProcessEvent
!= NULL
) {
436 gBS
->CloseEvent (UsbKeyboardDevice
->KeyNotifyProcessEvent
);
438 if (UsbKeyboardDevice
->KeyboardLayoutEvent
!= NULL
) {
439 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
440 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
442 FreePool (UsbKeyboardDevice
);
443 UsbKeyboardDevice
= NULL
;
447 &gEfiUsbIoProtocolGuid
,
448 This
->DriverBindingHandle
,
453 gBS
->RestoreTPL (OldTpl
);
461 Stop the USB keyboard device handled by this driver.
463 @param This The USB keyboard driver binding protocol.
464 @param Controller The controller to release.
465 @param NumberOfChildren The number of handles in ChildHandleBuffer.
466 @param ChildHandleBuffer The array of child handle.
468 @retval EFI_SUCCESS The device was stopped.
469 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
470 is not installed on Controller.
471 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
472 @retval Others Fail to uninstall protocols attached on the device.
477 USBKeyboardDriverBindingStop (
478 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
479 IN EFI_HANDLE Controller
,
480 IN UINTN NumberOfChildren
,
481 IN EFI_HANDLE
*ChildHandleBuffer
485 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
486 USB_KB_DEV
*UsbKeyboardDevice
;
488 Status
= gBS
->OpenProtocol (
490 &gEfiSimpleTextInProtocolGuid
,
491 (VOID
**) &SimpleInput
,
492 This
->DriverBindingHandle
,
494 EFI_OPEN_PROTOCOL_GET_PROTOCOL
496 if (EFI_ERROR (Status
)) {
497 return EFI_UNSUPPORTED
;
500 Status
= gBS
->OpenProtocol (
502 &gEfiSimpleTextInputExProtocolGuid
,
504 This
->DriverBindingHandle
,
506 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
508 if (EFI_ERROR (Status
)) {
509 return EFI_UNSUPPORTED
;
512 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
515 // The key data input from this device will be disabled.
517 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
519 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DISABLE
),
520 UsbKeyboardDevice
->DevicePath
524 // Delete the Asynchronous Interrupt Transfer from this device
526 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
527 UsbKeyboardDevice
->UsbIo
,
528 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
530 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
538 &gEfiUsbIoProtocolGuid
,
539 This
->DriverBindingHandle
,
543 Status
= gBS
->UninstallMultipleProtocolInterfaces (
545 &gEfiSimpleTextInProtocolGuid
,
546 &UsbKeyboardDevice
->SimpleInput
,
547 &gEfiSimpleTextInputExProtocolGuid
,
548 &UsbKeyboardDevice
->SimpleInputEx
,
552 // Free all resources.
554 gBS
->CloseEvent (UsbKeyboardDevice
->TimerEvent
);
555 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
556 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
557 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
558 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
559 gBS
->CloseEvent (UsbKeyboardDevice
->KeyNotifyProcessEvent
);
560 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
562 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
563 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
565 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
566 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
569 DestroyQueue (&UsbKeyboardDevice
->UsbKeyQueue
);
570 DestroyQueue (&UsbKeyboardDevice
->EfiKeyQueue
);
571 DestroyQueue (&UsbKeyboardDevice
->EfiKeyQueueForNotify
);
573 FreePool (UsbKeyboardDevice
);
579 Internal function to read the next keystroke from the keyboard buffer.
581 @param UsbKeyboardDevice USB keyboard's private structure.
582 @param KeyData A pointer to buffer to hold the keystroke
583 data for the key that was pressed.
585 @retval EFI_SUCCESS The keystroke information was returned.
586 @retval EFI_NOT_READY There was no keystroke data availiable.
587 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
589 @retval EFI_INVALID_PARAMETER KeyData is NULL.
590 @retval Others Fail to translate keycode into EFI_INPUT_KEY
594 USBKeyboardReadKeyStrokeWorker (
595 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
596 OUT EFI_KEY_DATA
*KeyData
599 if (KeyData
== NULL
) {
600 return EFI_INVALID_PARAMETER
;
603 if (IsQueueEmpty (&UsbKeyboardDevice
->EfiKeyQueue
)) {
604 ZeroMem (&KeyData
->Key
, sizeof (KeyData
->Key
));
605 InitializeKeyState (UsbKeyboardDevice
, &KeyData
->KeyState
);
606 return EFI_NOT_READY
;
609 Dequeue (&UsbKeyboardDevice
->EfiKeyQueue
, KeyData
, sizeof (*KeyData
));
615 Reset the input device and optionally run diagnostics
617 There are 2 types of reset for USB keyboard.
618 For non-exhaustive reset, only keyboard buffer is cleared.
619 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
620 is also re-initialized.
622 @param This Protocol instance pointer.
623 @param ExtendedVerification Driver may perform diagnostics on reset.
625 @retval EFI_SUCCESS The device was reset.
626 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
632 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
633 IN BOOLEAN ExtendedVerification
637 USB_KB_DEV
*UsbKeyboardDevice
;
639 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
641 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
643 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
),
644 UsbKeyboardDevice
->DevicePath
648 // Non-exhaustive reset:
649 // only reset private data structures.
651 if (!ExtendedVerification
) {
652 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
654 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
),
655 UsbKeyboardDevice
->DevicePath
658 // Clear the key buffer of this USB keyboard
660 InitQueue (&UsbKeyboardDevice
->UsbKeyQueue
, sizeof (USB_KEY
));
661 InitQueue (&UsbKeyboardDevice
->EfiKeyQueue
, sizeof (EFI_KEY_DATA
));
662 InitQueue (&UsbKeyboardDevice
->EfiKeyQueueForNotify
, sizeof (EFI_KEY_DATA
));
670 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
671 if (EFI_ERROR (Status
)) {
672 return EFI_DEVICE_ERROR
;
680 Reads the next keystroke from the input device.
682 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
683 @param Key A pointer to a buffer that is filled in with the keystroke
684 information for the key that was pressed.
686 @retval EFI_SUCCESS The keystroke information was returned.
687 @retval EFI_NOT_READY There was no keystroke data availiable.
688 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
694 USBKeyboardReadKeyStroke (
695 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
696 OUT EFI_INPUT_KEY
*Key
699 USB_KB_DEV
*UsbKeyboardDevice
;
701 EFI_KEY_DATA KeyData
;
703 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
706 // Considering if the partial keystroke is enabled, there maybe a partial
707 // keystroke in the queue, so here skip the partial keystroke and get the
708 // next key from the queue
711 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
712 if (EFI_ERROR (Status
)) {
716 // SimpleTextIn Protocol doesn't support partial keystroke;
718 if (KeyData
.Key
.ScanCode
== CHAR_NULL
&& KeyData
.Key
.UnicodeChar
== SCAN_NULL
) {
722 // Translate the CTRL-Alpha characters to their corresponding control value
723 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
725 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
726 if (KeyData
.Key
.UnicodeChar
>= L
'a' && KeyData
.Key
.UnicodeChar
<= L
'z') {
727 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'a' + 1);
728 } else if (KeyData
.Key
.UnicodeChar
>= L
'A' && KeyData
.Key
.UnicodeChar
<= L
'Z') {
729 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'A' + 1);
733 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
740 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
741 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.
743 @param Event Event to be signaled when a key is pressed.
744 @param Context Points to USB_KB_DEV instance.
749 USBKeyboardWaitForKey (
754 USB_KB_DEV
*UsbKeyboardDevice
;
755 EFI_KEY_DATA KeyData
;
758 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
761 // Enter critical section
763 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
766 // WaitforKey doesn't suppor the partial key.
767 // Considering if the partial keystroke is enabled, there maybe a partial
768 // keystroke in the queue, so here skip the partial keystroke and get the
769 // next key from the queue
771 while (!IsQueueEmpty (&UsbKeyboardDevice
->EfiKeyQueue
)) {
773 // If there is pending key, signal the event.
777 UsbKeyboardDevice
->EfiKeyQueue
.Buffer
[UsbKeyboardDevice
->EfiKeyQueue
.Head
],
778 sizeof (EFI_KEY_DATA
)
780 if (KeyData
.Key
.ScanCode
== SCAN_NULL
&& KeyData
.Key
.UnicodeChar
== CHAR_NULL
) {
781 Dequeue (&UsbKeyboardDevice
->EfiKeyQueue
, &KeyData
, sizeof (EFI_KEY_DATA
));
784 gBS
->SignalEvent (Event
);
788 // Leave critical section and return
790 gBS
->RestoreTPL (OldTpl
);
794 Timer handler to convert the key from USB.
796 @param Event Indicates the event that invoke this function.
797 @param Context Indicates the calling context.
801 USBKeyboardTimerHandler (
807 USB_KB_DEV
*UsbKeyboardDevice
;
809 EFI_KEY_DATA KeyData
;
811 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
814 // Fetch raw data from the USB keyboard buffer,
815 // and translate it into USB keycode.
817 Status
= USBParseKey (UsbKeyboardDevice
, &KeyCode
);
818 if (EFI_ERROR (Status
)) {
823 // Translate saved USB keycode into EFI_INPUT_KEY
825 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyCode
, &KeyData
);
826 if (EFI_ERROR (Status
)) {
831 // Insert to the EFI Key queue
833 Enqueue (&UsbKeyboardDevice
->EfiKeyQueue
, &KeyData
, sizeof (KeyData
));
837 Free keyboard notify list.
839 @param NotifyList The keyboard notify list to free.
841 @retval EFI_SUCCESS Free the notify list successfully.
842 @retval EFI_INVALID_PARAMETER NotifyList is NULL.
847 IN OUT LIST_ENTRY
*NotifyList
850 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
853 if (NotifyList
== NULL
) {
854 return EFI_INVALID_PARAMETER
;
856 while (!IsListEmpty (NotifyList
)) {
857 Link
= GetFirstNode (NotifyList
);
858 NotifyNode
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
859 RemoveEntryList (Link
);
860 FreePool (NotifyNode
);
867 Check whether the pressed key matches a registered key or not.
869 @param RegsiteredData A pointer to keystroke data for the key that was registered.
870 @param InputData A pointer to keystroke data for the key that was pressed.
872 @retval TRUE Key pressed matches a registered key.
873 @retval FLASE Key pressed does not matches a registered key.
878 IN EFI_KEY_DATA
*RegsiteredData
,
879 IN EFI_KEY_DATA
*InputData
882 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
884 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
885 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
890 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
892 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
893 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
896 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
897 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
905 // Simple Text Input Ex protocol functions
908 Resets the input device hardware.
910 The Reset() function resets the input device hardware. As part
911 of initialization process, the firmware/device will make a quick
912 but reasonable attempt to verify that the device is functioning.
913 If the ExtendedVerification flag is TRUE the firmware may take
914 an extended amount of time to verify the device is operating on
915 reset. Otherwise the reset operation is to occur as quickly as
916 possible. The hardware verification process is not defined by
917 this specification and is left up to the platform firmware or
920 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
922 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
923 verification operation of the device during reset.
925 @retval EFI_SUCCESS The device was reset.
926 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
932 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
933 IN BOOLEAN ExtendedVerification
937 USB_KB_DEV
*UsbKeyboardDevice
;
939 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
941 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
942 if (EFI_ERROR (Status
)) {
943 return EFI_DEVICE_ERROR
;
946 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
947 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
954 Reads the next keystroke from the input device.
956 @param This Protocol instance pointer.
957 @param KeyData A pointer to a buffer that is filled in with the keystroke
958 state data for the key that was pressed.
960 @retval EFI_SUCCESS The keystroke information was returned.
961 @retval EFI_NOT_READY There was no keystroke data available.
962 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
964 @retval EFI_INVALID_PARAMETER KeyData is NULL.
969 USBKeyboardReadKeyStrokeEx (
970 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
971 OUT EFI_KEY_DATA
*KeyData
974 USB_KB_DEV
*UsbKeyboardDevice
;
976 if (KeyData
== NULL
) {
977 return EFI_INVALID_PARAMETER
;
980 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
982 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, KeyData
);
987 Set certain state for the input device.
989 @param This Protocol instance pointer.
990 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
991 state for the input device.
993 @retval EFI_SUCCESS The device state was set appropriately.
994 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
995 not have the setting adjusted.
996 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.
997 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
1002 USBKeyboardSetState (
1003 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1004 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
1007 USB_KB_DEV
*UsbKeyboardDevice
;
1009 if (KeyToggleState
== NULL
) {
1010 return EFI_INVALID_PARAMETER
;
1013 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1015 if (((UsbKeyboardDevice
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
1016 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
1017 return EFI_UNSUPPORTED
;
1021 // Update the status light
1024 UsbKeyboardDevice
->ScrollOn
= FALSE
;
1025 UsbKeyboardDevice
->NumLockOn
= FALSE
;
1026 UsbKeyboardDevice
->CapsOn
= FALSE
;
1027 UsbKeyboardDevice
->IsSupportPartialKey
= FALSE
;
1029 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
1030 UsbKeyboardDevice
->ScrollOn
= TRUE
;
1032 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
1033 UsbKeyboardDevice
->NumLockOn
= TRUE
;
1035 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
1036 UsbKeyboardDevice
->CapsOn
= TRUE
;
1038 if ((*KeyToggleState
& EFI_KEY_STATE_EXPOSED
) == EFI_KEY_STATE_EXPOSED
) {
1039 UsbKeyboardDevice
->IsSupportPartialKey
= TRUE
;
1042 SetKeyLED (UsbKeyboardDevice
);
1044 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
1051 Register a notification function for a particular keystroke for the input device.
1053 @param This Protocol instance pointer.
1054 @param KeyData A pointer to a buffer that is filled in with
1055 the keystroke information for the key that was
1056 pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState
1057 and KeyData.KeyState.KeyShiftState are 0, then any incomplete
1058 keystroke will trigger a notification of the KeyNotificationFunction.
1059 @param KeyNotificationFunction Points to the function to be called when the key
1060 sequence is typed specified by KeyData. This notification function
1061 should be called at <=TPL_CALLBACK.
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
);