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 - 2010, 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 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_ENABLE
),
197 UsbKeyboardDevice
->DevicePath
201 // This is pretty close to keyboard detection, so log progress
203 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
205 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_PRESENCE_DETECT
),
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 if (UsbKeyboardDevice
->KeyboardLayoutEvent
!= NULL
) {
398 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
399 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
401 FreePool (UsbKeyboardDevice
);
402 UsbKeyboardDevice
= NULL
;
406 &gEfiUsbIoProtocolGuid
,
407 This
->DriverBindingHandle
,
416 Stop the USB keyboard device handled by this driver.
418 @param This The USB keyboard driver binding protocol.
419 @param Controller The controller to release.
420 @param NumberOfChildren The number of handles in ChildHandleBuffer.
421 @param ChildHandleBuffer The array of child handle.
423 @retval EFI_SUCCESS The device was stopped.
424 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
425 is not installed on Controller.
426 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
427 @retval Others Fail to uninstall protocols attached on the device.
432 USBKeyboardDriverBindingStop (
433 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
434 IN EFI_HANDLE Controller
,
435 IN UINTN NumberOfChildren
,
436 IN EFI_HANDLE
*ChildHandleBuffer
440 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
441 USB_KB_DEV
*UsbKeyboardDevice
;
443 Status
= gBS
->OpenProtocol (
445 &gEfiSimpleTextInProtocolGuid
,
446 (VOID
**) &SimpleInput
,
447 This
->DriverBindingHandle
,
449 EFI_OPEN_PROTOCOL_GET_PROTOCOL
451 if (EFI_ERROR (Status
)) {
452 return EFI_UNSUPPORTED
;
455 Status
= gBS
->OpenProtocol (
457 &gEfiSimpleTextInputExProtocolGuid
,
459 This
->DriverBindingHandle
,
461 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
463 if (EFI_ERROR (Status
)) {
464 return EFI_UNSUPPORTED
;
467 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
470 // The key data input from this device will be disabled.
472 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
474 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DISABLE
),
475 UsbKeyboardDevice
->DevicePath
479 // Delete the Asynchronous Interrupt Transfer from this device
481 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
482 UsbKeyboardDevice
->UsbIo
,
483 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
485 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
493 &gEfiUsbIoProtocolGuid
,
494 This
->DriverBindingHandle
,
498 Status
= gBS
->UninstallMultipleProtocolInterfaces (
500 &gEfiSimpleTextInProtocolGuid
,
501 &UsbKeyboardDevice
->SimpleInput
,
502 &gEfiSimpleTextInputExProtocolGuid
,
503 &UsbKeyboardDevice
->SimpleInputEx
,
507 // Free all resources.
509 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
510 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
511 gBS
->CloseEvent ((UsbKeyboardDevice
->SimpleInput
).WaitForKey
);
512 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
513 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
515 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
516 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
518 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
519 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
522 FreePool (UsbKeyboardDevice
);
528 Internal function to read the next keystroke from the keyboard buffer.
530 @param UsbKeyboardDevice USB keyboard's private structure.
531 @param KeyData A pointer to buffer to hold the keystroke
532 data for the key that was pressed.
534 @retval EFI_SUCCESS The keystroke information was returned.
535 @retval EFI_NOT_READY There was no keystroke data availiable.
536 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
538 @retval EFI_INVALID_PARAMETER KeyData is NULL.
539 @retval Others Fail to translate keycode into EFI_INPUT_KEY
544 USBKeyboardReadKeyStrokeWorker (
545 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
546 OUT EFI_KEY_DATA
*KeyData
552 LIST_ENTRY
*NotifyList
;
553 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
554 EFI_KEY_DATA OriginalKeyData
;
556 if (KeyData
== NULL
) {
557 return EFI_INVALID_PARAMETER
;
561 // If there is no saved USB keycode, fetch it
562 // by calling USBKeyboardCheckForKey().
564 if (UsbKeyboardDevice
->CurKeyCode
== 0) {
565 Status
= USBKeyboardCheckForKey (UsbKeyboardDevice
);
566 if (EFI_ERROR (Status
)) {
567 return EFI_NOT_READY
;
571 KeyData
->Key
.UnicodeChar
= 0;
572 KeyData
->Key
.ScanCode
= SCAN_NULL
;
575 // Store the current keycode and clear it.
577 KeyCode
= UsbKeyboardDevice
->CurKeyCode
;
578 UsbKeyboardDevice
->CurKeyCode
= 0;
581 // Translate saved USB keycode into EFI_INPUT_KEY
583 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyCode
, &KeyData
->Key
);
584 if (EFI_ERROR (Status
)) {
589 // Get current state of various toggled attributes as well as input modifier values,
590 // and set them as valid.
592 CopyMem (&KeyData
->KeyState
, &UsbKeyboardDevice
->KeyState
, sizeof (KeyData
->KeyState
));
594 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
595 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
598 // Switch the control value to their original characters.
599 // In UsbKeyCodeToEfiInputKey() the CTRL-Alpha characters have been switched to
600 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A),
601 // here switch them back for notification function.
603 CopyMem (&OriginalKeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
604 if (UsbKeyboardDevice
->CtrlOn
) {
605 if (OriginalKeyData
.Key
.UnicodeChar
>= 0x01 && OriginalKeyData
.Key
.UnicodeChar
<= 0x1A) {
606 if (UsbKeyboardDevice
->CapsOn
) {
607 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'A' - 1);
609 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'a' - 1);
615 // Invoke notification functions if the key is registered.
617 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
618 for (Link
= GetFirstNode (NotifyList
);
619 !IsNull (NotifyList
, Link
);
620 Link
= GetNextNode (NotifyList
, Link
)) {
621 CurrentNotify
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
622 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &OriginalKeyData
)) {
623 CurrentNotify
->KeyNotificationFn (&OriginalKeyData
);
631 Reset the input device and optionally run diagnostics
633 There are 2 types of reset for USB keyboard.
634 For non-exhaustive reset, only keyboard buffer is cleared.
635 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
636 is also re-initialized.
638 @param This Protocol instance pointer.
639 @param ExtendedVerification Driver may perform diagnostics on reset.
641 @retval EFI_SUCCESS The device was reset.
642 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
648 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
649 IN BOOLEAN ExtendedVerification
653 USB_KB_DEV
*UsbKeyboardDevice
;
655 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
657 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
659 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
),
660 UsbKeyboardDevice
->DevicePath
664 // Non-exhaustive reset:
665 // only reset private data structures.
667 if (!ExtendedVerification
) {
668 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
670 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
),
671 UsbKeyboardDevice
->DevicePath
674 // Clear the key buffer of this USB keyboard
676 InitUSBKeyBuffer (&(UsbKeyboardDevice
->KeyboardBuffer
));
677 UsbKeyboardDevice
->CurKeyCode
= 0;
685 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
686 UsbKeyboardDevice
->CurKeyCode
= 0;
687 if (EFI_ERROR (Status
)) {
688 return EFI_DEVICE_ERROR
;
696 Reads the next keystroke from the input device.
698 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
699 @param Key A pointer to a buffer that is filled in with the keystroke
700 information for the key that was pressed.
702 @retval EFI_SUCCESS The keystroke information was returned.
703 @retval EFI_NOT_READY There was no keystroke data availiable.
704 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
710 USBKeyboardReadKeyStroke (
711 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
712 OUT EFI_INPUT_KEY
*Key
715 USB_KB_DEV
*UsbKeyboardDevice
;
717 EFI_KEY_DATA KeyData
;
719 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
721 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
722 if (EFI_ERROR (Status
)) {
726 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
733 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
734 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.
736 @param Event Event to be signaled when a key is pressed.
737 @param Context Points to USB_KB_DEV instance.
742 USBKeyboardWaitForKey (
747 USB_KB_DEV
*UsbKeyboardDevice
;
749 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
751 if (UsbKeyboardDevice
->CurKeyCode
== 0) {
752 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice
))) {
754 // If no pending key, simply return.
760 // If there is pending key, signal the event.
762 gBS
->SignalEvent (Event
);
767 Check whether there is key pending in the keyboard buffer.
769 @param UsbKeyboardDevice The USB_KB_DEV instance.
771 @retval EFI_SUCCESS There is pending key to read.
772 @retval EFI_NOT_READY No pending key to read.
777 USBKeyboardCheckForKey (
778 IN OUT USB_KB_DEV
*UsbKeyboardDevice
785 // Fetch raw data from the USB keyboard buffer,
786 // and translate it into USB keycode.
788 Status
= USBParseKey (UsbKeyboardDevice
, &KeyCode
);
789 if (EFI_ERROR (Status
)) {
790 return EFI_NOT_READY
;
793 UsbKeyboardDevice
->CurKeyCode
= KeyCode
;
798 Free keyboard notify list.
800 @param NotifyList The keyboard notify list to free.
802 @retval EFI_SUCCESS Free the notify list successfully.
803 @retval EFI_INVALID_PARAMETER NotifyList is NULL.
809 IN OUT LIST_ENTRY
*NotifyList
812 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
815 if (NotifyList
== NULL
) {
816 return EFI_INVALID_PARAMETER
;
818 while (!IsListEmpty (NotifyList
)) {
819 Link
= GetFirstNode (NotifyList
);
820 NotifyNode
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
821 RemoveEntryList (Link
);
822 FreePool (NotifyNode
);
829 Check whether the pressed key matches a registered key or not.
831 @param RegsiteredData A pointer to keystroke data for the key that was registered.
832 @param InputData A pointer to keystroke data for the key that was pressed.
834 @retval TRUE Key pressed matches a registered key.
835 @retval FLASE Key pressed does not matches a registered key.
841 IN EFI_KEY_DATA
*RegsiteredData
,
842 IN EFI_KEY_DATA
*InputData
845 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
847 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
848 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
853 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
855 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
856 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
859 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
860 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
868 // Simple Text Input Ex protocol functions
871 Resets the input device hardware.
873 The Reset() function resets the input device hardware. As part
874 of initialization process, the firmware/device will make a quick
875 but reasonable attempt to verify that the device is functioning.
876 If the ExtendedVerification flag is TRUE the firmware may take
877 an extended amount of time to verify the device is operating on
878 reset. Otherwise the reset operation is to occur as quickly as
879 possible. The hardware verification process is not defined by
880 this specification and is left up to the platform firmware or
883 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
885 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
886 verification operation of the device during reset.
888 @retval EFI_SUCCESS The device was reset.
889 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
895 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
896 IN BOOLEAN ExtendedVerification
900 USB_KB_DEV
*UsbKeyboardDevice
;
904 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
906 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
907 if (EFI_ERROR (Status
)) {
908 return EFI_DEVICE_ERROR
;
911 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
912 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
913 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
914 gBS
->RestoreTPL (OldTpl
);
921 Reads the next keystroke from the input device.
923 @param This Protocol instance pointer.
924 @param KeyData A pointer to a buffer that is filled in with the keystroke
925 state data for the key that was pressed.
927 @retval EFI_SUCCESS The keystroke information was returned.
928 @retval EFI_NOT_READY There was no keystroke data available.
929 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
931 @retval EFI_INVALID_PARAMETER KeyData is NULL.
936 USBKeyboardReadKeyStrokeEx (
937 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
938 OUT EFI_KEY_DATA
*KeyData
941 USB_KB_DEV
*UsbKeyboardDevice
;
943 if (KeyData
== NULL
) {
944 return EFI_INVALID_PARAMETER
;
947 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
949 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, KeyData
);
954 Set certain state for the input device.
956 @param This Protocol instance pointer.
957 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
958 state for the input device.
960 @retval EFI_SUCCESS The device state was set appropriately.
961 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
962 not have the setting adjusted.
963 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.
964 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
969 USBKeyboardSetState (
970 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
971 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
974 USB_KB_DEV
*UsbKeyboardDevice
;
976 if (KeyToggleState
== NULL
) {
977 return EFI_INVALID_PARAMETER
;
980 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
982 if (((UsbKeyboardDevice
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
983 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
984 return EFI_UNSUPPORTED
;
988 // Update the status light
991 UsbKeyboardDevice
->ScrollOn
= FALSE
;
992 UsbKeyboardDevice
->NumLockOn
= FALSE
;
993 UsbKeyboardDevice
->CapsOn
= FALSE
;
995 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
996 UsbKeyboardDevice
->ScrollOn
= TRUE
;
998 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
999 UsbKeyboardDevice
->NumLockOn
= TRUE
;
1001 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
1002 UsbKeyboardDevice
->CapsOn
= TRUE
;
1005 SetKeyLED (UsbKeyboardDevice
);
1007 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
1014 Register a notification function for a particular keystroke for the input device.
1016 @param This Protocol instance pointer.
1017 @param KeyData A pointer to a buffer that is filled in with the keystroke
1018 information data for the key that was pressed.
1019 @param KeyNotificationFunction Points to the function to be called when the key
1020 sequence is typed specified by KeyData.
1021 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1023 @retval EFI_SUCCESS The notification function was registered successfully.
1024 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.
1025 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
1030 USBKeyboardRegisterKeyNotify (
1031 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1032 IN EFI_KEY_DATA
*KeyData
,
1033 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
1034 OUT EFI_HANDLE
*NotifyHandle
1037 USB_KB_DEV
*UsbKeyboardDevice
;
1038 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
1040 LIST_ENTRY
*NotifyList
;
1041 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1043 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
1044 return EFI_INVALID_PARAMETER
;
1047 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1050 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1052 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1054 for (Link
= GetFirstNode (NotifyList
);
1055 !IsNull (NotifyList
, Link
);
1056 Link
= GetNextNode (NotifyList
, Link
)) {
1057 CurrentNotify
= CR (
1059 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1061 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1063 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
1064 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
1065 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
1072 // Allocate resource to save the notification function
1074 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
1075 if (NewNotify
== NULL
) {
1076 return EFI_OUT_OF_RESOURCES
;
1079 NewNotify
->Signature
= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
1080 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
1081 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
1082 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
1083 InsertTailList (&UsbKeyboardDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
1086 *NotifyHandle
= NewNotify
->NotifyHandle
;
1093 Remove a registered notification function from a particular keystroke.
1095 @param This Protocol instance pointer.
1096 @param NotificationHandle The handle of the notification function being unregistered.
1098 @retval EFI_SUCCESS The notification function was unregistered successfully.
1099 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid
1104 USBKeyboardUnregisterKeyNotify (
1105 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1106 IN EFI_HANDLE NotificationHandle
1109 USB_KB_DEV
*UsbKeyboardDevice
;
1110 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1112 LIST_ENTRY
*NotifyList
;
1114 if (NotificationHandle
== NULL
) {
1115 return EFI_INVALID_PARAMETER
;
1118 if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
1119 return EFI_INVALID_PARAMETER
;
1122 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1125 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1127 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1128 for (Link
= GetFirstNode (NotifyList
);
1129 !IsNull (NotifyList
, Link
);
1130 Link
= GetNextNode (NotifyList
, Link
)) {
1131 CurrentNotify
= CR (
1133 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1135 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1137 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
1139 // Remove the notification function from NotifyList and free resources
1141 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
1143 FreePool (CurrentNotify
);
1149 // Cannot find the matching entry in database.
1151 return EFI_INVALID_PARAMETER
;