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. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 // USB Keyboard Driver Global Variables
22 EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding
= {
23 USBKeyboardDriverBindingSupported
,
24 USBKeyboardDriverBindingStart
,
25 USBKeyboardDriverBindingStop
,
32 Entrypoint of USB Keyboard Driver.
34 This function is the entrypoint of USB Keyboard Driver. It installs Driver Binding
35 Protocols together with Component Name Protocols.
37 @param ImageHandle The firmware allocated handle for the EFI image.
38 @param SystemTable A pointer to the EFI System Table.
40 @retval EFI_SUCCESS The entry point is executed successfully.
45 USBKeyboardDriverBindingEntryPoint (
46 IN EFI_HANDLE ImageHandle
,
47 IN EFI_SYSTEM_TABLE
*SystemTable
52 Status
= EfiLibInstallDriverBindingComponentName2 (
55 &gUsbKeyboardDriverBinding
,
57 &gUsbKeyboardComponentName
,
58 &gUsbKeyboardComponentName2
60 ASSERT_EFI_ERROR (Status
);
66 Check whether USB keyboard driver supports this device.
68 @param This The USB keyboard driver binding protocol.
69 @param Controller The controller handle to check.
70 @param RemainingDevicePath The remaining device path.
72 @retval EFI_SUCCESS The driver supports this controller.
73 @retval other This device isn't supported.
78 USBKeyboardDriverBindingSupported (
79 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
80 IN EFI_HANDLE Controller
,
81 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
85 EFI_USB_IO_PROTOCOL
*UsbIo
;
88 // Check if USB I/O Protocol is attached on the controller handle.
90 Status
= gBS
->OpenProtocol (
92 &gEfiUsbIoProtocolGuid
,
94 This
->DriverBindingHandle
,
96 EFI_OPEN_PROTOCOL_BY_DRIVER
98 if (EFI_ERROR (Status
)) {
103 // Use the USB I/O Protocol interface to check whether Controller is
104 // a keyboard device that can be managed by this driver.
106 Status
= EFI_SUCCESS
;
108 if (!IsUSBKeyboard (UsbIo
)) {
109 Status
= EFI_UNSUPPORTED
;
114 &gEfiUsbIoProtocolGuid
,
115 This
->DriverBindingHandle
,
123 Starts the keyboard device with this driver.
125 This function produces Simple Text Input Protocol and Simple Text Input Ex Protocol,
126 initializes the keyboard device, and submit Asynchronous Interrupt Transfer to manage
127 this keyboard device.
129 @param This The USB keyboard driver binding instance.
130 @param Controller Handle of device to bind driver to.
131 @param RemainingDevicePath Optional parameter use to pick a specific child
134 @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.
135 @retval EFI_UNSUPPORTED No interrupt endpoint can be found.
136 @retval Other This controller cannot be started.
141 USBKeyboardDriverBindingStart (
142 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
143 IN EFI_HANDLE Controller
,
144 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
148 EFI_USB_IO_PROTOCOL
*UsbIo
;
149 USB_KB_DEV
*UsbKeyboardDevice
;
150 UINT8 EndpointNumber
;
151 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
154 UINT8 PollingInterval
;
159 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
161 // Open USB I/O Protocol
163 Status
= gBS
->OpenProtocol (
165 &gEfiUsbIoProtocolGuid
,
167 This
->DriverBindingHandle
,
169 EFI_OPEN_PROTOCOL_BY_DRIVER
171 if (EFI_ERROR (Status
)) {
175 UsbKeyboardDevice
= AllocateZeroPool (sizeof (USB_KB_DEV
));
176 ASSERT (UsbKeyboardDevice
!= NULL
);
179 // Get the Device Path Protocol on Controller's handle
181 Status
= gBS
->OpenProtocol (
183 &gEfiDevicePathProtocolGuid
,
184 (VOID
**) &UsbKeyboardDevice
->DevicePath
,
185 This
->DriverBindingHandle
,
187 EFI_OPEN_PROTOCOL_GET_PROTOCOL
190 if (EFI_ERROR (Status
)) {
194 // Report that the USB keyboard is being enabled
196 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
198 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_ENABLE
),
199 UsbKeyboardDevice
->DevicePath
203 // This is pretty close to keyboard detection, so log progress
205 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
207 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_PRESENCE_DETECT
),
208 UsbKeyboardDevice
->DevicePath
211 UsbKeyboardDevice
->UsbIo
= UsbIo
;
214 // Get interface & endpoint descriptor
216 UsbIo
->UsbGetInterfaceDescriptor (
218 &UsbKeyboardDevice
->InterfaceDescriptor
221 EndpointNumber
= UsbKeyboardDevice
->InterfaceDescriptor
.NumEndpoints
;
224 // Traverse endpoints to find interrupt endpoint
227 for (Index
= 0; Index
< EndpointNumber
; Index
++) {
229 UsbIo
->UsbGetEndpointDescriptor (
235 if ((EndpointDescriptor
.Attributes
& (BIT0
| BIT1
)) == USB_ENDPOINT_INTERRUPT
) {
237 // We only care interrupt endpoint here
239 CopyMem(&UsbKeyboardDevice
->IntEndpointDescriptor
, &EndpointDescriptor
, sizeof(EndpointDescriptor
));
247 // No interrupt endpoint found, then return unsupported.
249 Status
= EFI_UNSUPPORTED
;
253 UsbKeyboardDevice
->Signature
= USB_KB_DEV_SIGNATURE
;
254 UsbKeyboardDevice
->SimpleInput
.Reset
= USBKeyboardReset
;
255 UsbKeyboardDevice
->SimpleInput
.ReadKeyStroke
= USBKeyboardReadKeyStroke
;
257 UsbKeyboardDevice
->SimpleInputEx
.Reset
= USBKeyboardResetEx
;
258 UsbKeyboardDevice
->SimpleInputEx
.ReadKeyStrokeEx
= USBKeyboardReadKeyStrokeEx
;
259 UsbKeyboardDevice
->SimpleInputEx
.SetState
= USBKeyboardSetState
;
260 UsbKeyboardDevice
->SimpleInputEx
.RegisterKeyNotify
= USBKeyboardRegisterKeyNotify
;
261 UsbKeyboardDevice
->SimpleInputEx
.UnregisterKeyNotify
= USBKeyboardUnregisterKeyNotify
;
263 InitializeListHead (&UsbKeyboardDevice
->NotifyList
);
265 Status
= gBS
->CreateEvent (
268 USBKeyboardWaitForKey
,
270 &(UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
)
273 if (EFI_ERROR (Status
)) {
277 Status
= gBS
->CreateEvent (
280 USBKeyboardWaitForKey
,
282 &(UsbKeyboardDevice
->SimpleInput
.WaitForKey
)
284 if (EFI_ERROR (Status
)) {
289 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol
290 // for the USB keyboard device.
291 // USB keyboard is a hot plug device, and expected to work immediately
292 // when plugging into system, other conventional console devices could
293 // distinguish it by its device path.
295 Status
= gBS
->InstallMultipleProtocolInterfaces (
297 &gEfiSimpleTextInProtocolGuid
,
298 &UsbKeyboardDevice
->SimpleInput
,
299 &gEfiSimpleTextInputExProtocolGuid
,
300 &UsbKeyboardDevice
->SimpleInputEx
,
303 if (EFI_ERROR (Status
)) {
307 UsbKeyboardDevice
->ControllerHandle
= Controller
;
308 Status
= InitKeyboardLayout (UsbKeyboardDevice
);
309 if (EFI_ERROR (Status
)) {
310 gBS
->UninstallMultipleProtocolInterfaces (
312 &gEfiSimpleTextInProtocolGuid
,
313 &UsbKeyboardDevice
->SimpleInput
,
314 &gEfiSimpleTextInputExProtocolGuid
,
315 &UsbKeyboardDevice
->SimpleInputEx
,
323 // Reset USB Keyboard Device exhaustively.
325 Status
= UsbKeyboardDevice
->SimpleInputEx
.Reset (
326 &UsbKeyboardDevice
->SimpleInputEx
,
329 if (EFI_ERROR (Status
)) {
330 gBS
->UninstallMultipleProtocolInterfaces (
332 &gEfiSimpleTextInProtocolGuid
,
333 &UsbKeyboardDevice
->SimpleInput
,
334 &gEfiSimpleTextInputExProtocolGuid
,
335 &UsbKeyboardDevice
->SimpleInputEx
,
342 // Submit Asynchronous Interrupt Transfer to manage this device.
344 EndpointAddr
= UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
;
345 PollingInterval
= UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
;
346 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
348 Status
= UsbIo
->UsbAsyncInterruptTransfer (
358 if (EFI_ERROR (Status
)) {
359 gBS
->UninstallMultipleProtocolInterfaces (
361 &gEfiSimpleTextInProtocolGuid
,
362 &UsbKeyboardDevice
->SimpleInput
,
363 &gEfiSimpleTextInputExProtocolGuid
,
364 &UsbKeyboardDevice
->SimpleInputEx
,
370 UsbKeyboardDevice
->ControllerNameTable
= NULL
;
373 gUsbKeyboardComponentName
.SupportedLanguages
,
374 &UsbKeyboardDevice
->ControllerNameTable
,
375 L
"Generic Usb Keyboard",
380 gUsbKeyboardComponentName2
.SupportedLanguages
,
381 &UsbKeyboardDevice
->ControllerNameTable
,
382 L
"Generic Usb Keyboard",
386 gBS
->RestoreTPL (OldTpl
);
393 if (UsbKeyboardDevice
!= NULL
) {
394 if (UsbKeyboardDevice
->SimpleInput
.WaitForKey
!= NULL
) {
395 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
397 if (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
398 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
400 if (UsbKeyboardDevice
->KeyboardLayoutEvent
!= NULL
) {
401 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
402 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
404 FreePool (UsbKeyboardDevice
);
405 UsbKeyboardDevice
= NULL
;
409 &gEfiUsbIoProtocolGuid
,
410 This
->DriverBindingHandle
,
415 gBS
->RestoreTPL (OldTpl
);
423 Stop the USB keyboard device handled by this driver.
425 @param This The USB keyboard driver binding protocol.
426 @param Controller The controller to release.
427 @param NumberOfChildren The number of handles in ChildHandleBuffer.
428 @param ChildHandleBuffer The array of child handle.
430 @retval EFI_SUCCESS The device was stopped.
431 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
432 is not installed on Controller.
433 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
434 @retval Others Fail to uninstall protocols attached on the device.
439 USBKeyboardDriverBindingStop (
440 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
441 IN EFI_HANDLE Controller
,
442 IN UINTN NumberOfChildren
,
443 IN EFI_HANDLE
*ChildHandleBuffer
447 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
448 USB_KB_DEV
*UsbKeyboardDevice
;
450 Status
= gBS
->OpenProtocol (
452 &gEfiSimpleTextInProtocolGuid
,
453 (VOID
**) &SimpleInput
,
454 This
->DriverBindingHandle
,
456 EFI_OPEN_PROTOCOL_GET_PROTOCOL
458 if (EFI_ERROR (Status
)) {
459 return EFI_UNSUPPORTED
;
462 Status
= gBS
->OpenProtocol (
464 &gEfiSimpleTextInputExProtocolGuid
,
466 This
->DriverBindingHandle
,
468 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
470 if (EFI_ERROR (Status
)) {
471 return EFI_UNSUPPORTED
;
474 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
477 // The key data input from this device will be disabled.
479 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
481 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DISABLE
),
482 UsbKeyboardDevice
->DevicePath
486 // Delete the Asynchronous Interrupt Transfer from this device
488 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
489 UsbKeyboardDevice
->UsbIo
,
490 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
492 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
500 &gEfiUsbIoProtocolGuid
,
501 This
->DriverBindingHandle
,
505 Status
= gBS
->UninstallMultipleProtocolInterfaces (
507 &gEfiSimpleTextInProtocolGuid
,
508 &UsbKeyboardDevice
->SimpleInput
,
509 &gEfiSimpleTextInputExProtocolGuid
,
510 &UsbKeyboardDevice
->SimpleInputEx
,
514 // Free all resources.
516 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
517 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
518 gBS
->CloseEvent ((UsbKeyboardDevice
->SimpleInput
).WaitForKey
);
519 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
520 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
522 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
523 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
525 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
526 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
529 FreePool (UsbKeyboardDevice
);
535 Internal function to read the next keystroke from the keyboard buffer.
537 @param UsbKeyboardDevice USB keyboard's private structure.
538 @param KeyData A pointer to buffer to hold the keystroke
539 data for the key that was pressed.
541 @retval EFI_SUCCESS The keystroke information was returned.
542 @retval EFI_NOT_READY There was no keystroke data availiable.
543 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
545 @retval EFI_INVALID_PARAMETER KeyData is NULL.
546 @retval Others Fail to translate keycode into EFI_INPUT_KEY
551 USBKeyboardReadKeyStrokeWorker (
552 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
553 OUT EFI_KEY_DATA
*KeyData
559 LIST_ENTRY
*NotifyList
;
560 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
561 EFI_KEY_DATA OriginalKeyData
;
563 if (KeyData
== NULL
) {
564 return EFI_INVALID_PARAMETER
;
568 // If there is no saved USB keycode, fetch it
569 // by calling USBKeyboardCheckForKey().
571 if (UsbKeyboardDevice
->CurKeyCode
== 0) {
572 Status
= USBKeyboardCheckForKey (UsbKeyboardDevice
);
573 if (EFI_ERROR (Status
)) {
574 return EFI_NOT_READY
;
578 KeyData
->Key
.UnicodeChar
= 0;
579 KeyData
->Key
.ScanCode
= SCAN_NULL
;
582 // Store the current keycode and clear it.
584 KeyCode
= UsbKeyboardDevice
->CurKeyCode
;
585 UsbKeyboardDevice
->CurKeyCode
= 0;
588 // Translate saved USB keycode into EFI_INPUT_KEY
590 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyCode
, &KeyData
->Key
);
591 if (EFI_ERROR (Status
)) {
596 // Get current state of various toggled attributes as well as input modifier values,
597 // and set them as valid.
599 CopyMem (&KeyData
->KeyState
, &UsbKeyboardDevice
->KeyState
, sizeof (KeyData
->KeyState
));
601 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
602 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
605 // Switch the control value to their original characters.
606 // In UsbKeyCodeToEfiInputKey() the CTRL-Alpha characters have been switched to
607 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A),
608 // here switch them back for notification function.
610 CopyMem (&OriginalKeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
611 if (UsbKeyboardDevice
->CtrlOn
) {
612 if (OriginalKeyData
.Key
.UnicodeChar
>= 0x01 && OriginalKeyData
.Key
.UnicodeChar
<= 0x1A) {
613 if (UsbKeyboardDevice
->CapsOn
) {
614 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'A' - 1);
616 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'a' - 1);
622 // Invoke notification functions if the key is registered.
624 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
625 for (Link
= GetFirstNode (NotifyList
);
626 !IsNull (NotifyList
, Link
);
627 Link
= GetNextNode (NotifyList
, Link
)) {
628 CurrentNotify
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
629 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &OriginalKeyData
)) {
630 CurrentNotify
->KeyNotificationFn (&OriginalKeyData
);
638 Reset the input device and optionally run diagnostics
640 There are 2 types of reset for USB keyboard.
641 For non-exhaustive reset, only keyboard buffer is cleared.
642 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
643 is also re-initialized.
645 @param This Protocol instance pointer.
646 @param ExtendedVerification Driver may perform diagnostics on reset.
648 @retval EFI_SUCCESS The device was reset.
649 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
655 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
656 IN BOOLEAN ExtendedVerification
660 USB_KB_DEV
*UsbKeyboardDevice
;
662 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
664 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
666 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
),
667 UsbKeyboardDevice
->DevicePath
671 // Non-exhaustive reset:
672 // only reset private data structures.
674 if (!ExtendedVerification
) {
675 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
677 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
),
678 UsbKeyboardDevice
->DevicePath
681 // Clear the key buffer of this USB keyboard
683 InitUSBKeyBuffer (&(UsbKeyboardDevice
->KeyboardBuffer
));
684 UsbKeyboardDevice
->CurKeyCode
= 0;
692 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
693 UsbKeyboardDevice
->CurKeyCode
= 0;
694 if (EFI_ERROR (Status
)) {
695 return EFI_DEVICE_ERROR
;
703 Reads the next keystroke from the input device.
705 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
706 @param Key A pointer to a buffer that is filled in with the keystroke
707 information for the key that was pressed.
709 @retval EFI_SUCCESS The keystroke information was returned.
710 @retval EFI_NOT_READY There was no keystroke data availiable.
711 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
717 USBKeyboardReadKeyStroke (
718 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
719 OUT EFI_INPUT_KEY
*Key
722 USB_KB_DEV
*UsbKeyboardDevice
;
724 EFI_KEY_DATA KeyData
;
726 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
728 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
729 if (EFI_ERROR (Status
)) {
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
;
756 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
758 if (UsbKeyboardDevice
->CurKeyCode
== 0) {
759 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice
))) {
761 // If no pending key, simply return.
767 // If there is pending key, signal the event.
769 gBS
->SignalEvent (Event
);
774 Check whether there is key pending in the keyboard buffer.
776 @param UsbKeyboardDevice The USB_KB_DEV instance.
778 @retval EFI_SUCCESS There is pending key to read.
779 @retval EFI_NOT_READY No pending key to read.
784 USBKeyboardCheckForKey (
785 IN OUT USB_KB_DEV
*UsbKeyboardDevice
792 // Fetch raw data from the USB keyboard buffer,
793 // and translate it into USB keycode.
795 Status
= USBParseKey (UsbKeyboardDevice
, &KeyCode
);
796 if (EFI_ERROR (Status
)) {
797 return EFI_NOT_READY
;
800 UsbKeyboardDevice
->CurKeyCode
= KeyCode
;
805 Free keyboard notify list.
807 @param NotifyList The keyboard notify list to free.
809 @retval EFI_SUCCESS Free the notify list successfully.
810 @retval EFI_INVALID_PARAMETER NotifyList is NULL.
816 IN OUT LIST_ENTRY
*NotifyList
819 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
822 if (NotifyList
== NULL
) {
823 return EFI_INVALID_PARAMETER
;
825 while (!IsListEmpty (NotifyList
)) {
826 Link
= GetFirstNode (NotifyList
);
827 NotifyNode
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
828 RemoveEntryList (Link
);
829 FreePool (NotifyNode
);
836 Check whether the pressed key matches a registered key or not.
838 @param RegsiteredData A pointer to keystroke data for the key that was registered.
839 @param InputData A pointer to keystroke data for the key that was pressed.
841 @retval TRUE Key pressed matches a registered key.
842 @retval FLASE Key pressed does not matches a registered key.
848 IN EFI_KEY_DATA
*RegsiteredData
,
849 IN EFI_KEY_DATA
*InputData
852 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
854 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
855 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
860 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
862 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
863 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
866 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
867 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
875 // Simple Text Input Ex protocol functions
878 Resets the input device hardware.
880 The Reset() function resets the input device hardware. As part
881 of initialization process, the firmware/device will make a quick
882 but reasonable attempt to verify that the device is functioning.
883 If the ExtendedVerification flag is TRUE the firmware may take
884 an extended amount of time to verify the device is operating on
885 reset. Otherwise the reset operation is to occur as quickly as
886 possible. The hardware verification process is not defined by
887 this specification and is left up to the platform firmware or
890 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
892 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
893 verification operation of the device during reset.
895 @retval EFI_SUCCESS The device was reset.
896 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
902 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
903 IN BOOLEAN ExtendedVerification
907 USB_KB_DEV
*UsbKeyboardDevice
;
911 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
913 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
914 if (EFI_ERROR (Status
)) {
915 return EFI_DEVICE_ERROR
;
918 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
919 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
920 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
921 gBS
->RestoreTPL (OldTpl
);
928 Reads the next keystroke from the input device.
930 @param This Protocol instance pointer.
931 @param KeyData A pointer to a buffer that is filled in with the keystroke
932 state data for the key that was pressed.
934 @retval EFI_SUCCESS The keystroke information was returned.
935 @retval EFI_NOT_READY There was no keystroke data available.
936 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
938 @retval EFI_INVALID_PARAMETER KeyData is NULL.
943 USBKeyboardReadKeyStrokeEx (
944 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
945 OUT EFI_KEY_DATA
*KeyData
948 USB_KB_DEV
*UsbKeyboardDevice
;
950 if (KeyData
== NULL
) {
951 return EFI_INVALID_PARAMETER
;
954 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
956 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, KeyData
);
961 Set certain state for the input device.
963 @param This Protocol instance pointer.
964 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
965 state for the input device.
967 @retval EFI_SUCCESS The device state was set appropriately.
968 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
969 not have the setting adjusted.
970 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.
971 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
976 USBKeyboardSetState (
977 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
978 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
981 USB_KB_DEV
*UsbKeyboardDevice
;
983 if (KeyToggleState
== NULL
) {
984 return EFI_INVALID_PARAMETER
;
987 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
989 if (((UsbKeyboardDevice
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
990 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
991 return EFI_UNSUPPORTED
;
995 // Update the status light
998 UsbKeyboardDevice
->ScrollOn
= FALSE
;
999 UsbKeyboardDevice
->NumLockOn
= FALSE
;
1000 UsbKeyboardDevice
->CapsOn
= FALSE
;
1002 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
1003 UsbKeyboardDevice
->ScrollOn
= TRUE
;
1005 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
1006 UsbKeyboardDevice
->NumLockOn
= TRUE
;
1008 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
1009 UsbKeyboardDevice
->CapsOn
= TRUE
;
1012 SetKeyLED (UsbKeyboardDevice
);
1014 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
1021 Register a notification function for a particular keystroke for the input device.
1023 @param This Protocol instance pointer.
1024 @param KeyData A pointer to a buffer that is filled in with the keystroke
1025 information data for the key that was pressed.
1026 @param KeyNotificationFunction Points to the function to be called when the key
1027 sequence is typed specified by KeyData.
1028 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1030 @retval EFI_SUCCESS The notification function was registered successfully.
1031 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.
1032 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
1037 USBKeyboardRegisterKeyNotify (
1038 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1039 IN EFI_KEY_DATA
*KeyData
,
1040 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
1041 OUT EFI_HANDLE
*NotifyHandle
1044 USB_KB_DEV
*UsbKeyboardDevice
;
1045 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
1047 LIST_ENTRY
*NotifyList
;
1048 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1050 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
1051 return EFI_INVALID_PARAMETER
;
1054 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1057 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1059 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1061 for (Link
= GetFirstNode (NotifyList
);
1062 !IsNull (NotifyList
, Link
);
1063 Link
= GetNextNode (NotifyList
, Link
)) {
1064 CurrentNotify
= CR (
1066 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1068 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1070 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
1071 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
1072 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
1079 // Allocate resource to save the notification function
1081 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
1082 if (NewNotify
== NULL
) {
1083 return EFI_OUT_OF_RESOURCES
;
1086 NewNotify
->Signature
= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
1087 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
1088 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
1089 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
1090 InsertTailList (&UsbKeyboardDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
1093 *NotifyHandle
= NewNotify
->NotifyHandle
;
1100 Remove a registered notification function from a particular keystroke.
1102 @param This Protocol instance pointer.
1103 @param NotificationHandle The handle of the notification function being unregistered.
1105 @retval EFI_SUCCESS The notification function was unregistered successfully.
1106 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid
1111 USBKeyboardUnregisterKeyNotify (
1112 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1113 IN EFI_HANDLE NotificationHandle
1116 USB_KB_DEV
*UsbKeyboardDevice
;
1117 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1119 LIST_ENTRY
*NotifyList
;
1121 if (NotificationHandle
== NULL
) {
1122 return EFI_INVALID_PARAMETER
;
1125 if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
1126 return EFI_INVALID_PARAMETER
;
1129 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1132 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1134 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1135 for (Link
= GetFirstNode (NotifyList
);
1136 !IsNull (NotifyList
, Link
);
1137 Link
= GetNextNode (NotifyList
, Link
)) {
1138 CurrentNotify
= CR (
1140 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1142 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1144 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
1146 // Remove the notification function from NotifyList and free resources
1148 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
1150 FreePool (CurrentNotify
);
1156 // Cannot find the matching entry in database.
1158 return EFI_INVALID_PARAMETER
;