2 USB Keyboard Driver that includes the implementation of interface.
4 Copyright (c) 2004 - 2008, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 // USB Keyboard Driver Global Variables
21 EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding
= {
22 USBKeyboardDriverBindingSupported
,
23 USBKeyboardDriverBindingStart
,
24 USBKeyboardDriverBindingStop
,
31 Entrypoint of USB Keyboard Driver.
33 This function is the entrypoint of USB Keyboard Driver. It installs Driver Binding
34 Protocols together with Component Name Protocols.
36 @param ImageHandle The firmware allocated handle for the EFI image.
37 @param SystemTable A pointer to the EFI System Table.
39 @retval EFI_SUCCESS The entry point is executed successfully.
44 USBKeyboardDriverBindingEntryPoint (
45 IN EFI_HANDLE ImageHandle
,
46 IN EFI_SYSTEM_TABLE
*SystemTable
51 Status
= EfiLibInstallDriverBindingComponentName2 (
54 &gUsbKeyboardDriverBinding
,
56 &gUsbKeyboardComponentName
,
57 &gUsbKeyboardComponentName2
59 ASSERT_EFI_ERROR (Status
);
65 Check whether USB keyboard driver supports this device.
67 @param This The USB keyboard driver binding protocol.
68 @param Controller The controller handle to check.
69 @param RemainingDevicePath The remaining device path.
71 @retval EFI_SUCCESS The driver supports this controller.
72 @retval other This device isn't supported.
77 USBKeyboardDriverBindingSupported (
78 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
79 IN EFI_HANDLE Controller
,
80 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
84 EFI_USB_IO_PROTOCOL
*UsbIo
;
87 // Check if USB I/O Protocol is attached on the controller handle.
89 Status
= gBS
->OpenProtocol (
91 &gEfiUsbIoProtocolGuid
,
93 This
->DriverBindingHandle
,
95 EFI_OPEN_PROTOCOL_BY_DRIVER
97 if (EFI_ERROR (Status
)) {
102 // Use the USB I/O Protocol interface to check whether the Controller is
103 // the Keyboard controller that can be managed by this driver.
105 Status
= EFI_SUCCESS
;
107 if (!IsUSBKeyboard (UsbIo
)) {
108 Status
= EFI_UNSUPPORTED
;
113 &gEfiUsbIoProtocolGuid
,
114 This
->DriverBindingHandle
,
122 Start running driver on the controller.
124 @param This The USB keyboard driver binding instance.
125 @param Controller Handle of device to bind driver to.
126 @param RemainingDevicePath Optional parameter use to pick a specific child
129 @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.
130 @retval EFI_UNSUPPORTED No interrupt endpoint can be found.
131 @retval Other The keyboard driver cannot support this controller.
136 USBKeyboardDriverBindingStart (
137 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
138 IN EFI_HANDLE Controller
,
139 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
143 EFI_USB_IO_PROTOCOL
*UsbIo
;
144 USB_KB_DEV
*UsbKeyboardDevice
;
145 UINT8 EndpointNumber
;
146 EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor
;
149 UINT8 PollingInterval
;
154 // Open USB I/O Protocol
156 Status
= gBS
->OpenProtocol (
158 &gEfiUsbIoProtocolGuid
,
160 This
->DriverBindingHandle
,
162 EFI_OPEN_PROTOCOL_BY_DRIVER
164 if (EFI_ERROR (Status
)) {
168 UsbKeyboardDevice
= AllocateZeroPool (sizeof (USB_KB_DEV
));
169 ASSERT (UsbKeyboardDevice
!= NULL
);
172 // Get the Device Path Protocol on Controller's handle
174 Status
= gBS
->OpenProtocol (
176 &gEfiDevicePathProtocolGuid
,
177 (VOID
**) &UsbKeyboardDevice
->DevicePath
,
178 This
->DriverBindingHandle
,
180 EFI_OPEN_PROTOCOL_GET_PROTOCOL
183 if (EFI_ERROR (Status
)) {
187 // Report that the USB keyboard is being enabled
189 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
191 PcdGet32 (PcdStatusCodeValueKeyboardEnable
),
192 UsbKeyboardDevice
->DevicePath
196 // This is pretty close to keyboard detection, so log progress
198 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
200 PcdGet32 (PcdStatusCodeValueKeyboardPresenceDetect
),
201 UsbKeyboardDevice
->DevicePath
205 // Initialize UsbKeyboardDevice
207 UsbKeyboardDevice
->UsbIo
= UsbIo
;
210 // Get interface & endpoint descriptor
212 UsbIo
->UsbGetInterfaceDescriptor (
214 &UsbKeyboardDevice
->InterfaceDescriptor
217 EndpointNumber
= UsbKeyboardDevice
->InterfaceDescriptor
.NumEndpoints
;
220 // Traverse endpoints to find interrupt endpoints
223 for (Index
= 0; Index
< EndpointNumber
; Index
++) {
225 UsbIo
->UsbGetEndpointDescriptor (
231 if ((EndpointDescriptor
.Attributes
& 0x03) == USB_ENDPOINT_INTERRUPT
) {
233 // We only care interrupt endpoint here
235 CopyMem(&UsbKeyboardDevice
->IntEndpointDescriptor
, &EndpointDescriptor
, sizeof(EndpointDescriptor
));
243 // No interrupt endpoint found, then return unsupported.
245 Status
= EFI_UNSUPPORTED
;
249 UsbKeyboardDevice
->Signature
= USB_KB_DEV_SIGNATURE
;
250 UsbKeyboardDevice
->SimpleInput
.Reset
= USBKeyboardReset
;
251 UsbKeyboardDevice
->SimpleInput
.ReadKeyStroke
= USBKeyboardReadKeyStroke
;
253 UsbKeyboardDevice
->SimpleInputEx
.Reset
= USBKeyboardResetEx
;
254 UsbKeyboardDevice
->SimpleInputEx
.ReadKeyStrokeEx
= USBKeyboardReadKeyStrokeEx
;
255 UsbKeyboardDevice
->SimpleInputEx
.SetState
= USBKeyboardSetState
;
256 UsbKeyboardDevice
->SimpleInputEx
.RegisterKeyNotify
= USBKeyboardRegisterKeyNotify
;
257 UsbKeyboardDevice
->SimpleInputEx
.UnregisterKeyNotify
= USBKeyboardUnregisterKeyNotify
;
259 InitializeListHead (&UsbKeyboardDevice
->NotifyList
);
261 Status
= gBS
->CreateEvent (
264 USBKeyboardWaitForKey
,
266 &(UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
)
269 if (EFI_ERROR (Status
)) {
273 Status
= gBS
->CreateEvent (
276 USBKeyboardWaitForKey
,
278 &(UsbKeyboardDevice
->SimpleInput
.WaitForKey
)
281 if (EFI_ERROR (Status
)) {
285 Status
= InitKeyboardLayout (UsbKeyboardDevice
);
286 if (EFI_ERROR (Status
)) {
291 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol
292 // for the USB keyboard device.
293 // USB keyboard is a hot plug device, and expected to work immediately
294 // when plugging into system, so a HotPlugDeviceGuid is installed onto
295 // the usb keyboard device handle, to distinguish it from other conventional
298 Status
= gBS
->InstallMultipleProtocolInterfaces (
300 &gEfiSimpleTextInProtocolGuid
,
301 &UsbKeyboardDevice
->SimpleInput
,
302 &gEfiSimpleTextInputExProtocolGuid
,
303 &UsbKeyboardDevice
->SimpleInputEx
,
304 &gEfiHotPlugDeviceGuid
,
308 if (EFI_ERROR (Status
)) {
313 // Reset USB Keyboard Device exhaustively.
315 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (
316 &UsbKeyboardDevice
->SimpleInput
,
319 if (EFI_ERROR (Status
)) {
320 gBS
->UninstallMultipleProtocolInterfaces (
322 &gEfiSimpleTextInProtocolGuid
,
323 &UsbKeyboardDevice
->SimpleInput
,
324 &gEfiSimpleTextInputExProtocolGuid
,
325 &UsbKeyboardDevice
->SimpleInputEx
,
326 &gEfiHotPlugDeviceGuid
,
334 // Submit Asynchronous Interrupt Transfer to manage this device.
336 EndpointAddr
= UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
;
337 PollingInterval
= UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
;
338 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
340 Status
= UsbIo
->UsbAsyncInterruptTransfer (
350 if (EFI_ERROR (Status
)) {
351 gBS
->UninstallMultipleProtocolInterfaces (
353 &gEfiSimpleTextInProtocolGuid
,
354 &UsbKeyboardDevice
->SimpleInput
,
355 &gEfiSimpleTextInputExProtocolGuid
,
356 &UsbKeyboardDevice
->SimpleInputEx
,
357 &gEfiHotPlugDeviceGuid
,
364 UsbKeyboardDevice
->ControllerNameTable
= NULL
;
367 gUsbKeyboardComponentName
.SupportedLanguages
,
368 &UsbKeyboardDevice
->ControllerNameTable
,
369 L
"Generic Usb Keyboard",
374 gUsbKeyboardComponentName2
.SupportedLanguages
,
375 &UsbKeyboardDevice
->ControllerNameTable
,
376 L
"Generic Usb Keyboard",
386 if (UsbKeyboardDevice
!= NULL
) {
387 if (UsbKeyboardDevice
->SimpleInput
.WaitForKey
!= NULL
) {
388 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
390 if (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
391 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
393 gBS
->FreePool (UsbKeyboardDevice
);
394 UsbKeyboardDevice
= NULL
;
398 &gEfiUsbIoProtocolGuid
,
399 This
->DriverBindingHandle
,
408 Stop handling the controller by this USB keyboard driver.
410 @param This The USB keyboard driver binding protocol.
411 @param Controller The controller to release.
412 @param NumberOfChildren The number of handles in ChildHandleBuffer.
413 @param ChildHandleBuffer The array of child handle.
415 @retval EFI_SUCCESS The controller or children are stopped.
416 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
417 is not installed on Controller.
418 @retval EFI_DEVICE_ERROR Failed to stop the driver.
423 USBKeyboardDriverBindingStop (
424 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
425 IN EFI_HANDLE Controller
,
426 IN UINTN NumberOfChildren
,
427 IN EFI_HANDLE
*ChildHandleBuffer
431 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
432 USB_KB_DEV
*UsbKeyboardDevice
;
434 Status
= gBS
->OpenProtocol (
436 &gEfiSimpleTextInProtocolGuid
,
437 (VOID
**) &SimpleInput
,
438 This
->DriverBindingHandle
,
440 EFI_OPEN_PROTOCOL_GET_PROTOCOL
442 if (EFI_ERROR (Status
)) {
443 return EFI_UNSUPPORTED
;
446 Status
= gBS
->OpenProtocol (
448 &gEfiSimpleTextInputExProtocolGuid
,
450 This
->DriverBindingHandle
,
452 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
454 if (EFI_ERROR (Status
)) {
455 return EFI_UNSUPPORTED
;
458 // Get USB_KB_DEV instance.
460 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
463 // The key data input from this device will be disabled.
465 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
467 PcdGet32 (PcdStatusCodeValueKeyboardDisable
),
468 UsbKeyboardDevice
->DevicePath
472 // Delete the Asynchronous Interrupt Transfer from this device
474 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
475 UsbKeyboardDevice
->UsbIo
,
476 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
478 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
486 &gEfiUsbIoProtocolGuid
,
487 This
->DriverBindingHandle
,
491 Status
= gBS
->UninstallMultipleProtocolInterfaces (
493 &gEfiSimpleTextInProtocolGuid
,
494 &UsbKeyboardDevice
->SimpleInput
,
495 &gEfiSimpleTextInputExProtocolGuid
,
496 &UsbKeyboardDevice
->SimpleInputEx
,
497 &gEfiHotPlugDeviceGuid
,
502 // Free all resources.
504 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
505 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
506 gBS
->CloseEvent ((UsbKeyboardDevice
->SimpleInput
).WaitForKey
);
507 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
508 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
510 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
511 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
513 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
514 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
517 gBS
->FreePool (UsbKeyboardDevice
);
523 Internal function to read the next keystroke from the input device.
525 @param UsbKeyboardDevice Usb keyboard's private structure.
526 @param KeyData A pointer to a buffer that is filled in with the keystroke
527 state data for the key that was pressed.
529 @return EFI_SUCCESS The keystroke information was returned.
530 @return EFI_NOT_READY There was no keystroke data availiable.
531 @return EFI_DEVICE_ERROR The keystroke information was not returned due to
533 @return EFI_INVALID_PARAMETER KeyData is NULL.
538 USBKeyboardReadKeyStrokeWorker (
539 IN USB_KB_DEV
*UsbKeyboardDevice
,
540 OUT EFI_KEY_DATA
*KeyData
546 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
547 EFI_KEY_DATA OriginalKeyData
;
549 if (KeyData
== NULL
) {
550 return EFI_INVALID_PARAMETER
;
554 // If there is no saved ASCII byte, fetch it
555 // by calling USBKeyboardCheckForKey().
557 if (UsbKeyboardDevice
->CurKeyChar
== 0) {
558 Status
= USBKeyboardCheckForKey (UsbKeyboardDevice
);
559 if (EFI_ERROR (Status
)) {
560 return EFI_NOT_READY
;
564 KeyData
->Key
.UnicodeChar
= 0;
565 KeyData
->Key
.ScanCode
= SCAN_NULL
;
568 // Store the key char read by USBKeyboardCheckForKey() and clear it.
570 KeyChar
= UsbKeyboardDevice
->CurKeyChar
;
571 UsbKeyboardDevice
->CurKeyChar
= 0;
574 // Translate saved ASCII byte into EFI_INPUT_KEY
576 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyChar
, &KeyData
->Key
);
577 if (EFI_ERROR (Status
)) {
582 // Get current state of various toggled attributes as well as input modifier values,
583 // and set them as valid.
585 CopyMem (&KeyData
->KeyState
, &UsbKeyboardDevice
->KeyState
, sizeof (KeyData
->KeyState
));
587 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
588 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
591 // Switch the control value to their original characters.
592 // In UsbKeyCodeToEfiInputKey() the CTRL-Alpha characters have been switched to
593 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A),
594 // here switch them back for notification function.
596 CopyMem (&OriginalKeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
597 if (UsbKeyboardDevice
->CtrlOn
!= 0) {
598 if (OriginalKeyData
.Key
.UnicodeChar
>= 0x01 && OriginalKeyData
.Key
.UnicodeChar
<= 0x1A) {
599 if (UsbKeyboardDevice
->CapsOn
!= 0) {
600 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'A' - 1);
602 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'a' - 1);
608 // Invoke notification functions if the key is registered.
610 for (Link
= GetFirstNode (&UsbKeyboardDevice
->NotifyList
);
611 !IsNull (&UsbKeyboardDevice
->NotifyList
, Link
);
612 Link
= GetNextNode (&UsbKeyboardDevice
->NotifyList
, Link
)) {
613 CurrentNotify
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
614 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &OriginalKeyData
)) {
615 CurrentNotify
->KeyNotificationFn (&OriginalKeyData
);
626 There are 2 types of reset for USB keyboard.
627 For non-exhaustive reset, only keyboard buffer is cleared.
628 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
629 is also re-initialized.
631 @param This The protocol instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
632 @param ExtendedVerification Indicates if exhaustive reset is used.
633 TRUE for exhaustive reset.
634 FALSE for non-exhaustive reset.
636 @retval EFI_SUCCESS Keyboard is reset successfully.
637 @retval EFI_DEVICE_ERROR Failed to reset keyboard.
643 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
644 IN BOOLEAN ExtendedVerification
648 USB_KB_DEV
*UsbKeyboardDevice
;
650 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
652 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
654 PcdGet32 (PcdStatusCodeValueKeyboardReset
),
655 UsbKeyboardDevice
->DevicePath
659 // Non-exhaustive reset:
660 // only reset private data structures.
662 if (!ExtendedVerification
) {
663 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
665 PcdGet32 (PcdStatusCodeValueKeyboardClearBuffer
),
666 UsbKeyboardDevice
->DevicePath
669 // Clear the key buffer of this USB keyboard
671 InitUSBKeyBuffer (&(UsbKeyboardDevice
->KeyboardBuffer
));
672 UsbKeyboardDevice
->CurKeyChar
= 0;
680 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
681 UsbKeyboardDevice
->CurKeyChar
= 0;
682 if (EFI_ERROR (Status
)) {
683 return EFI_DEVICE_ERROR
;
691 Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke() function.
693 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
694 @param Key A pointer to a buffer that is filled in with the keystroke
695 information for the key that was pressed.
697 @retval EFI_SUCCESS Read key stroke successfully.
698 @retval Other Read key stroke failed.
703 USBKeyboardReadKeyStroke (
704 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
705 OUT EFI_INPUT_KEY
*Key
708 USB_KB_DEV
*UsbKeyboardDevice
;
710 EFI_KEY_DATA KeyData
;
712 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
714 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
715 if (EFI_ERROR (Status
)) {
719 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
727 Handler function for WaitForKey event.
729 @param Event Event to be signaled when a key is pressed.
730 @param Context Points to USB_KB_DEV instance.
735 USBKeyboardWaitForKey (
740 USB_KB_DEV
*UsbKeyboardDevice
;
742 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
744 if (UsbKeyboardDevice
->CurKeyChar
== 0) {
745 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice
))) {
747 // If no pending key, simply return.
753 // If there is pending key, signal the event.
755 gBS
->SignalEvent (Event
);
760 Check whether there is key pending.
762 @param UsbKeyboardDevice The USB_KB_DEV instance.
764 @retval EFI_SUCCESS There is pending key to read.
765 @retval EFI_NOT_READY No pending key to read.
770 USBKeyboardCheckForKey (
771 IN USB_KB_DEV
*UsbKeyboardDevice
778 // Fetch raw data from the USB keyboard input,
779 // and translate it into ASCII data.
781 Status
= USBParseKey (UsbKeyboardDevice
, &KeyChar
);
782 if (EFI_ERROR (Status
)) {
783 return EFI_NOT_READY
;
786 UsbKeyboardDevice
->CurKeyChar
= KeyChar
;
791 Free keyboard notify list.
793 @param ListHead The list head.
795 @retval EFI_SUCCESS Free the notify list successfully.
796 @retval EFI_INVALID_PARAMETER ListHead is invalid.
802 IN OUT LIST_ENTRY
*ListHead
805 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
807 if (ListHead
== NULL
) {
808 return EFI_INVALID_PARAMETER
;
810 while (!IsListEmpty (ListHead
)) {
812 ListHead
->ForwardLink
,
813 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
815 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
817 RemoveEntryList (ListHead
->ForwardLink
);
818 gBS
->FreePool (NotifyNode
);
825 Whether the pressed key matches a registered key or not.
827 @param RegsiteredData A pointer to a buffer that is filled in with the keystroke
828 state data for the key that was registered.
829 @param InputData A pointer to a buffer that is filled in with the keystroke
830 state data for the key that was pressed.
832 @retval TRUE Key pressed matches a registered key.
833 @retval FLASE Match failed.
839 IN EFI_KEY_DATA
*RegsiteredData
,
840 IN EFI_KEY_DATA
*InputData
843 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
845 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
846 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
851 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
853 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
854 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
857 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
858 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
867 // Simple Text Input Ex protocol functions
870 The extension routine to reset the input device.
872 @param This Protocol instance pointer.
873 @param ExtendedVerification Driver may perform diagnostics on reset.
875 @retval EFI_SUCCESS The device was reset.
876 @retval EFI_DEVICE_ERROR The device is not functioning properly and could
883 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
884 IN BOOLEAN ExtendedVerification
888 USB_KB_DEV
*UsbKeyboardDevice
;
892 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
894 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
895 if (EFI_ERROR (Status
)) {
896 return EFI_DEVICE_ERROR
;
899 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
900 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
901 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
902 gBS
->RestoreTPL (OldTpl
);
909 Reads the next keystroke from the input device. The WaitForKey Event can
910 be used to test for existance of a keystroke via WaitForEvent () call.
912 @param This Protocol instance pointer.
913 @param KeyData A pointer to a buffer that is filled in with the keystroke
914 state data for the key that was pressed.
916 @return EFI_SUCCESS The keystroke information was returned successfully.
917 @retval EFI_INVALID_PARAMETER KeyData is NULL.
918 @retval Other Read key stroke information failed.
923 USBKeyboardReadKeyStrokeEx (
924 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
925 OUT EFI_KEY_DATA
*KeyData
928 USB_KB_DEV
*UsbKeyboardDevice
;
930 if (KeyData
== NULL
) {
931 return EFI_INVALID_PARAMETER
;
934 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
936 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, KeyData
);
941 Set certain state for the input device.
943 @param This Protocol instance pointer.
944 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
945 state for the input device.
947 @retval EFI_SUCCESS The device state was set successfully.
948 @retval EFI_UNSUPPORTED The device does not have the ability to set its state.
949 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
954 USBKeyboardSetState (
955 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
956 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
959 USB_KB_DEV
*UsbKeyboardDevice
;
961 if (KeyToggleState
== NULL
) {
962 return EFI_INVALID_PARAMETER
;
965 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
967 if (((UsbKeyboardDevice
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
968 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
969 return EFI_UNSUPPORTED
;
973 // Update the status light
976 UsbKeyboardDevice
->ScrollOn
= 0;
977 UsbKeyboardDevice
->NumLockOn
= 0;
978 UsbKeyboardDevice
->CapsOn
= 0;
980 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
981 UsbKeyboardDevice
->ScrollOn
= 1;
983 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
984 UsbKeyboardDevice
->NumLockOn
= 1;
986 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
987 UsbKeyboardDevice
->CapsOn
= 1;
990 SetKeyLED (UsbKeyboardDevice
);
992 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
999 Register a notification function for a particular keystroke for the input device.
1001 @param This Protocol instance pointer.
1002 @param KeyData A pointer to a buffer that is filled in with the keystroke
1003 information data for the key that was pressed.
1004 @param KeyNotificationFunction Points to the function to be called when the key
1005 sequence is typed specified by KeyData.
1006 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1008 @retval EFI_SUCCESS The notification function was registered successfully.
1009 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.
1010 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.
1015 USBKeyboardRegisterKeyNotify (
1016 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1017 IN EFI_KEY_DATA
*KeyData
,
1018 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
1019 OUT EFI_HANDLE
*NotifyHandle
1022 USB_KB_DEV
*UsbKeyboardDevice
;
1024 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
1026 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1028 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
1029 return EFI_INVALID_PARAMETER
;
1032 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1035 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1037 for (Link
= GetFirstNode (&UsbKeyboardDevice
->NotifyList
);
1038 !IsNull (&UsbKeyboardDevice
->NotifyList
, Link
);
1039 Link
= GetNextNode (&UsbKeyboardDevice
->NotifyList
, Link
)) {
1040 CurrentNotify
= CR (
1042 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1044 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1046 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
1047 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
1048 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
1055 // Allocate resource to save the notification function
1057 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
1058 if (NewNotify
== NULL
) {
1059 return EFI_OUT_OF_RESOURCES
;
1062 NewNotify
->Signature
= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
1063 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
1064 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
1065 InsertTailList (&UsbKeyboardDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
1068 // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE
1070 Status
= gBS
->InstallMultipleProtocolInterfaces (
1071 &NewNotify
->NotifyHandle
,
1072 &gSimpleTextInExNotifyGuid
,
1076 ASSERT_EFI_ERROR (Status
);
1078 *NotifyHandle
= NewNotify
->NotifyHandle
;
1085 Remove a registered notification function from a particular keystroke.
1087 @param This Protocol instance pointer.
1088 @param NotificationHandle The handle of the notification function being unregistered.
1090 @retval EFI_SUCCESS The notification function was unregistered successfully.
1091 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid or opening gSimpleTextInExNotifyGuid
1092 on NotificationHandle fails.
1093 @retval EFI_NOT_FOUND Can not find the matching entry in database.
1098 USBKeyboardUnregisterKeyNotify (
1099 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1100 IN EFI_HANDLE NotificationHandle
1103 USB_KB_DEV
*UsbKeyboardDevice
;
1105 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1108 if (NotificationHandle
== NULL
) {
1109 return EFI_INVALID_PARAMETER
;
1112 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1115 // Check if NotificationHandle is returned from RegisterKeyNotify().
1117 Status
= gBS
->OpenProtocol (
1119 &gSimpleTextInExNotifyGuid
,
1123 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1125 if (EFI_ERROR (Status
)) {
1126 return EFI_INVALID_PARAMETER
;
1130 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1132 for (Link
= GetFirstNode (&UsbKeyboardDevice
->NotifyList
);
1133 !IsNull (&UsbKeyboardDevice
->NotifyList
, Link
);
1134 Link
= GetNextNode (&UsbKeyboardDevice
->NotifyList
, Link
)) {
1135 CurrentNotify
= CR (
1137 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1139 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1141 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
1143 // Remove the notification function from NotifyList and free resources
1145 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
1146 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1147 CurrentNotify
->NotifyHandle
,
1148 &gSimpleTextInExNotifyGuid
,
1152 ASSERT_EFI_ERROR (Status
);
1153 gBS
->FreePool (CurrentNotify
);
1158 return EFI_NOT_FOUND
;