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 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
400 if (UsbKeyboardDevice
->KeyConvertionTable
!= NULL
) {
401 FreePool (UsbKeyboardDevice
->KeyConvertionTable
);
403 FreePool (UsbKeyboardDevice
);
404 UsbKeyboardDevice
= NULL
;
408 &gEfiUsbIoProtocolGuid
,
409 This
->DriverBindingHandle
,
418 Stop the USB keyboard device handled by this driver.
420 @param This The USB keyboard driver binding protocol.
421 @param Controller The controller to release.
422 @param NumberOfChildren The number of handles in ChildHandleBuffer.
423 @param ChildHandleBuffer The array of child handle.
425 @retval EFI_SUCCESS The device was stopped.
426 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
427 is not installed on Controller.
428 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
429 @retval Others Fail to uninstall protocols attached on the device.
434 USBKeyboardDriverBindingStop (
435 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
436 IN EFI_HANDLE Controller
,
437 IN UINTN NumberOfChildren
,
438 IN EFI_HANDLE
*ChildHandleBuffer
442 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
443 USB_KB_DEV
*UsbKeyboardDevice
;
445 Status
= gBS
->OpenProtocol (
447 &gEfiSimpleTextInProtocolGuid
,
448 (VOID
**) &SimpleInput
,
449 This
->DriverBindingHandle
,
451 EFI_OPEN_PROTOCOL_GET_PROTOCOL
453 if (EFI_ERROR (Status
)) {
454 return EFI_UNSUPPORTED
;
457 Status
= gBS
->OpenProtocol (
459 &gEfiSimpleTextInputExProtocolGuid
,
461 This
->DriverBindingHandle
,
463 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
465 if (EFI_ERROR (Status
)) {
466 return EFI_UNSUPPORTED
;
469 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
472 // The key data input from this device will be disabled.
474 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
476 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DISABLE
),
477 UsbKeyboardDevice
->DevicePath
481 // Delete the Asynchronous Interrupt Transfer from this device
483 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
484 UsbKeyboardDevice
->UsbIo
,
485 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
487 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
495 &gEfiUsbIoProtocolGuid
,
496 This
->DriverBindingHandle
,
500 Status
= gBS
->UninstallMultipleProtocolInterfaces (
502 &gEfiSimpleTextInProtocolGuid
,
503 &UsbKeyboardDevice
->SimpleInput
,
504 &gEfiSimpleTextInputExProtocolGuid
,
505 &UsbKeyboardDevice
->SimpleInputEx
,
509 // Free all resources.
511 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
512 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
513 gBS
->CloseEvent ((UsbKeyboardDevice
->SimpleInput
).WaitForKey
);
514 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
515 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
517 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
518 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
520 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
521 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
524 FreePool (UsbKeyboardDevice
);
530 Internal function to read the next keystroke from the keyboard buffer.
532 @param UsbKeyboardDevice USB keyboard's private structure.
533 @param KeyData A pointer to buffer to hold the keystroke
534 data for the key that was pressed.
536 @retval EFI_SUCCESS The keystroke information was returned.
537 @retval EFI_NOT_READY There was no keystroke data availiable.
538 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
540 @retval EFI_INVALID_PARAMETER KeyData is NULL.
541 @retval Others Fail to translate keycode into EFI_INPUT_KEY
546 USBKeyboardReadKeyStrokeWorker (
547 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
548 OUT EFI_KEY_DATA
*KeyData
554 LIST_ENTRY
*NotifyList
;
555 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
556 EFI_KEY_DATA OriginalKeyData
;
558 if (KeyData
== NULL
) {
559 return EFI_INVALID_PARAMETER
;
563 // If there is no saved USB keycode, fetch it
564 // by calling USBKeyboardCheckForKey().
566 if (UsbKeyboardDevice
->CurKeyCode
== 0) {
567 Status
= USBKeyboardCheckForKey (UsbKeyboardDevice
);
568 if (EFI_ERROR (Status
)) {
569 return EFI_NOT_READY
;
573 KeyData
->Key
.UnicodeChar
= 0;
574 KeyData
->Key
.ScanCode
= SCAN_NULL
;
577 // Store the current keycode and clear it.
579 KeyCode
= UsbKeyboardDevice
->CurKeyCode
;
580 UsbKeyboardDevice
->CurKeyCode
= 0;
583 // Translate saved USB keycode into EFI_INPUT_KEY
585 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyCode
, &KeyData
->Key
);
586 if (EFI_ERROR (Status
)) {
591 // Get current state of various toggled attributes as well as input modifier values,
592 // and set them as valid.
594 CopyMem (&KeyData
->KeyState
, &UsbKeyboardDevice
->KeyState
, sizeof (KeyData
->KeyState
));
596 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
597 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
600 // Switch the control value to their original characters.
601 // In UsbKeyCodeToEfiInputKey() the CTRL-Alpha characters have been switched to
602 // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A),
603 // here switch them back for notification function.
605 CopyMem (&OriginalKeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
606 if (UsbKeyboardDevice
->CtrlOn
) {
607 if (OriginalKeyData
.Key
.UnicodeChar
>= 0x01 && OriginalKeyData
.Key
.UnicodeChar
<= 0x1A) {
608 if (UsbKeyboardDevice
->CapsOn
) {
609 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'A' - 1);
611 OriginalKeyData
.Key
.UnicodeChar
= (CHAR16
)(OriginalKeyData
.Key
.UnicodeChar
+ 'a' - 1);
617 // Invoke notification functions if the key is registered.
619 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
620 for (Link
= GetFirstNode (NotifyList
);
621 !IsNull (NotifyList
, Link
);
622 Link
= GetNextNode (NotifyList
, Link
)) {
623 CurrentNotify
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
624 if (IsKeyRegistered (&CurrentNotify
->KeyData
, &OriginalKeyData
)) {
625 CurrentNotify
->KeyNotificationFn (&OriginalKeyData
);
633 Reset the input device and optionally run diagnostics
635 There are 2 types of reset for USB keyboard.
636 For non-exhaustive reset, only keyboard buffer is cleared.
637 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
638 is also re-initialized.
640 @param This Protocol instance pointer.
641 @param ExtendedVerification Driver may perform diagnostics on reset.
643 @retval EFI_SUCCESS The device was reset.
644 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
650 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
651 IN BOOLEAN ExtendedVerification
655 USB_KB_DEV
*UsbKeyboardDevice
;
657 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
659 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
661 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
),
662 UsbKeyboardDevice
->DevicePath
666 // Non-exhaustive reset:
667 // only reset private data structures.
669 if (!ExtendedVerification
) {
670 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
672 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
),
673 UsbKeyboardDevice
->DevicePath
676 // Clear the key buffer of this USB keyboard
678 InitUSBKeyBuffer (&(UsbKeyboardDevice
->KeyboardBuffer
));
679 UsbKeyboardDevice
->CurKeyCode
= 0;
687 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
688 UsbKeyboardDevice
->CurKeyCode
= 0;
689 if (EFI_ERROR (Status
)) {
690 return EFI_DEVICE_ERROR
;
698 Reads the next keystroke from the input device.
700 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
701 @param Key A pointer to a buffer that is filled in with the keystroke
702 information for the key that was pressed.
704 @retval EFI_SUCCESS The keystroke information was returned.
705 @retval EFI_NOT_READY There was no keystroke data availiable.
706 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
712 USBKeyboardReadKeyStroke (
713 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
714 OUT EFI_INPUT_KEY
*Key
717 USB_KB_DEV
*UsbKeyboardDevice
;
719 EFI_KEY_DATA KeyData
;
721 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
723 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
724 if (EFI_ERROR (Status
)) {
728 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
735 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
736 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.
738 @param Event Event to be signaled when a key is pressed.
739 @param Context Points to USB_KB_DEV instance.
744 USBKeyboardWaitForKey (
749 USB_KB_DEV
*UsbKeyboardDevice
;
751 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
753 if (UsbKeyboardDevice
->CurKeyCode
== 0) {
754 if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice
))) {
756 // If no pending key, simply return.
762 // If there is pending key, signal the event.
764 gBS
->SignalEvent (Event
);
769 Check whether there is key pending in the keyboard buffer.
771 @param UsbKeyboardDevice The USB_KB_DEV instance.
773 @retval EFI_SUCCESS There is pending key to read.
774 @retval EFI_NOT_READY No pending key to read.
779 USBKeyboardCheckForKey (
780 IN OUT USB_KB_DEV
*UsbKeyboardDevice
787 // Fetch raw data from the USB keyboard buffer,
788 // and translate it into USB keycode.
790 Status
= USBParseKey (UsbKeyboardDevice
, &KeyCode
);
791 if (EFI_ERROR (Status
)) {
792 return EFI_NOT_READY
;
795 UsbKeyboardDevice
->CurKeyCode
= KeyCode
;
800 Free keyboard notify list.
802 @param NotifyList The keyboard notify list to free.
804 @retval EFI_SUCCESS Free the notify list successfully.
805 @retval EFI_INVALID_PARAMETER NotifyList is NULL.
811 IN OUT LIST_ENTRY
*NotifyList
814 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
817 if (NotifyList
== NULL
) {
818 return EFI_INVALID_PARAMETER
;
820 while (!IsListEmpty (NotifyList
)) {
821 Link
= GetFirstNode (NotifyList
);
822 NotifyNode
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
823 RemoveEntryList (Link
);
824 FreePool (NotifyNode
);
831 Check whether the pressed key matches a registered key or not.
833 @param RegsiteredData A pointer to keystroke data for the key that was registered.
834 @param InputData A pointer to keystroke data for the key that was pressed.
836 @retval TRUE Key pressed matches a registered key.
837 @retval FLASE Key pressed does not matches a registered key.
843 IN EFI_KEY_DATA
*RegsiteredData
,
844 IN EFI_KEY_DATA
*InputData
847 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
849 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
850 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
855 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
857 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
858 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
861 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
862 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
870 // Simple Text Input Ex protocol functions
873 Resets the input device hardware.
875 The Reset() function resets the input device hardware. As part
876 of initialization process, the firmware/device will make a quick
877 but reasonable attempt to verify that the device is functioning.
878 If the ExtendedVerification flag is TRUE the firmware may take
879 an extended amount of time to verify the device is operating on
880 reset. Otherwise the reset operation is to occur as quickly as
881 possible. The hardware verification process is not defined by
882 this specification and is left up to the platform firmware or
885 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
887 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
888 verification operation of the device during reset.
890 @retval EFI_SUCCESS The device was reset.
891 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
897 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
898 IN BOOLEAN ExtendedVerification
902 USB_KB_DEV
*UsbKeyboardDevice
;
906 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
908 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
909 if (EFI_ERROR (Status
)) {
910 return EFI_DEVICE_ERROR
;
913 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
914 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
915 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
916 gBS
->RestoreTPL (OldTpl
);
923 Reads the next keystroke from the input device.
925 @param This Protocol instance pointer.
926 @param KeyData A pointer to a buffer that is filled in with the keystroke
927 state data for the key that was pressed.
929 @retval EFI_SUCCESS The keystroke information was returned.
930 @retval EFI_NOT_READY There was no keystroke data available.
931 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
933 @retval EFI_INVALID_PARAMETER KeyData is NULL.
938 USBKeyboardReadKeyStrokeEx (
939 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
940 OUT EFI_KEY_DATA
*KeyData
943 USB_KB_DEV
*UsbKeyboardDevice
;
945 if (KeyData
== NULL
) {
946 return EFI_INVALID_PARAMETER
;
949 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
951 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, KeyData
);
956 Set certain state for the input device.
958 @param This Protocol instance pointer.
959 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
960 state for the input device.
962 @retval EFI_SUCCESS The device state was set appropriately.
963 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
964 not have the setting adjusted.
965 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.
966 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
971 USBKeyboardSetState (
972 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
973 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
976 USB_KB_DEV
*UsbKeyboardDevice
;
978 if (KeyToggleState
== NULL
) {
979 return EFI_INVALID_PARAMETER
;
982 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
984 if (((UsbKeyboardDevice
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
985 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
986 return EFI_UNSUPPORTED
;
990 // Update the status light
993 UsbKeyboardDevice
->ScrollOn
= FALSE
;
994 UsbKeyboardDevice
->NumLockOn
= FALSE
;
995 UsbKeyboardDevice
->CapsOn
= FALSE
;
997 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
998 UsbKeyboardDevice
->ScrollOn
= TRUE
;
1000 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
1001 UsbKeyboardDevice
->NumLockOn
= TRUE
;
1003 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
1004 UsbKeyboardDevice
->CapsOn
= TRUE
;
1007 SetKeyLED (UsbKeyboardDevice
);
1009 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
1016 Register a notification function for a particular keystroke for the input device.
1018 @param This Protocol instance pointer.
1019 @param KeyData A pointer to a buffer that is filled in with the keystroke
1020 information data for the key that was pressed.
1021 @param KeyNotificationFunction Points to the function to be called when the key
1022 sequence is typed specified by KeyData.
1023 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1025 @retval EFI_SUCCESS The notification function was registered successfully.
1026 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.
1027 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
1032 USBKeyboardRegisterKeyNotify (
1033 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1034 IN EFI_KEY_DATA
*KeyData
,
1035 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
1036 OUT EFI_HANDLE
*NotifyHandle
1039 USB_KB_DEV
*UsbKeyboardDevice
;
1040 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
1042 LIST_ENTRY
*NotifyList
;
1043 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1045 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
1046 return EFI_INVALID_PARAMETER
;
1049 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1052 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1054 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1056 for (Link
= GetFirstNode (NotifyList
);
1057 !IsNull (NotifyList
, Link
);
1058 Link
= GetNextNode (NotifyList
, Link
)) {
1059 CurrentNotify
= CR (
1061 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1063 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1065 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
1066 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
1067 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
1074 // Allocate resource to save the notification function
1076 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
1077 if (NewNotify
== NULL
) {
1078 return EFI_OUT_OF_RESOURCES
;
1081 NewNotify
->Signature
= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
1082 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
1083 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
1084 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
1085 InsertTailList (&UsbKeyboardDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
1088 *NotifyHandle
= NewNotify
->NotifyHandle
;
1095 Remove a registered notification function from a particular keystroke.
1097 @param This Protocol instance pointer.
1098 @param NotificationHandle The handle of the notification function being unregistered.
1100 @retval EFI_SUCCESS The notification function was unregistered successfully.
1101 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid
1106 USBKeyboardUnregisterKeyNotify (
1107 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1108 IN EFI_HANDLE NotificationHandle
1111 USB_KB_DEV
*UsbKeyboardDevice
;
1112 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1114 LIST_ENTRY
*NotifyList
;
1116 if (NotificationHandle
== NULL
) {
1117 return EFI_INVALID_PARAMETER
;
1120 if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
1121 return EFI_INVALID_PARAMETER
;
1124 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1127 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1129 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1130 for (Link
= GetFirstNode (NotifyList
);
1131 !IsNull (NotifyList
, Link
);
1132 Link
= GetNextNode (NotifyList
, Link
)) {
1133 CurrentNotify
= CR (
1135 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1137 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1139 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
1141 // Remove the notification function from NotifyList and free resources
1143 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
1145 FreePool (CurrentNotify
);
1151 // Cannot find the matching entry in database.
1153 return EFI_INVALID_PARAMETER
;