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 - 2012, 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 // Report Status Code to indicate that there is no USB keyboard
250 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
251 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_EC_NOT_DETECTED
)
254 // No interrupt endpoint found, then return unsupported.
256 Status
= EFI_UNSUPPORTED
;
260 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
262 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DETECTED
),
263 UsbKeyboardDevice
->DevicePath
266 UsbKeyboardDevice
->Signature
= USB_KB_DEV_SIGNATURE
;
267 UsbKeyboardDevice
->SimpleInput
.Reset
= USBKeyboardReset
;
268 UsbKeyboardDevice
->SimpleInput
.ReadKeyStroke
= USBKeyboardReadKeyStroke
;
270 UsbKeyboardDevice
->SimpleInputEx
.Reset
= USBKeyboardResetEx
;
271 UsbKeyboardDevice
->SimpleInputEx
.ReadKeyStrokeEx
= USBKeyboardReadKeyStrokeEx
;
272 UsbKeyboardDevice
->SimpleInputEx
.SetState
= USBKeyboardSetState
;
273 UsbKeyboardDevice
->SimpleInputEx
.RegisterKeyNotify
= USBKeyboardRegisterKeyNotify
;
274 UsbKeyboardDevice
->SimpleInputEx
.UnregisterKeyNotify
= USBKeyboardUnregisterKeyNotify
;
276 InitializeListHead (&UsbKeyboardDevice
->NotifyList
);
278 Status
= gBS
->CreateEvent (
279 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
281 USBKeyboardTimerHandler
,
283 &UsbKeyboardDevice
->TimerEvent
285 if (!EFI_ERROR (Status
)) {
286 Status
= gBS
->SetTimer (UsbKeyboardDevice
->TimerEvent
, TimerPeriodic
, KEYBOARD_TIMER_INTERVAL
);
288 if (EFI_ERROR (Status
)) {
292 Status
= gBS
->CreateEvent (
295 USBKeyboardWaitForKey
,
297 &(UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
)
300 if (EFI_ERROR (Status
)) {
304 Status
= gBS
->CreateEvent (
307 USBKeyboardWaitForKey
,
309 &(UsbKeyboardDevice
->SimpleInput
.WaitForKey
)
311 if (EFI_ERROR (Status
)) {
316 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol
317 // for the USB keyboard device.
318 // USB keyboard is a hot plug device, and expected to work immediately
319 // when plugging into system, other conventional console devices could
320 // distinguish it by its device path.
322 Status
= gBS
->InstallMultipleProtocolInterfaces (
324 &gEfiSimpleTextInProtocolGuid
,
325 &UsbKeyboardDevice
->SimpleInput
,
326 &gEfiSimpleTextInputExProtocolGuid
,
327 &UsbKeyboardDevice
->SimpleInputEx
,
330 if (EFI_ERROR (Status
)) {
334 UsbKeyboardDevice
->ControllerHandle
= Controller
;
335 Status
= InitKeyboardLayout (UsbKeyboardDevice
);
336 if (EFI_ERROR (Status
)) {
337 gBS
->UninstallMultipleProtocolInterfaces (
339 &gEfiSimpleTextInProtocolGuid
,
340 &UsbKeyboardDevice
->SimpleInput
,
341 &gEfiSimpleTextInputExProtocolGuid
,
342 &UsbKeyboardDevice
->SimpleInputEx
,
350 // Reset USB Keyboard Device exhaustively.
352 Status
= UsbKeyboardDevice
->SimpleInputEx
.Reset (
353 &UsbKeyboardDevice
->SimpleInputEx
,
356 if (EFI_ERROR (Status
)) {
357 gBS
->UninstallMultipleProtocolInterfaces (
359 &gEfiSimpleTextInProtocolGuid
,
360 &UsbKeyboardDevice
->SimpleInput
,
361 &gEfiSimpleTextInputExProtocolGuid
,
362 &UsbKeyboardDevice
->SimpleInputEx
,
369 // Submit Asynchronous Interrupt Transfer to manage this device.
371 EndpointAddr
= UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
;
372 PollingInterval
= UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
;
373 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
375 Status
= UsbIo
->UsbAsyncInterruptTransfer (
385 if (EFI_ERROR (Status
)) {
386 gBS
->UninstallMultipleProtocolInterfaces (
388 &gEfiSimpleTextInProtocolGuid
,
389 &UsbKeyboardDevice
->SimpleInput
,
390 &gEfiSimpleTextInputExProtocolGuid
,
391 &UsbKeyboardDevice
->SimpleInputEx
,
397 UsbKeyboardDevice
->ControllerNameTable
= NULL
;
400 gUsbKeyboardComponentName
.SupportedLanguages
,
401 &UsbKeyboardDevice
->ControllerNameTable
,
402 L
"Generic Usb Keyboard",
407 gUsbKeyboardComponentName2
.SupportedLanguages
,
408 &UsbKeyboardDevice
->ControllerNameTable
,
409 L
"Generic Usb Keyboard",
413 gBS
->RestoreTPL (OldTpl
);
420 if (UsbKeyboardDevice
!= NULL
) {
421 if (UsbKeyboardDevice
->TimerEvent
!= NULL
) {
422 gBS
->CloseEvent (UsbKeyboardDevice
->TimerEvent
);
424 if (UsbKeyboardDevice
->SimpleInput
.WaitForKey
!= NULL
) {
425 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
427 if (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
428 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
430 if (UsbKeyboardDevice
->KeyboardLayoutEvent
!= NULL
) {
431 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
432 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
434 FreePool (UsbKeyboardDevice
);
435 UsbKeyboardDevice
= NULL
;
439 &gEfiUsbIoProtocolGuid
,
440 This
->DriverBindingHandle
,
445 gBS
->RestoreTPL (OldTpl
);
453 Stop the USB keyboard device handled by this driver.
455 @param This The USB keyboard driver binding protocol.
456 @param Controller The controller to release.
457 @param NumberOfChildren The number of handles in ChildHandleBuffer.
458 @param ChildHandleBuffer The array of child handle.
460 @retval EFI_SUCCESS The device was stopped.
461 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
462 is not installed on Controller.
463 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
464 @retval Others Fail to uninstall protocols attached on the device.
469 USBKeyboardDriverBindingStop (
470 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
471 IN EFI_HANDLE Controller
,
472 IN UINTN NumberOfChildren
,
473 IN EFI_HANDLE
*ChildHandleBuffer
477 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
478 USB_KB_DEV
*UsbKeyboardDevice
;
480 Status
= gBS
->OpenProtocol (
482 &gEfiSimpleTextInProtocolGuid
,
483 (VOID
**) &SimpleInput
,
484 This
->DriverBindingHandle
,
486 EFI_OPEN_PROTOCOL_GET_PROTOCOL
488 if (EFI_ERROR (Status
)) {
489 return EFI_UNSUPPORTED
;
492 Status
= gBS
->OpenProtocol (
494 &gEfiSimpleTextInputExProtocolGuid
,
496 This
->DriverBindingHandle
,
498 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
500 if (EFI_ERROR (Status
)) {
501 return EFI_UNSUPPORTED
;
504 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
507 // The key data input from this device will be disabled.
509 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
511 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DISABLE
),
512 UsbKeyboardDevice
->DevicePath
516 // Delete the Asynchronous Interrupt Transfer from this device
518 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
519 UsbKeyboardDevice
->UsbIo
,
520 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
522 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
530 &gEfiUsbIoProtocolGuid
,
531 This
->DriverBindingHandle
,
535 Status
= gBS
->UninstallMultipleProtocolInterfaces (
537 &gEfiSimpleTextInProtocolGuid
,
538 &UsbKeyboardDevice
->SimpleInput
,
539 &gEfiSimpleTextInputExProtocolGuid
,
540 &UsbKeyboardDevice
->SimpleInputEx
,
544 // Free all resources.
546 gBS
->CloseEvent (UsbKeyboardDevice
->TimerEvent
);
547 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
548 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
549 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
550 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
551 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
553 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
554 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
556 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
557 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
560 DestroyQueue (&UsbKeyboardDevice
->UsbKeyQueue
);
561 DestroyQueue (&UsbKeyboardDevice
->EfiKeyQueue
);
563 FreePool (UsbKeyboardDevice
);
569 Internal function to read the next keystroke from the keyboard buffer.
571 @param UsbKeyboardDevice USB keyboard's private structure.
572 @param KeyData A pointer to buffer to hold the keystroke
573 data for the key that was pressed.
575 @retval EFI_SUCCESS The keystroke information was returned.
576 @retval EFI_NOT_READY There was no keystroke data availiable.
577 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
579 @retval EFI_INVALID_PARAMETER KeyData is NULL.
580 @retval Others Fail to translate keycode into EFI_INPUT_KEY
584 USBKeyboardReadKeyStrokeWorker (
585 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
586 OUT EFI_KEY_DATA
*KeyData
589 if (KeyData
== NULL
) {
590 return EFI_INVALID_PARAMETER
;
593 if (IsQueueEmpty (&UsbKeyboardDevice
->EfiKeyQueue
)) {
594 return EFI_NOT_READY
;
597 Dequeue (&UsbKeyboardDevice
->EfiKeyQueue
, KeyData
, sizeof (*KeyData
));
603 Reset the input device and optionally run diagnostics
605 There are 2 types of reset for USB keyboard.
606 For non-exhaustive reset, only keyboard buffer is cleared.
607 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
608 is also re-initialized.
610 @param This Protocol instance pointer.
611 @param ExtendedVerification Driver may perform diagnostics on reset.
613 @retval EFI_SUCCESS The device was reset.
614 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
620 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
621 IN BOOLEAN ExtendedVerification
625 USB_KB_DEV
*UsbKeyboardDevice
;
627 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
629 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
631 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
),
632 UsbKeyboardDevice
->DevicePath
636 // Non-exhaustive reset:
637 // only reset private data structures.
639 if (!ExtendedVerification
) {
640 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
642 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
),
643 UsbKeyboardDevice
->DevicePath
646 // Clear the key buffer of this USB keyboard
648 InitQueue (&UsbKeyboardDevice
->UsbKeyQueue
, sizeof (USB_KEY
));
649 InitQueue (&UsbKeyboardDevice
->EfiKeyQueue
, sizeof (EFI_KEY_DATA
));
657 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
658 if (EFI_ERROR (Status
)) {
659 return EFI_DEVICE_ERROR
;
667 Reads the next keystroke from the input device.
669 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
670 @param Key A pointer to a buffer that is filled in with the keystroke
671 information for the key that was pressed.
673 @retval EFI_SUCCESS The keystroke information was returned.
674 @retval EFI_NOT_READY There was no keystroke data availiable.
675 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
681 USBKeyboardReadKeyStroke (
682 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
683 OUT EFI_INPUT_KEY
*Key
686 USB_KB_DEV
*UsbKeyboardDevice
;
688 EFI_KEY_DATA KeyData
;
690 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
693 // Considering if the partial keystroke is enabled, there maybe a partial
694 // keystroke in the queue, so here skip the partial keystroke and get the
695 // next key from the queue
698 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
699 if (EFI_ERROR (Status
)) {
703 // SimpleTextIn Protocol doesn't support partial keystroke;
705 if (KeyData
.Key
.ScanCode
== CHAR_NULL
&& KeyData
.Key
.UnicodeChar
== SCAN_NULL
) {
709 // Translate the CTRL-Alpha characters to their corresponding control value
710 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
712 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
713 if (KeyData
.Key
.UnicodeChar
>= L
'a' && KeyData
.Key
.UnicodeChar
<= L
'z') {
714 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'a' + 1);
715 } else if (KeyData
.Key
.UnicodeChar
>= L
'A' && KeyData
.Key
.UnicodeChar
<= L
'Z') {
716 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'A' + 1);
720 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
727 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
728 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.
730 @param Event Event to be signaled when a key is pressed.
731 @param Context Points to USB_KB_DEV instance.
736 USBKeyboardWaitForKey (
741 USB_KB_DEV
*UsbKeyboardDevice
;
742 EFI_KEY_DATA KeyData
;
745 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
748 // Enter critical section
750 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
753 // WaitforKey doesn't suppor the partial key.
754 // Considering if the partial keystroke is enabled, there maybe a partial
755 // keystroke in the queue, so here skip the partial keystroke and get the
756 // next key from the queue
758 while (!IsQueueEmpty (&UsbKeyboardDevice
->EfiKeyQueue
)) {
760 // If there is pending key, signal the event.
764 UsbKeyboardDevice
->EfiKeyQueue
.Buffer
[UsbKeyboardDevice
->EfiKeyQueue
.Head
],
765 sizeof (EFI_KEY_DATA
)
767 if (KeyData
.Key
.ScanCode
== SCAN_NULL
&& KeyData
.Key
.UnicodeChar
== CHAR_NULL
) {
768 Dequeue (&UsbKeyboardDevice
->EfiKeyQueue
, &KeyData
, sizeof (EFI_KEY_DATA
));
771 gBS
->SignalEvent (Event
);
775 // Leave critical section and return
777 gBS
->RestoreTPL (OldTpl
);
781 Timer handler to convert the key from USB.
783 @param Event Indicates the event that invoke this function.
784 @param Context Indicates the calling context.
788 USBKeyboardTimerHandler (
794 USB_KB_DEV
*UsbKeyboardDevice
;
796 EFI_KEY_DATA KeyData
;
798 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
801 // Fetch raw data from the USB keyboard buffer,
802 // and translate it into USB keycode.
804 Status
= USBParseKey (UsbKeyboardDevice
, &KeyCode
);
805 if (EFI_ERROR (Status
)) {
810 // Translate saved USB keycode into EFI_INPUT_KEY
812 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyCode
, &KeyData
);
813 if (EFI_ERROR (Status
)) {
818 // Insert to the EFI Key queue
820 Enqueue (&UsbKeyboardDevice
->EfiKeyQueue
, &KeyData
, sizeof (KeyData
));
824 Free keyboard notify list.
826 @param NotifyList The keyboard notify list to free.
828 @retval EFI_SUCCESS Free the notify list successfully.
829 @retval EFI_INVALID_PARAMETER NotifyList is NULL.
834 IN OUT LIST_ENTRY
*NotifyList
837 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
840 if (NotifyList
== NULL
) {
841 return EFI_INVALID_PARAMETER
;
843 while (!IsListEmpty (NotifyList
)) {
844 Link
= GetFirstNode (NotifyList
);
845 NotifyNode
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
846 RemoveEntryList (Link
);
847 FreePool (NotifyNode
);
854 Check whether the pressed key matches a registered key or not.
856 @param RegsiteredData A pointer to keystroke data for the key that was registered.
857 @param InputData A pointer to keystroke data for the key that was pressed.
859 @retval TRUE Key pressed matches a registered key.
860 @retval FLASE Key pressed does not matches a registered key.
865 IN EFI_KEY_DATA
*RegsiteredData
,
866 IN EFI_KEY_DATA
*InputData
869 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
871 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
872 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
877 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
879 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
880 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
883 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
884 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
892 // Simple Text Input Ex protocol functions
895 Resets the input device hardware.
897 The Reset() function resets the input device hardware. As part
898 of initialization process, the firmware/device will make a quick
899 but reasonable attempt to verify that the device is functioning.
900 If the ExtendedVerification flag is TRUE the firmware may take
901 an extended amount of time to verify the device is operating on
902 reset. Otherwise the reset operation is to occur as quickly as
903 possible. The hardware verification process is not defined by
904 this specification and is left up to the platform firmware or
907 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
909 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
910 verification operation of the device during reset.
912 @retval EFI_SUCCESS The device was reset.
913 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
919 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
920 IN BOOLEAN ExtendedVerification
924 USB_KB_DEV
*UsbKeyboardDevice
;
926 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
928 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
929 if (EFI_ERROR (Status
)) {
930 return EFI_DEVICE_ERROR
;
933 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
934 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
941 Reads the next keystroke from the input device.
943 @param This Protocol instance pointer.
944 @param KeyData A pointer to a buffer that is filled in with the keystroke
945 state data for the key that was pressed.
947 @retval EFI_SUCCESS The keystroke information was returned.
948 @retval EFI_NOT_READY There was no keystroke data available.
949 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
951 @retval EFI_INVALID_PARAMETER KeyData is NULL.
956 USBKeyboardReadKeyStrokeEx (
957 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
958 OUT EFI_KEY_DATA
*KeyData
961 USB_KB_DEV
*UsbKeyboardDevice
;
963 if (KeyData
== NULL
) {
964 return EFI_INVALID_PARAMETER
;
967 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
969 return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, KeyData
);
974 Set certain state for the input device.
976 @param This Protocol instance pointer.
977 @param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the
978 state for the input device.
980 @retval EFI_SUCCESS The device state was set appropriately.
981 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could
982 not have the setting adjusted.
983 @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.
984 @retval EFI_INVALID_PARAMETER KeyToggleState is NULL.
989 USBKeyboardSetState (
990 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
991 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
994 USB_KB_DEV
*UsbKeyboardDevice
;
996 if (KeyToggleState
== NULL
) {
997 return EFI_INVALID_PARAMETER
;
1000 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1002 if (((UsbKeyboardDevice
->KeyState
.KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
) ||
1003 ((*KeyToggleState
& EFI_TOGGLE_STATE_VALID
) != EFI_TOGGLE_STATE_VALID
)) {
1004 return EFI_UNSUPPORTED
;
1008 // Update the status light
1011 UsbKeyboardDevice
->ScrollOn
= FALSE
;
1012 UsbKeyboardDevice
->NumLockOn
= FALSE
;
1013 UsbKeyboardDevice
->CapsOn
= FALSE
;
1014 UsbKeyboardDevice
->IsSupportPartialKey
= FALSE
;
1016 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
1017 UsbKeyboardDevice
->ScrollOn
= TRUE
;
1019 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
1020 UsbKeyboardDevice
->NumLockOn
= TRUE
;
1022 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
1023 UsbKeyboardDevice
->CapsOn
= TRUE
;
1025 if ((*KeyToggleState
& EFI_KEY_STATE_EXPOSED
) == EFI_KEY_STATE_EXPOSED
) {
1026 UsbKeyboardDevice
->IsSupportPartialKey
= TRUE
;
1029 SetKeyLED (UsbKeyboardDevice
);
1031 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
1038 Register a notification function for a particular keystroke for the input device.
1040 @param This Protocol instance pointer.
1041 @param KeyData A pointer to a buffer that is filled in with the keystroke
1042 information data for the key that was pressed.
1043 @param KeyNotificationFunction Points to the function to be called when the key
1044 sequence is typed specified by KeyData.
1045 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1047 @retval EFI_SUCCESS The notification function was registered successfully.
1048 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.
1049 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
1054 USBKeyboardRegisterKeyNotify (
1055 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1056 IN EFI_KEY_DATA
*KeyData
,
1057 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
1058 OUT VOID
**NotifyHandle
1061 USB_KB_DEV
*UsbKeyboardDevice
;
1062 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
1064 LIST_ENTRY
*NotifyList
;
1065 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1067 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
1068 return EFI_INVALID_PARAMETER
;
1071 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1074 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1076 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1078 for (Link
= GetFirstNode (NotifyList
);
1079 !IsNull (NotifyList
, Link
);
1080 Link
= GetNextNode (NotifyList
, Link
)) {
1081 CurrentNotify
= CR (
1083 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1085 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1087 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
1088 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
1089 *NotifyHandle
= CurrentNotify
;
1096 // Allocate resource to save the notification function
1098 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
1099 if (NewNotify
== NULL
) {
1100 return EFI_OUT_OF_RESOURCES
;
1103 NewNotify
->Signature
= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
1104 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
1105 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
1106 InsertTailList (&UsbKeyboardDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
1109 *NotifyHandle
= NewNotify
;
1116 Remove a registered notification function from a particular keystroke.
1118 @param This Protocol instance pointer.
1119 @param NotificationHandle The handle of the notification function being unregistered.
1121 @retval EFI_SUCCESS The notification function was unregistered successfully.
1122 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid
1127 USBKeyboardUnregisterKeyNotify (
1128 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1129 IN VOID
*NotificationHandle
1132 USB_KB_DEV
*UsbKeyboardDevice
;
1133 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1135 LIST_ENTRY
*NotifyList
;
1137 if (NotificationHandle
== NULL
) {
1138 return EFI_INVALID_PARAMETER
;
1141 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1144 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1146 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1147 for (Link
= GetFirstNode (NotifyList
);
1148 !IsNull (NotifyList
, Link
);
1149 Link
= GetNextNode (NotifyList
, Link
)) {
1150 CurrentNotify
= CR (
1152 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1154 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1156 if (CurrentNotify
== NotificationHandle
) {
1158 // Remove the notification function from NotifyList and free resources
1160 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
1162 FreePool (CurrentNotify
);
1168 // Cannot find the matching entry in database.
1170 return EFI_INVALID_PARAMETER
;