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 IN
221 for (Index
= 0; Index
< EndpointNumber
; Index
++) {
223 UsbIo
->UsbGetEndpointDescriptor (
229 if (((EndpointDescriptor
.Attributes
& (BIT0
| BIT1
)) == USB_ENDPOINT_INTERRUPT
) &&
230 ((EndpointDescriptor
.EndpointAddress
& USB_ENDPOINT_DIR_IN
) != 0)) {
232 // We only care interrupt endpoint here
234 CopyMem(&UsbKeyboardDevice
->IntEndpointDescriptor
, &EndpointDescriptor
, sizeof(EndpointDescriptor
));
242 // Report Status Code to indicate that there is no USB keyboard
245 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
246 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_NOT_DETECTED
)
249 // No interrupt endpoint found, then return unsupported.
251 Status
= EFI_UNSUPPORTED
;
255 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
257 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DETECTED
),
258 UsbKeyboardDevice
->DevicePath
261 UsbKeyboardDevice
->Signature
= USB_KB_DEV_SIGNATURE
;
262 UsbKeyboardDevice
->SimpleInput
.Reset
= USBKeyboardReset
;
263 UsbKeyboardDevice
->SimpleInput
.ReadKeyStroke
= USBKeyboardReadKeyStroke
;
265 UsbKeyboardDevice
->SimpleInputEx
.Reset
= USBKeyboardResetEx
;
266 UsbKeyboardDevice
->SimpleInputEx
.ReadKeyStrokeEx
= USBKeyboardReadKeyStrokeEx
;
267 UsbKeyboardDevice
->SimpleInputEx
.SetState
= USBKeyboardSetState
;
268 UsbKeyboardDevice
->SimpleInputEx
.RegisterKeyNotify
= USBKeyboardRegisterKeyNotify
;
269 UsbKeyboardDevice
->SimpleInputEx
.UnregisterKeyNotify
= USBKeyboardUnregisterKeyNotify
;
271 InitializeListHead (&UsbKeyboardDevice
->NotifyList
);
273 Status
= gBS
->CreateEvent (
274 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
276 USBKeyboardTimerHandler
,
278 &UsbKeyboardDevice
->TimerEvent
280 if (!EFI_ERROR (Status
)) {
281 Status
= gBS
->SetTimer (UsbKeyboardDevice
->TimerEvent
, TimerPeriodic
, KEYBOARD_TIMER_INTERVAL
);
283 if (EFI_ERROR (Status
)) {
287 Status
= gBS
->CreateEvent (
290 USBKeyboardWaitForKey
,
292 &(UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
)
295 if (EFI_ERROR (Status
)) {
299 Status
= gBS
->CreateEvent (
302 USBKeyboardWaitForKey
,
304 &(UsbKeyboardDevice
->SimpleInput
.WaitForKey
)
306 if (EFI_ERROR (Status
)) {
310 Status
= gBS
->CreateEvent (
313 KeyNotifyProcessHandler
,
315 &UsbKeyboardDevice
->KeyNotifyProcessEvent
317 if (EFI_ERROR (Status
)) {
322 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol
323 // for the USB keyboard device.
324 // USB keyboard is a hot plug device, and expected to work immediately
325 // when plugging into system, other conventional console devices could
326 // distinguish it by its device path.
328 Status
= gBS
->InstallMultipleProtocolInterfaces (
330 &gEfiSimpleTextInProtocolGuid
,
331 &UsbKeyboardDevice
->SimpleInput
,
332 &gEfiSimpleTextInputExProtocolGuid
,
333 &UsbKeyboardDevice
->SimpleInputEx
,
336 if (EFI_ERROR (Status
)) {
340 UsbKeyboardDevice
->ControllerHandle
= Controller
;
341 Status
= InitKeyboardLayout (UsbKeyboardDevice
);
342 if (EFI_ERROR (Status
)) {
343 gBS
->UninstallMultipleProtocolInterfaces (
345 &gEfiSimpleTextInProtocolGuid
,
346 &UsbKeyboardDevice
->SimpleInput
,
347 &gEfiSimpleTextInputExProtocolGuid
,
348 &UsbKeyboardDevice
->SimpleInputEx
,
356 // Reset USB Keyboard Device exhaustively.
358 Status
= UsbKeyboardDevice
->SimpleInputEx
.Reset (
359 &UsbKeyboardDevice
->SimpleInputEx
,
362 if (EFI_ERROR (Status
)) {
363 gBS
->UninstallMultipleProtocolInterfaces (
365 &gEfiSimpleTextInProtocolGuid
,
366 &UsbKeyboardDevice
->SimpleInput
,
367 &gEfiSimpleTextInputExProtocolGuid
,
368 &UsbKeyboardDevice
->SimpleInputEx
,
375 // Submit Asynchronous Interrupt Transfer to manage this device.
377 EndpointAddr
= UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
;
378 PollingInterval
= UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
;
379 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
381 Status
= UsbIo
->UsbAsyncInterruptTransfer (
391 if (EFI_ERROR (Status
)) {
392 gBS
->UninstallMultipleProtocolInterfaces (
394 &gEfiSimpleTextInProtocolGuid
,
395 &UsbKeyboardDevice
->SimpleInput
,
396 &gEfiSimpleTextInputExProtocolGuid
,
397 &UsbKeyboardDevice
->SimpleInputEx
,
403 UsbKeyboardDevice
->ControllerNameTable
= NULL
;
406 gUsbKeyboardComponentName
.SupportedLanguages
,
407 &UsbKeyboardDevice
->ControllerNameTable
,
408 L
"Generic Usb Keyboard",
413 gUsbKeyboardComponentName2
.SupportedLanguages
,
414 &UsbKeyboardDevice
->ControllerNameTable
,
415 L
"Generic Usb Keyboard",
419 gBS
->RestoreTPL (OldTpl
);
426 if (UsbKeyboardDevice
!= NULL
) {
427 if (UsbKeyboardDevice
->TimerEvent
!= NULL
) {
428 gBS
->CloseEvent (UsbKeyboardDevice
->TimerEvent
);
430 if (UsbKeyboardDevice
->SimpleInput
.WaitForKey
!= NULL
) {
431 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
433 if (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
434 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
436 if (UsbKeyboardDevice
->KeyNotifyProcessEvent
!= NULL
) {
437 gBS
->CloseEvent (UsbKeyboardDevice
->KeyNotifyProcessEvent
);
439 if (UsbKeyboardDevice
->KeyboardLayoutEvent
!= NULL
) {
440 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
441 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
443 FreePool (UsbKeyboardDevice
);
444 UsbKeyboardDevice
= NULL
;
448 &gEfiUsbIoProtocolGuid
,
449 This
->DriverBindingHandle
,
454 gBS
->RestoreTPL (OldTpl
);
462 Stop the USB keyboard device handled by this driver.
464 @param This The USB keyboard driver binding protocol.
465 @param Controller The controller to release.
466 @param NumberOfChildren The number of handles in ChildHandleBuffer.
467 @param ChildHandleBuffer The array of child handle.
469 @retval EFI_SUCCESS The device was stopped.
470 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
471 is not installed on Controller.
472 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
473 @retval Others Fail to uninstall protocols attached on the device.
478 USBKeyboardDriverBindingStop (
479 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
480 IN EFI_HANDLE Controller
,
481 IN UINTN NumberOfChildren
,
482 IN EFI_HANDLE
*ChildHandleBuffer
486 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
487 USB_KB_DEV
*UsbKeyboardDevice
;
489 Status
= gBS
->OpenProtocol (
491 &gEfiSimpleTextInProtocolGuid
,
492 (VOID
**) &SimpleInput
,
493 This
->DriverBindingHandle
,
495 EFI_OPEN_PROTOCOL_GET_PROTOCOL
497 if (EFI_ERROR (Status
)) {
498 return EFI_UNSUPPORTED
;
501 Status
= gBS
->OpenProtocol (
503 &gEfiSimpleTextInputExProtocolGuid
,
505 This
->DriverBindingHandle
,
507 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
509 if (EFI_ERROR (Status
)) {
510 return EFI_UNSUPPORTED
;
513 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
516 // The key data input from this device will be disabled.
518 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
520 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DISABLE
),
521 UsbKeyboardDevice
->DevicePath
525 // Delete the Asynchronous Interrupt Transfer from this device
527 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
528 UsbKeyboardDevice
->UsbIo
,
529 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
531 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
539 &gEfiUsbIoProtocolGuid
,
540 This
->DriverBindingHandle
,
544 Status
= gBS
->UninstallMultipleProtocolInterfaces (
546 &gEfiSimpleTextInProtocolGuid
,
547 &UsbKeyboardDevice
->SimpleInput
,
548 &gEfiSimpleTextInputExProtocolGuid
,
549 &UsbKeyboardDevice
->SimpleInputEx
,
553 // Free all resources.
555 gBS
->CloseEvent (UsbKeyboardDevice
->TimerEvent
);
556 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
557 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
558 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
559 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
560 gBS
->CloseEvent (UsbKeyboardDevice
->KeyNotifyProcessEvent
);
561 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
563 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
564 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
566 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
567 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
570 DestroyQueue (&UsbKeyboardDevice
->UsbKeyQueue
);
571 DestroyQueue (&UsbKeyboardDevice
->EfiKeyQueue
);
572 DestroyQueue (&UsbKeyboardDevice
->EfiKeyQueueForNotify
);
574 FreePool (UsbKeyboardDevice
);
580 Internal function to read the next keystroke from the keyboard buffer.
582 @param UsbKeyboardDevice USB keyboard's private structure.
583 @param KeyData A pointer to buffer to hold the keystroke
584 data for the key that was pressed.
586 @retval EFI_SUCCESS The keystroke information was returned.
587 @retval EFI_NOT_READY There was no keystroke data availiable.
588 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
590 @retval EFI_INVALID_PARAMETER KeyData is NULL.
591 @retval Others Fail to translate keycode into EFI_INPUT_KEY
595 USBKeyboardReadKeyStrokeWorker (
596 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
597 OUT EFI_KEY_DATA
*KeyData
600 if (KeyData
== NULL
) {
601 return EFI_INVALID_PARAMETER
;
604 if (IsQueueEmpty (&UsbKeyboardDevice
->EfiKeyQueue
)) {
605 ZeroMem (&KeyData
->Key
, sizeof (KeyData
->Key
));
606 InitializeKeyState (UsbKeyboardDevice
, &KeyData
->KeyState
);
607 return EFI_NOT_READY
;
610 Dequeue (&UsbKeyboardDevice
->EfiKeyQueue
, KeyData
, sizeof (*KeyData
));
616 Reset the input device and optionally run diagnostics
618 There are 2 types of reset for USB keyboard.
619 For non-exhaustive reset, only keyboard buffer is cleared.
620 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
621 is also re-initialized.
623 @param This Protocol instance pointer.
624 @param ExtendedVerification Driver may perform diagnostics on reset.
626 @retval EFI_SUCCESS The device was reset.
627 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
633 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
634 IN BOOLEAN ExtendedVerification
638 USB_KB_DEV
*UsbKeyboardDevice
;
640 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
642 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
644 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
),
645 UsbKeyboardDevice
->DevicePath
649 // Non-exhaustive reset:
650 // only reset private data structures.
652 if (!ExtendedVerification
) {
653 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
655 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
),
656 UsbKeyboardDevice
->DevicePath
659 // Clear the key buffer of this USB keyboard
661 InitQueue (&UsbKeyboardDevice
->UsbKeyQueue
, sizeof (USB_KEY
));
662 InitQueue (&UsbKeyboardDevice
->EfiKeyQueue
, sizeof (EFI_KEY_DATA
));
663 InitQueue (&UsbKeyboardDevice
->EfiKeyQueueForNotify
, sizeof (EFI_KEY_DATA
));
671 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
672 if (EFI_ERROR (Status
)) {
673 return EFI_DEVICE_ERROR
;
681 Reads the next keystroke from the input device.
683 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
684 @param Key A pointer to a buffer that is filled in with the keystroke
685 information for the key that was pressed.
687 @retval EFI_SUCCESS The keystroke information was returned.
688 @retval EFI_NOT_READY There was no keystroke data availiable.
689 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
695 USBKeyboardReadKeyStroke (
696 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
697 OUT EFI_INPUT_KEY
*Key
700 USB_KB_DEV
*UsbKeyboardDevice
;
702 EFI_KEY_DATA KeyData
;
704 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
707 // Considering if the partial keystroke is enabled, there maybe a partial
708 // keystroke in the queue, so here skip the partial keystroke and get the
709 // next key from the queue
712 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
713 if (EFI_ERROR (Status
)) {
717 // SimpleTextIn Protocol doesn't support partial keystroke;
719 if (KeyData
.Key
.ScanCode
== CHAR_NULL
&& KeyData
.Key
.UnicodeChar
== SCAN_NULL
) {
723 // Translate the CTRL-Alpha characters to their corresponding control value
724 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
726 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
727 if (KeyData
.Key
.UnicodeChar
>= L
'a' && KeyData
.Key
.UnicodeChar
<= L
'z') {
728 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'a' + 1);
729 } else if (KeyData
.Key
.UnicodeChar
>= L
'A' && 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
));
741 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
742 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.
744 @param Event Event to be signaled when a key is pressed.
745 @param Context Points to USB_KB_DEV instance.
750 USBKeyboardWaitForKey (
755 USB_KB_DEV
*UsbKeyboardDevice
;
756 EFI_KEY_DATA KeyData
;
759 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
762 // Enter critical section
764 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
767 // WaitforKey doesn't suppor the partial key.
768 // Considering if the partial keystroke is enabled, there maybe a partial
769 // keystroke in the queue, so here skip the partial keystroke and get the
770 // next key from the queue
772 while (!IsQueueEmpty (&UsbKeyboardDevice
->EfiKeyQueue
)) {
774 // If there is pending key, signal the event.
778 UsbKeyboardDevice
->EfiKeyQueue
.Buffer
[UsbKeyboardDevice
->EfiKeyQueue
.Head
],
779 sizeof (EFI_KEY_DATA
)
781 if (KeyData
.Key
.ScanCode
== SCAN_NULL
&& KeyData
.Key
.UnicodeChar
== CHAR_NULL
) {
782 Dequeue (&UsbKeyboardDevice
->EfiKeyQueue
, &KeyData
, sizeof (EFI_KEY_DATA
));
785 gBS
->SignalEvent (Event
);
789 // Leave critical section and return
791 gBS
->RestoreTPL (OldTpl
);
795 Timer handler to convert the key from USB.
797 @param Event Indicates the event that invoke this function.
798 @param Context Indicates the calling context.
802 USBKeyboardTimerHandler (
808 USB_KB_DEV
*UsbKeyboardDevice
;
810 EFI_KEY_DATA KeyData
;
812 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
815 // Fetch raw data from the USB keyboard buffer,
816 // and translate it into USB keycode.
818 Status
= USBParseKey (UsbKeyboardDevice
, &KeyCode
);
819 if (EFI_ERROR (Status
)) {
824 // Translate saved USB keycode into EFI_INPUT_KEY
826 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyCode
, &KeyData
);
827 if (EFI_ERROR (Status
)) {
832 // Insert to the EFI Key queue
834 Enqueue (&UsbKeyboardDevice
->EfiKeyQueue
, &KeyData
, sizeof (KeyData
));
838 Free keyboard notify list.
840 @param NotifyList The keyboard notify list to free.
842 @retval EFI_SUCCESS Free the notify list successfully.
843 @retval EFI_INVALID_PARAMETER NotifyList is NULL.
848 IN OUT LIST_ENTRY
*NotifyList
851 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
854 if (NotifyList
== NULL
) {
855 return EFI_INVALID_PARAMETER
;
857 while (!IsListEmpty (NotifyList
)) {
858 Link
= GetFirstNode (NotifyList
);
859 NotifyNode
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
860 RemoveEntryList (Link
);
861 FreePool (NotifyNode
);
868 Check whether the pressed key matches a registered key or not.
870 @param RegsiteredData A pointer to keystroke data for the key that was registered.
871 @param InputData A pointer to keystroke data for the key that was pressed.
873 @retval TRUE Key pressed matches a registered key.
874 @retval FLASE Key pressed does not matches a registered key.
879 IN EFI_KEY_DATA
*RegsiteredData
,
880 IN EFI_KEY_DATA
*InputData
883 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
885 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
886 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
891 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
893 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
894 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
897 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
898 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
906 // Simple Text Input Ex protocol functions
909 Resets the input device hardware.
911 The Reset() function resets the input device hardware. As part
912 of initialization process, the firmware/device will make a quick
913 but reasonable attempt to verify that the device is functioning.
914 If the ExtendedVerification flag is TRUE the firmware may take
915 an extended amount of time to verify the device is operating on
916 reset. Otherwise the reset operation is to occur as quickly as
917 possible. The hardware verification process is not defined by
918 this specification and is left up to the platform firmware or
921 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
923 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
924 verification operation of the device during reset.
926 @retval EFI_SUCCESS The device was reset.
927 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
933 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
934 IN BOOLEAN ExtendedVerification
938 USB_KB_DEV
*UsbKeyboardDevice
;
940 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
942 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
943 if (EFI_ERROR (Status
)) {
944 return EFI_DEVICE_ERROR
;
947 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
948 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
955 Reads the next keystroke from the input device.
957 @param This Protocol instance pointer.
958 @param KeyData A pointer to a buffer that is filled in with the keystroke
959 state data for the key that was pressed.
961 @retval EFI_SUCCESS The keystroke information was returned.
962 @retval EFI_NOT_READY There was no keystroke data available.
963 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
965 @retval EFI_INVALID_PARAMETER KeyData is NULL.
970 USBKeyboardReadKeyStrokeEx (
971 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
972 OUT EFI_KEY_DATA
*KeyData
975 USB_KB_DEV
*UsbKeyboardDevice
;
977 if (KeyData
== NULL
) {
978 return EFI_INVALID_PARAMETER
;
981 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
983 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, KeyData
);
988 Set certain state for the input device.
990 @param This Protocol instance pointer.
991 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
992 state for the input device.
994 @retval EFI_SUCCESS The device state was set appropriately.
995 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
996 not have the setting adjusted.
997 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.
998 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
1003 USBKeyboardSetState (
1004 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1005 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
1008 USB_KB_DEV
*UsbKeyboardDevice
;
1010 if (KeyToggleState
== NULL
) {
1011 return EFI_INVALID_PARAMETER
;
1014 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1016 if (((UsbKeyboardDevice
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
1017 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
1018 return EFI_UNSUPPORTED
;
1022 // Update the status light
1025 UsbKeyboardDevice
->ScrollOn
= FALSE
;
1026 UsbKeyboardDevice
->NumLockOn
= FALSE
;
1027 UsbKeyboardDevice
->CapsOn
= FALSE
;
1028 UsbKeyboardDevice
->IsSupportPartialKey
= FALSE
;
1030 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
1031 UsbKeyboardDevice
->ScrollOn
= TRUE
;
1033 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
1034 UsbKeyboardDevice
->NumLockOn
= TRUE
;
1036 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
1037 UsbKeyboardDevice
->CapsOn
= TRUE
;
1039 if ((*KeyToggleState
& EFI_KEY_STATE_EXPOSED
) == EFI_KEY_STATE_EXPOSED
) {
1040 UsbKeyboardDevice
->IsSupportPartialKey
= TRUE
;
1043 SetKeyLED (UsbKeyboardDevice
);
1045 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
1052 Register a notification function for a particular keystroke for the input device.
1054 @param This Protocol instance pointer.
1055 @param KeyData A pointer to a buffer that is filled in with
1056 the keystroke information for the key that was
1057 pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState
1058 and KeyData.KeyState.KeyShiftState are 0, then any incomplete
1059 keystroke will trigger a notification of the KeyNotificationFunction.
1060 @param KeyNotificationFunction Points to the function to be called when the key
1061 sequence is typed specified by KeyData. This notification function
1062 should be called at <=TPL_CALLBACK.
1063 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1065 @retval EFI_SUCCESS The notification function was registered successfully.
1066 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.
1067 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
1072 USBKeyboardRegisterKeyNotify (
1073 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1074 IN EFI_KEY_DATA
*KeyData
,
1075 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
1076 OUT VOID
**NotifyHandle
1079 USB_KB_DEV
*UsbKeyboardDevice
;
1080 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
1082 LIST_ENTRY
*NotifyList
;
1083 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1085 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
1086 return EFI_INVALID_PARAMETER
;
1089 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1092 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1094 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1096 for (Link
= GetFirstNode (NotifyList
);
1097 !IsNull (NotifyList
, Link
);
1098 Link
= GetNextNode (NotifyList
, Link
)) {
1099 CurrentNotify
= CR (
1101 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1103 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1105 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
1106 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
1107 *NotifyHandle
= CurrentNotify
;
1114 // Allocate resource to save the notification function
1116 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
1117 if (NewNotify
== NULL
) {
1118 return EFI_OUT_OF_RESOURCES
;
1121 NewNotify
->Signature
= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
1122 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
1123 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
1124 InsertTailList (&UsbKeyboardDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
1127 *NotifyHandle
= NewNotify
;
1134 Remove a registered notification function from a particular keystroke.
1136 @param This Protocol instance pointer.
1137 @param NotificationHandle The handle of the notification function being unregistered.
1139 @retval EFI_SUCCESS The notification function was unregistered successfully.
1140 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid
1145 USBKeyboardUnregisterKeyNotify (
1146 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1147 IN VOID
*NotificationHandle
1150 USB_KB_DEV
*UsbKeyboardDevice
;
1151 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1153 LIST_ENTRY
*NotifyList
;
1155 if (NotificationHandle
== NULL
) {
1156 return EFI_INVALID_PARAMETER
;
1159 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1162 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1164 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1165 for (Link
= GetFirstNode (NotifyList
);
1166 !IsNull (NotifyList
, Link
);
1167 Link
= GetNextNode (NotifyList
, Link
)) {
1168 CurrentNotify
= CR (
1170 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1172 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1174 if (CurrentNotify
== NotificationHandle
) {
1176 // Remove the notification function from NotifyList and free resources
1178 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
1180 FreePool (CurrentNotify
);
1186 // Cannot find the matching entry in database.
1188 return EFI_INVALID_PARAMETER
;
1194 @param Event Indicates the event that invoke this function.
1195 @param Context Indicates the calling context.
1199 KeyNotifyProcessHandler (
1205 USB_KB_DEV
*UsbKeyboardDevice
;
1206 EFI_KEY_DATA KeyData
;
1208 LIST_ENTRY
*NotifyList
;
1209 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1212 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
1215 // Invoke notification functions.
1217 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1220 // Enter critical section
1222 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1223 Status
= Dequeue (&UsbKeyboardDevice
->EfiKeyQueueForNotify
, &KeyData
, sizeof (KeyData
));
1225 // Leave critical section
1227 gBS
->RestoreTPL (OldTpl
);
1228 if (EFI_ERROR (Status
)) {
1231 for (Link
= GetFirstNode (NotifyList
); !IsNull (NotifyList
, Link
); Link
= GetNextNode (NotifyList
, Link
)) {
1232 CurrentNotify
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
1233 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &KeyData
)) {
1234 CurrentNotify
->KeyNotificationFn (&KeyData
);