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 - 2008, Intel Corporation
6 All rights reserved. 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 // Open USB I/O Protocol
161 Status
= gBS
->OpenProtocol (
163 &gEfiUsbIoProtocolGuid
,
165 This
->DriverBindingHandle
,
167 EFI_OPEN_PROTOCOL_BY_DRIVER
169 if (EFI_ERROR (Status
)) {
173 UsbKeyboardDevice
= AllocateZeroPool (sizeof (USB_KB_DEV
));
174 ASSERT (UsbKeyboardDevice
!= NULL
);
177 // Get the Device Path Protocol on Controller's handle
179 Status
= gBS
->OpenProtocol (
181 &gEfiDevicePathProtocolGuid
,
182 (VOID
**) &UsbKeyboardDevice
->DevicePath
,
183 This
->DriverBindingHandle
,
185 EFI_OPEN_PROTOCOL_GET_PROTOCOL
188 if (EFI_ERROR (Status
)) {
192 // Report that the USB keyboard is being enabled
194 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
196 PcdGet32 (PcdStatusCodeValueKeyboardEnable
),
197 UsbKeyboardDevice
->DevicePath
201 // This is pretty close to keyboard detection, so log progress
203 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
205 PcdGet32 (PcdStatusCodeValueKeyboardPresenceDetect
),
206 UsbKeyboardDevice
->DevicePath
209 UsbKeyboardDevice
->UsbIo
= UsbIo
;
212 // Get interface & endpoint descriptor
214 UsbIo
->UsbGetInterfaceDescriptor (
216 &UsbKeyboardDevice
->InterfaceDescriptor
219 EndpointNumber
= UsbKeyboardDevice
->InterfaceDescriptor
.NumEndpoints
;
222 // Traverse endpoints to find interrupt endpoint
225 for (Index
= 0; Index
< EndpointNumber
; Index
++) {
227 UsbIo
->UsbGetEndpointDescriptor (
233 if ((EndpointDescriptor
.Attributes
& (BIT0
| BIT1
)) == USB_ENDPOINT_INTERRUPT
) {
235 // We only care interrupt endpoint here
237 CopyMem(&UsbKeyboardDevice
->IntEndpointDescriptor
, &EndpointDescriptor
, sizeof(EndpointDescriptor
));
245 // No interrupt endpoint found, then return unsupported.
247 Status
= EFI_UNSUPPORTED
;
251 UsbKeyboardDevice
->Signature
= USB_KB_DEV_SIGNATURE
;
252 UsbKeyboardDevice
->SimpleInput
.Reset
= USBKeyboardReset
;
253 UsbKeyboardDevice
->SimpleInput
.ReadKeyStroke
= USBKeyboardReadKeyStroke
;
255 UsbKeyboardDevice
->SimpleInputEx
.Reset
= USBKeyboardResetEx
;
256 UsbKeyboardDevice
->SimpleInputEx
.ReadKeyStrokeEx
= USBKeyboardReadKeyStrokeEx
;
257 UsbKeyboardDevice
->SimpleInputEx
.SetState
= USBKeyboardSetState
;
258 UsbKeyboardDevice
->SimpleInputEx
.RegisterKeyNotify
= USBKeyboardRegisterKeyNotify
;
259 UsbKeyboardDevice
->SimpleInputEx
.UnregisterKeyNotify
= USBKeyboardUnregisterKeyNotify
;
261 InitializeListHead (&UsbKeyboardDevice
->NotifyList
);
263 Status
= gBS
->CreateEvent (
266 USBKeyboardWaitForKey
,
268 &(UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
)
271 if (EFI_ERROR (Status
)) {
275 Status
= gBS
->CreateEvent (
278 USBKeyboardWaitForKey
,
280 &(UsbKeyboardDevice
->SimpleInput
.WaitForKey
)
282 if (EFI_ERROR (Status
)) {
287 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol
288 // for the USB keyboard device.
289 // USB keyboard is a hot plug device, and expected to work immediately
290 // when plugging into system, other conventional console devices could
291 // distinguish it by its device path.
293 Status
= gBS
->InstallMultipleProtocolInterfaces (
295 &gEfiSimpleTextInProtocolGuid
,
296 &UsbKeyboardDevice
->SimpleInput
,
297 &gEfiSimpleTextInputExProtocolGuid
,
298 &UsbKeyboardDevice
->SimpleInputEx
,
301 if (EFI_ERROR (Status
)) {
305 UsbKeyboardDevice
->ControllerHandle
= Controller
;
306 Status
= InitKeyboardLayout (UsbKeyboardDevice
);
307 if (EFI_ERROR (Status
)) {
308 gBS
->UninstallMultipleProtocolInterfaces (
310 &gEfiSimpleTextInProtocolGuid
,
311 &UsbKeyboardDevice
->SimpleInput
,
312 &gEfiSimpleTextInputExProtocolGuid
,
313 &UsbKeyboardDevice
->SimpleInputEx
,
321 // Reset USB Keyboard Device exhaustively.
323 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (
324 &UsbKeyboardDevice
->SimpleInput
,
327 if (EFI_ERROR (Status
)) {
328 gBS
->UninstallMultipleProtocolInterfaces (
330 &gEfiSimpleTextInProtocolGuid
,
331 &UsbKeyboardDevice
->SimpleInput
,
332 &gEfiSimpleTextInputExProtocolGuid
,
333 &UsbKeyboardDevice
->SimpleInputEx
,
340 // Submit Asynchronous Interrupt Transfer to manage this device.
342 EndpointAddr
= UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
;
343 PollingInterval
= UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
;
344 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
346 Status
= UsbIo
->UsbAsyncInterruptTransfer (
356 if (EFI_ERROR (Status
)) {
357 gBS
->UninstallMultipleProtocolInterfaces (
359 &gEfiSimpleTextInProtocolGuid
,
360 &UsbKeyboardDevice
->SimpleInput
,
361 &gEfiSimpleTextInputExProtocolGuid
,
362 &UsbKeyboardDevice
->SimpleInputEx
,
368 UsbKeyboardDevice
->ControllerNameTable
= NULL
;
371 gUsbKeyboardComponentName
.SupportedLanguages
,
372 &UsbKeyboardDevice
->ControllerNameTable
,
373 L
"Generic Usb Keyboard",
378 gUsbKeyboardComponentName2
.SupportedLanguages
,
379 &UsbKeyboardDevice
->ControllerNameTable
,
380 L
"Generic Usb Keyboard",
390 if (UsbKeyboardDevice
!= NULL
) {
391 if (UsbKeyboardDevice
->SimpleInput
.WaitForKey
!= NULL
) {
392 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
394 if (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
395 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
397 FreePool (UsbKeyboardDevice
);
398 UsbKeyboardDevice
= NULL
;
402 &gEfiUsbIoProtocolGuid
,
403 This
->DriverBindingHandle
,
412 Stop the USB keyboard device handled by this driver.
414 @param This The USB keyboard driver binding protocol.
415 @param Controller The controller to release.
416 @param NumberOfChildren The number of handles in ChildHandleBuffer.
417 @param ChildHandleBuffer The array of child handle.
419 @retval EFI_SUCCESS The device was stopped.
420 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
421 is not installed on Controller.
422 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
423 @retval Others Fail to uninstall protocols attached on the device.
428 USBKeyboardDriverBindingStop (
429 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
430 IN EFI_HANDLE Controller
,
431 IN UINTN NumberOfChildren
,
432 IN EFI_HANDLE
*ChildHandleBuffer
436 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
437 USB_KB_DEV
*UsbKeyboardDevice
;
439 Status
= gBS
->OpenProtocol (
441 &gEfiSimpleTextInProtocolGuid
,
442 (VOID
**) &SimpleInput
,
443 This
->DriverBindingHandle
,
445 EFI_OPEN_PROTOCOL_GET_PROTOCOL
447 if (EFI_ERROR (Status
)) {
448 return EFI_UNSUPPORTED
;
451 Status
= gBS
->OpenProtocol (
453 &gEfiSimpleTextInputExProtocolGuid
,
455 This
->DriverBindingHandle
,
457 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
459 if (EFI_ERROR (Status
)) {
460 return EFI_UNSUPPORTED
;
463 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
466 // The key data input from this device will be disabled.
468 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
470 PcdGet32 (PcdStatusCodeValueKeyboardDisable
),
471 UsbKeyboardDevice
->DevicePath
475 // Delete the Asynchronous Interrupt Transfer from this device
477 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
478 UsbKeyboardDevice
->UsbIo
,
479 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
481 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
489 &gEfiUsbIoProtocolGuid
,
490 This
->DriverBindingHandle
,
494 Status
= gBS
->UninstallMultipleProtocolInterfaces (
496 &gEfiSimpleTextInProtocolGuid
,
497 &UsbKeyboardDevice
->SimpleInput
,
498 &gEfiSimpleTextInputExProtocolGuid
,
499 &UsbKeyboardDevice
->SimpleInputEx
,
503 // Free all resources.
505 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
506 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
507 gBS
->CloseEvent ((UsbKeyboardDevice
->SimpleInput
).WaitForKey
);
508 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
509 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
511 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
512 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
514 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
515 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
518 FreePool (UsbKeyboardDevice
);
524 Internal function to read the next keystroke from the keyboard buffer.
526 @param UsbKeyboardDevice USB keyboard's private structure.
527 @param KeyData A pointer to buffer to hold the keystroke
528 data for the key that was pressed.
530 @retval EFI_SUCCESS The keystroke information was returned.
531 @retval EFI_NOT_READY There was no keystroke data availiable.
532 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
534 @retval EFI_INVALID_PARAMETER KeyData is NULL.
535 @retval Others Fail to translate keycode into EFI_INPUT_KEY
540 USBKeyboardReadKeyStrokeWorker (
541 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
542 OUT EFI_KEY_DATA
*KeyData
548 LIST_ENTRY
*NotifyList
;
549 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
550 EFI_KEY_DATA OriginalKeyData
;
552 if (KeyData
== NULL
) {
553 return EFI_INVALID_PARAMETER
;
557 // If there is no saved USB keycode, fetch it
558 // by calling USBKeyboardCheckForKey().
560 if (UsbKeyboardDevice
->CurKeyCode
== 0) {
561 Status
= USBKeyboardCheckForKey (UsbKeyboardDevice
);
562 if (EFI_ERROR (Status
)) {
563 return EFI_NOT_READY
;
567 KeyData
->Key
.UnicodeChar
= 0;
568 KeyData
->Key
.ScanCode
= SCAN_NULL
;
571 // Store the current keycode and clear it.
573 KeyCode
= UsbKeyboardDevice
->CurKeyCode
;
574 UsbKeyboardDevice
->CurKeyCode
= 0;
577 // Translate saved USB keycode into EFI_INPUT_KEY
579 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyCode
, &KeyData
->Key
);
580 if (EFI_ERROR (Status
)) {
585 // Get current state of various toggled attributes as well as input modifier values,
586 // and set them as valid.
588 CopyMem (&KeyData
->KeyState
, &UsbKeyboardDevice
->KeyState
, sizeof (KeyData
->KeyState
));
590 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
591 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
594 // Switch the control value to their original characters.
595 // In UsbKeyCodeToEfiInputKey() the CTRL-Alpha characters have been switched to
596 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A),
597 // here switch them back for notification function.
599 CopyMem (&OriginalKeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
600 if (UsbKeyboardDevice
->CtrlOn
) {
601 if (OriginalKeyData
.Key
.UnicodeChar
>= 0x01 && OriginalKeyData
.Key
.UnicodeChar
<= 0x1A) {
602 if (UsbKeyboardDevice
->CapsOn
) {
603 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'A' - 1);
605 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'a' - 1);
611 // Invoke notification functions if the key is registered.
613 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
614 for (Link
= GetFirstNode (NotifyList
);
615 !IsNull (NotifyList
, Link
);
616 Link
= GetNextNode (NotifyList
, Link
)) {
617 CurrentNotify
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
618 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &OriginalKeyData
)) {
619 CurrentNotify
->KeyNotificationFn (&OriginalKeyData
);
627 Reset the input device and optionally run diagnostics
629 There are 2 types of reset for USB keyboard.
630 For non-exhaustive reset, only keyboard buffer is cleared.
631 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
632 is also re-initialized.
634 @param This Protocol instance pointer.
635 @param ExtendedVerification Driver may perform diagnostics on reset.
637 @retval EFI_SUCCESS The device was reset.
638 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
644 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
645 IN BOOLEAN ExtendedVerification
649 USB_KB_DEV
*UsbKeyboardDevice
;
651 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
653 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
655 PcdGet32 (PcdStatusCodeValueKeyboardReset
),
656 UsbKeyboardDevice
->DevicePath
660 // Non-exhaustive reset:
661 // only reset private data structures.
663 if (!ExtendedVerification
) {
664 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
666 PcdGet32 (PcdStatusCodeValueKeyboardClearBuffer
),
667 UsbKeyboardDevice
->DevicePath
670 // Clear the key buffer of this USB keyboard
672 InitUSBKeyBuffer (&(UsbKeyboardDevice
->KeyboardBuffer
));
673 UsbKeyboardDevice
->CurKeyCode
= 0;
681 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
682 UsbKeyboardDevice
->CurKeyCode
= 0;
683 if (EFI_ERROR (Status
)) {
684 return EFI_DEVICE_ERROR
;
692 Reads the next keystroke from the input device.
694 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
695 @param Key A pointer to a buffer that is filled in with the keystroke
696 information for the key that was pressed.
698 @retval EFI_SUCCESS The keystroke information was returned.
699 @retval EFI_NOT_READY There was no keystroke data availiable.
700 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
706 USBKeyboardReadKeyStroke (
707 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
708 OUT EFI_INPUT_KEY
*Key
711 USB_KB_DEV
*UsbKeyboardDevice
;
713 EFI_KEY_DATA KeyData
;
715 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
717 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
718 if (EFI_ERROR (Status
)) {
722 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
729 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
730 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.
732 @param Event Event to be signaled when a key is pressed.
733 @param Context Points to USB_KB_DEV instance.
738 USBKeyboardWaitForKey (
743 USB_KB_DEV
*UsbKeyboardDevice
;
745 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
747 if (UsbKeyboardDevice
->CurKeyCode
== 0) {
748 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice
))) {
750 // If no pending key, simply return.
756 // If there is pending key, signal the event.
758 gBS
->SignalEvent (Event
);
763 Check whether there is key pending in the keyboard buffer.
765 @param UsbKeyboardDevice The USB_KB_DEV instance.
767 @retval EFI_SUCCESS There is pending key to read.
768 @retval EFI_NOT_READY No pending key to read.
773 USBKeyboardCheckForKey (
774 IN OUT USB_KB_DEV
*UsbKeyboardDevice
781 // Fetch raw data from the USB keyboard buffer,
782 // and translate it into USB keycode.
784 Status
= USBParseKey (UsbKeyboardDevice
, &KeyCode
);
785 if (EFI_ERROR (Status
)) {
786 return EFI_NOT_READY
;
789 UsbKeyboardDevice
->CurKeyCode
= KeyCode
;
794 Free keyboard notify list.
796 @param NotifyList The keyboard notify list to free.
798 @retval EFI_SUCCESS Free the notify list successfully.
799 @retval EFI_INVALID_PARAMETER NotifyList is NULL.
805 IN OUT LIST_ENTRY
*NotifyList
808 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
811 if (NotifyList
== NULL
) {
812 return EFI_INVALID_PARAMETER
;
814 while (!IsListEmpty (NotifyList
)) {
815 Link
= GetFirstNode (NotifyList
);
816 NotifyNode
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
817 RemoveEntryList (Link
);
818 FreePool (NotifyNode
);
825 Check whether the pressed key matches a registered key or not.
827 @param RegsiteredData A pointer to keystroke data for the key that was registered.
828 @param InputData A pointer to keystroke data for the key that was pressed.
830 @retval TRUE Key pressed matches a registered key.
831 @retval FLASE Key pressed does not matches a registered key.
837 IN EFI_KEY_DATA
*RegsiteredData
,
838 IN EFI_KEY_DATA
*InputData
841 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
843 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
844 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
849 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
851 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
852 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
855 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
856 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
864 // Simple Text Input Ex protocol functions
867 Resets the input device hardware.
869 The Reset() function resets the input device hardware. As part
870 of initialization process, the firmware/device will make a quick
871 but reasonable attempt to verify that the device is functioning.
872 If the ExtendedVerification flag is TRUE the firmware may take
873 an extended amount of time to verify the device is operating on
874 reset. Otherwise the reset operation is to occur as quickly as
875 possible. The hardware verification process is not defined by
876 this specification and is left up to the platform firmware or
879 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
881 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
882 verification operation of the device during reset.
884 @retval EFI_SUCCESS The device was reset.
885 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
891 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
892 IN BOOLEAN ExtendedVerification
896 USB_KB_DEV
*UsbKeyboardDevice
;
900 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
902 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
903 if (EFI_ERROR (Status
)) {
904 return EFI_DEVICE_ERROR
;
907 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
908 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
909 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
910 gBS
->RestoreTPL (OldTpl
);
917 Reads the next keystroke from the input device.
919 @param This Protocol instance pointer.
920 @param KeyData A pointer to a buffer that is filled in with the keystroke
921 state data for the key that was pressed.
923 @retval EFI_SUCCESS The keystroke information was returned.
924 @retval EFI_NOT_READY There was no keystroke data available.
925 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
927 @retval EFI_INVALID_PARAMETER KeyData is NULL.
932 USBKeyboardReadKeyStrokeEx (
933 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
934 OUT EFI_KEY_DATA
*KeyData
937 USB_KB_DEV
*UsbKeyboardDevice
;
939 if (KeyData
== NULL
) {
940 return EFI_INVALID_PARAMETER
;
943 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
945 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, KeyData
);
950 Set certain state for the input device.
952 @param This Protocol instance pointer.
953 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
954 state for the input device.
956 @retval EFI_SUCCESS The device state was set appropriately.
957 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
958 not have the setting adjusted.
959 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.
960 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
965 USBKeyboardSetState (
966 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
967 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
970 USB_KB_DEV
*UsbKeyboardDevice
;
972 if (KeyToggleState
== NULL
) {
973 return EFI_INVALID_PARAMETER
;
976 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
978 if (((UsbKeyboardDevice
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
979 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
980 return EFI_UNSUPPORTED
;
984 // Update the status light
987 UsbKeyboardDevice
->ScrollOn
= FALSE
;
988 UsbKeyboardDevice
->NumLockOn
= FALSE
;
989 UsbKeyboardDevice
->CapsOn
= FALSE
;
991 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
992 UsbKeyboardDevice
->ScrollOn
= TRUE
;
994 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
995 UsbKeyboardDevice
->NumLockOn
= TRUE
;
997 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
998 UsbKeyboardDevice
->CapsOn
= TRUE
;
1001 SetKeyLED (UsbKeyboardDevice
);
1003 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
1010 Register a notification function for a particular keystroke for the input device.
1012 @param This Protocol instance pointer.
1013 @param KeyData A pointer to a buffer that is filled in with the keystroke
1014 information data for the key that was pressed.
1015 @param KeyNotificationFunction Points to the function to be called when the key
1016 sequence is typed specified by KeyData.
1017 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1019 @retval EFI_SUCCESS The notification function was registered successfully.
1020 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.
1021 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
1026 USBKeyboardRegisterKeyNotify (
1027 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1028 IN EFI_KEY_DATA
*KeyData
,
1029 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
1030 OUT EFI_HANDLE
*NotifyHandle
1033 USB_KB_DEV
*UsbKeyboardDevice
;
1034 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
1036 LIST_ENTRY
*NotifyList
;
1037 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1039 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
1040 return EFI_INVALID_PARAMETER
;
1043 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1046 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1048 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1050 for (Link
= GetFirstNode (NotifyList
);
1051 !IsNull (NotifyList
, Link
);
1052 Link
= GetNextNode (NotifyList
, Link
)) {
1053 CurrentNotify
= CR (
1055 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1057 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1059 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
1060 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
1061 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
1068 // Allocate resource to save the notification function
1070 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
1071 if (NewNotify
== NULL
) {
1072 return EFI_OUT_OF_RESOURCES
;
1075 NewNotify
->Signature
= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
1076 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
1077 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
1078 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
1079 InsertTailList (&UsbKeyboardDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
1082 *NotifyHandle
= NewNotify
->NotifyHandle
;
1089 Remove a registered notification function from a particular keystroke.
1091 @param This Protocol instance pointer.
1092 @param NotificationHandle The handle of the notification function being unregistered.
1094 @retval EFI_SUCCESS The notification function was unregistered successfully.
1095 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid
1100 USBKeyboardUnregisterKeyNotify (
1101 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1102 IN EFI_HANDLE NotificationHandle
1105 USB_KB_DEV
*UsbKeyboardDevice
;
1106 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1108 LIST_ENTRY
*NotifyList
;
1110 if (NotificationHandle
== NULL
) {
1111 return EFI_INVALID_PARAMETER
;
1114 if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
1115 return EFI_INVALID_PARAMETER
;
1118 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1121 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1123 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1124 for (Link
= GetFirstNode (NotifyList
);
1125 !IsNull (NotifyList
, Link
);
1126 Link
= GetNextNode (NotifyList
, Link
)) {
1127 CurrentNotify
= CR (
1129 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1131 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1133 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
1135 // Remove the notification function from NotifyList and free resources
1137 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
1139 FreePool (CurrentNotify
);
1145 // Cannot find the matching entry in database.
1147 return EFI_INVALID_PARAMETER
;