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 - 2011, 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 (
266 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
268 USBKeyboardTimerHandler
,
270 &UsbKeyboardDevice
->TimerEvent
272 if (!EFI_ERROR (Status
)) {
273 Status
= gBS
->SetTimer (UsbKeyboardDevice
->TimerEvent
, TimerPeriodic
, KEYBOARD_TIMER_INTERVAL
);
275 if (EFI_ERROR (Status
)) {
279 Status
= gBS
->CreateEvent (
282 USBKeyboardWaitForKey
,
284 &(UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
)
287 if (EFI_ERROR (Status
)) {
291 Status
= gBS
->CreateEvent (
294 USBKeyboardWaitForKey
,
296 &(UsbKeyboardDevice
->SimpleInput
.WaitForKey
)
298 if (EFI_ERROR (Status
)) {
303 // Install Simple Text Input Protocol and Simple Text Input Ex Protocol
304 // for the USB keyboard device.
305 // USB keyboard is a hot plug device, and expected to work immediately
306 // when plugging into system, other conventional console devices could
307 // distinguish it by its device path.
309 Status
= gBS
->InstallMultipleProtocolInterfaces (
311 &gEfiSimpleTextInProtocolGuid
,
312 &UsbKeyboardDevice
->SimpleInput
,
313 &gEfiSimpleTextInputExProtocolGuid
,
314 &UsbKeyboardDevice
->SimpleInputEx
,
317 if (EFI_ERROR (Status
)) {
321 UsbKeyboardDevice
->ControllerHandle
= Controller
;
322 Status
= InitKeyboardLayout (UsbKeyboardDevice
);
323 if (EFI_ERROR (Status
)) {
324 gBS
->UninstallMultipleProtocolInterfaces (
326 &gEfiSimpleTextInProtocolGuid
,
327 &UsbKeyboardDevice
->SimpleInput
,
328 &gEfiSimpleTextInputExProtocolGuid
,
329 &UsbKeyboardDevice
->SimpleInputEx
,
337 // Reset USB Keyboard Device exhaustively.
339 Status
= UsbKeyboardDevice
->SimpleInputEx
.Reset (
340 &UsbKeyboardDevice
->SimpleInputEx
,
343 if (EFI_ERROR (Status
)) {
344 gBS
->UninstallMultipleProtocolInterfaces (
346 &gEfiSimpleTextInProtocolGuid
,
347 &UsbKeyboardDevice
->SimpleInput
,
348 &gEfiSimpleTextInputExProtocolGuid
,
349 &UsbKeyboardDevice
->SimpleInputEx
,
356 // Submit Asynchronous Interrupt Transfer to manage this device.
358 EndpointAddr
= UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
;
359 PollingInterval
= UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
;
360 PacketSize
= (UINT8
) (UsbKeyboardDevice
->IntEndpointDescriptor
.MaxPacketSize
);
362 Status
= UsbIo
->UsbAsyncInterruptTransfer (
372 if (EFI_ERROR (Status
)) {
373 gBS
->UninstallMultipleProtocolInterfaces (
375 &gEfiSimpleTextInProtocolGuid
,
376 &UsbKeyboardDevice
->SimpleInput
,
377 &gEfiSimpleTextInputExProtocolGuid
,
378 &UsbKeyboardDevice
->SimpleInputEx
,
384 UsbKeyboardDevice
->ControllerNameTable
= NULL
;
387 gUsbKeyboardComponentName
.SupportedLanguages
,
388 &UsbKeyboardDevice
->ControllerNameTable
,
389 L
"Generic Usb Keyboard",
394 gUsbKeyboardComponentName2
.SupportedLanguages
,
395 &UsbKeyboardDevice
->ControllerNameTable
,
396 L
"Generic Usb Keyboard",
400 gBS
->RestoreTPL (OldTpl
);
407 if (UsbKeyboardDevice
!= NULL
) {
408 if (UsbKeyboardDevice
->TimerEvent
!= NULL
) {
409 gBS
->CloseEvent (UsbKeyboardDevice
->TimerEvent
);
411 if (UsbKeyboardDevice
->SimpleInput
.WaitForKey
!= NULL
) {
412 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
414 if (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
!= NULL
) {
415 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
417 if (UsbKeyboardDevice
->KeyboardLayoutEvent
!= NULL
) {
418 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
419 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
421 FreePool (UsbKeyboardDevice
);
422 UsbKeyboardDevice
= NULL
;
426 &gEfiUsbIoProtocolGuid
,
427 This
->DriverBindingHandle
,
432 gBS
->RestoreTPL (OldTpl
);
440 Stop the USB keyboard device handled by this driver.
442 @param This The USB keyboard driver binding protocol.
443 @param Controller The controller to release.
444 @param NumberOfChildren The number of handles in ChildHandleBuffer.
445 @param ChildHandleBuffer The array of child handle.
447 @retval EFI_SUCCESS The device was stopped.
448 @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol
449 is not installed on Controller.
450 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
451 @retval Others Fail to uninstall protocols attached on the device.
456 USBKeyboardDriverBindingStop (
457 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
458 IN EFI_HANDLE Controller
,
459 IN UINTN NumberOfChildren
,
460 IN EFI_HANDLE
*ChildHandleBuffer
464 EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*SimpleInput
;
465 USB_KB_DEV
*UsbKeyboardDevice
;
467 Status
= gBS
->OpenProtocol (
469 &gEfiSimpleTextInProtocolGuid
,
470 (VOID
**) &SimpleInput
,
471 This
->DriverBindingHandle
,
473 EFI_OPEN_PROTOCOL_GET_PROTOCOL
475 if (EFI_ERROR (Status
)) {
476 return EFI_UNSUPPORTED
;
479 Status
= gBS
->OpenProtocol (
481 &gEfiSimpleTextInputExProtocolGuid
,
483 This
->DriverBindingHandle
,
485 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
487 if (EFI_ERROR (Status
)) {
488 return EFI_UNSUPPORTED
;
491 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (SimpleInput
);
494 // The key data input from this device will be disabled.
496 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
498 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_DISABLE
),
499 UsbKeyboardDevice
->DevicePath
503 // Delete the Asynchronous Interrupt Transfer from this device
505 UsbKeyboardDevice
->UsbIo
->UsbAsyncInterruptTransfer (
506 UsbKeyboardDevice
->UsbIo
,
507 UsbKeyboardDevice
->IntEndpointDescriptor
.EndpointAddress
,
509 UsbKeyboardDevice
->IntEndpointDescriptor
.Interval
,
517 &gEfiUsbIoProtocolGuid
,
518 This
->DriverBindingHandle
,
522 Status
= gBS
->UninstallMultipleProtocolInterfaces (
524 &gEfiSimpleTextInProtocolGuid
,
525 &UsbKeyboardDevice
->SimpleInput
,
526 &gEfiSimpleTextInputExProtocolGuid
,
527 &UsbKeyboardDevice
->SimpleInputEx
,
531 // Free all resources.
533 gBS
->CloseEvent (UsbKeyboardDevice
->TimerEvent
);
534 gBS
->CloseEvent (UsbKeyboardDevice
->RepeatTimer
);
535 gBS
->CloseEvent (UsbKeyboardDevice
->DelayedRecoveryEvent
);
536 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInput
.WaitForKey
);
537 gBS
->CloseEvent (UsbKeyboardDevice
->SimpleInputEx
.WaitForKeyEx
);
538 KbdFreeNotifyList (&UsbKeyboardDevice
->NotifyList
);
540 ReleaseKeyboardLayoutResources (UsbKeyboardDevice
);
541 gBS
->CloseEvent (UsbKeyboardDevice
->KeyboardLayoutEvent
);
543 if (UsbKeyboardDevice
->ControllerNameTable
!= NULL
) {
544 FreeUnicodeStringTable (UsbKeyboardDevice
->ControllerNameTable
);
547 DestroyQueue (&UsbKeyboardDevice
->UsbKeyQueue
);
548 DestroyQueue (&UsbKeyboardDevice
->EfiKeyQueue
);
550 FreePool (UsbKeyboardDevice
);
556 Internal function to read the next keystroke from the keyboard buffer.
558 @param UsbKeyboardDevice USB keyboard's private structure.
559 @param KeyData A pointer to buffer to hold the keystroke
560 data for the key that was pressed.
562 @retval EFI_SUCCESS The keystroke information was returned.
563 @retval EFI_NOT_READY There was no keystroke data availiable.
564 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
566 @retval EFI_INVALID_PARAMETER KeyData is NULL.
567 @retval Others Fail to translate keycode into EFI_INPUT_KEY
571 USBKeyboardReadKeyStrokeWorker (
572 IN OUT USB_KB_DEV
*UsbKeyboardDevice
,
573 OUT EFI_KEY_DATA
*KeyData
576 if (KeyData
== NULL
) {
577 return EFI_INVALID_PARAMETER
;
580 if (IsQueueEmpty (&UsbKeyboardDevice
->EfiKeyQueue
)) {
581 return EFI_NOT_READY
;
584 Dequeue (&UsbKeyboardDevice
->EfiKeyQueue
, KeyData
, sizeof (*KeyData
));
590 Reset the input device and optionally run diagnostics
592 There are 2 types of reset for USB keyboard.
593 For non-exhaustive reset, only keyboard buffer is cleared.
594 For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status
595 is also re-initialized.
597 @param This Protocol instance pointer.
598 @param ExtendedVerification Driver may perform diagnostics on reset.
600 @retval EFI_SUCCESS The device was reset.
601 @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.
607 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
608 IN BOOLEAN ExtendedVerification
612 USB_KB_DEV
*UsbKeyboardDevice
;
614 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
616 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
618 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_PC_RESET
),
619 UsbKeyboardDevice
->DevicePath
623 // Non-exhaustive reset:
624 // only reset private data structures.
626 if (!ExtendedVerification
) {
627 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
629 (EFI_PERIPHERAL_KEYBOARD
| EFI_P_KEYBOARD_PC_CLEAR_BUFFER
),
630 UsbKeyboardDevice
->DevicePath
633 // Clear the key buffer of this USB keyboard
635 InitQueue (&UsbKeyboardDevice
->UsbKeyQueue
, sizeof (USB_KEY
));
636 InitQueue (&UsbKeyboardDevice
->EfiKeyQueue
, sizeof (EFI_KEY_DATA
));
644 Status
= InitUSBKeyboard (UsbKeyboardDevice
);
645 if (EFI_ERROR (Status
)) {
646 return EFI_DEVICE_ERROR
;
654 Reads the next keystroke from the input device.
656 @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.
657 @param Key A pointer to a buffer that is filled in with the keystroke
658 information for the key that was pressed.
660 @retval EFI_SUCCESS The keystroke information was returned.
661 @retval EFI_NOT_READY There was no keystroke data availiable.
662 @retval EFI_DEVICE_ERROR The keystroke information was not returned due to
668 USBKeyboardReadKeyStroke (
669 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
670 OUT EFI_INPUT_KEY
*Key
673 USB_KB_DEV
*UsbKeyboardDevice
;
675 EFI_KEY_DATA KeyData
;
677 UsbKeyboardDevice
= USB_KB_DEV_FROM_THIS (This
);
680 // Considering if the partial keystroke is enabled, there maybe a partial
681 // keystroke in the queue, so here skip the partial keystroke and get the
682 // next key from the queue
685 Status
= USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice
, &KeyData
);
686 if (EFI_ERROR (Status
)) {
690 // SimpleTextIn Protocol doesn't support partial keystroke;
692 if (KeyData
.Key
.ScanCode
== CHAR_NULL
&& KeyData
.Key
.UnicodeChar
== SCAN_NULL
) {
696 // Translate the CTRL-Alpha characters to their corresponding control value
697 // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)
699 if ((KeyData
.KeyState
.KeyShiftState
& (EFI_LEFT_CONTROL_PRESSED
| EFI_RIGHT_CONTROL_PRESSED
)) != 0) {
700 if (KeyData
.Key
.UnicodeChar
>= L
'a' && KeyData
.Key
.UnicodeChar
<= L
'z') {
701 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'a' + 1);
702 } else if (KeyData
.Key
.UnicodeChar
>= L
'A' && KeyData
.Key
.UnicodeChar
<= L
'Z') {
703 KeyData
.Key
.UnicodeChar
= (CHAR16
) (KeyData
.Key
.UnicodeChar
- L
'A' + 1);
707 CopyMem (Key
, &KeyData
.Key
, sizeof (EFI_INPUT_KEY
));
714 Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx
715 and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.
717 @param Event Event to be signaled when a key is pressed.
718 @param Context Points to USB_KB_DEV instance.
723 USBKeyboardWaitForKey (
728 USB_KB_DEV
*UsbKeyboardDevice
;
729 EFI_KEY_DATA KeyData
;
732 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
735 // Enter critical section
737 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
740 // WaitforKey doesn't suppor the partial key.
741 // Considering if the partial keystroke is enabled, there maybe a partial
742 // keystroke in the queue, so here skip the partial keystroke and get the
743 // next key from the queue
745 while (!IsQueueEmpty (&UsbKeyboardDevice
->EfiKeyQueue
)) {
747 // If there is pending key, signal the event.
751 UsbKeyboardDevice
->EfiKeyQueue
.Buffer
[UsbKeyboardDevice
->EfiKeyQueue
.Head
],
752 sizeof (EFI_KEY_DATA
)
754 if (KeyData
.Key
.ScanCode
== SCAN_NULL
&& KeyData
.Key
.UnicodeChar
== CHAR_NULL
) {
755 Dequeue (&UsbKeyboardDevice
->EfiKeyQueue
, &KeyData
, sizeof (EFI_KEY_DATA
));
758 gBS
->SignalEvent (Event
);
762 // Leave critical section and return
764 gBS
->RestoreTPL (OldTpl
);
768 Timer handler to convert the key from USB.
770 @param Event Indicates the event that invoke this function.
771 @param Context Indicates the calling context.
775 USBKeyboardTimerHandler (
781 USB_KB_DEV
*UsbKeyboardDevice
;
783 EFI_KEY_DATA KeyData
;
785 UsbKeyboardDevice
= (USB_KB_DEV
*) Context
;
788 // Fetch raw data from the USB keyboard buffer,
789 // and translate it into USB keycode.
791 Status
= USBParseKey (UsbKeyboardDevice
, &KeyCode
);
792 if (EFI_ERROR (Status
)) {
797 // Translate saved USB keycode into EFI_INPUT_KEY
799 Status
= UsbKeyCodeToEfiInputKey (UsbKeyboardDevice
, KeyCode
, &KeyData
);
800 if (EFI_ERROR (Status
)) {
805 // Insert to the EFI Key queue
807 Enqueue (&UsbKeyboardDevice
->EfiKeyQueue
, &KeyData
, sizeof (KeyData
));
811 Free keyboard notify list.
813 @param NotifyList The keyboard notify list to free.
815 @retval EFI_SUCCESS Free the notify list successfully.
816 @retval EFI_INVALID_PARAMETER NotifyList is NULL.
821 IN OUT LIST_ENTRY
*NotifyList
824 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NotifyNode
;
827 if (NotifyList
== NULL
) {
828 return EFI_INVALID_PARAMETER
;
830 while (!IsListEmpty (NotifyList
)) {
831 Link
= GetFirstNode (NotifyList
);
832 NotifyNode
= CR (Link
, KEYBOARD_CONSOLE_IN_EX_NOTIFY
, NotifyEntry
, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
);
833 RemoveEntryList (Link
);
834 FreePool (NotifyNode
);
841 Check whether the pressed key matches a registered key or not.
843 @param RegsiteredData A pointer to keystroke data for the key that was registered.
844 @param InputData A pointer to keystroke data for the key that was pressed.
846 @retval TRUE Key pressed matches a registered key.
847 @retval FLASE Key pressed does not matches a registered key.
852 IN EFI_KEY_DATA
*RegsiteredData
,
853 IN EFI_KEY_DATA
*InputData
856 ASSERT (RegsiteredData
!= NULL
&& InputData
!= NULL
);
858 if ((RegsiteredData
->Key
.ScanCode
!= InputData
->Key
.ScanCode
) ||
859 (RegsiteredData
->Key
.UnicodeChar
!= InputData
->Key
.UnicodeChar
)) {
864 // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.
866 if (RegsiteredData
->KeyState
.KeyShiftState
!= 0 &&
867 RegsiteredData
->KeyState
.KeyShiftState
!= InputData
->KeyState
.KeyShiftState
) {
870 if (RegsiteredData
->KeyState
.KeyToggleState
!= 0 &&
871 RegsiteredData
->KeyState
.KeyToggleState
!= InputData
->KeyState
.KeyToggleState
) {
879 // Simple Text Input Ex protocol functions
882 Resets the input device hardware.
884 The Reset() function resets the input device hardware. As part
885 of initialization process, the firmware/device will make a quick
886 but reasonable attempt to verify that the device is functioning.
887 If the ExtendedVerification flag is TRUE the firmware may take
888 an extended amount of time to verify the device is operating on
889 reset. Otherwise the reset operation is to occur as quickly as
890 possible. The hardware verification process is not defined by
891 this specification and is left up to the platform firmware or
894 @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.
896 @param ExtendedVerification Indicates that the driver may perform a more exhaustive
897 verification operation of the device during reset.
899 @retval EFI_SUCCESS The device was reset.
900 @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.
906 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
907 IN BOOLEAN ExtendedVerification
911 USB_KB_DEV
*UsbKeyboardDevice
;
913 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
915 Status
= UsbKeyboardDevice
->SimpleInput
.Reset (&UsbKeyboardDevice
->SimpleInput
, ExtendedVerification
);
916 if (EFI_ERROR (Status
)) {
917 return EFI_DEVICE_ERROR
;
920 UsbKeyboardDevice
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
921 UsbKeyboardDevice
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
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
;
1001 UsbKeyboardDevice
->IsSupportPartialKey
= FALSE
;
1003 if ((*KeyToggleState
& EFI_SCROLL_LOCK_ACTIVE
) == EFI_SCROLL_LOCK_ACTIVE
) {
1004 UsbKeyboardDevice
->ScrollOn
= TRUE
;
1006 if ((*KeyToggleState
& EFI_NUM_LOCK_ACTIVE
) == EFI_NUM_LOCK_ACTIVE
) {
1007 UsbKeyboardDevice
->NumLockOn
= TRUE
;
1009 if ((*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == EFI_CAPS_LOCK_ACTIVE
) {
1010 UsbKeyboardDevice
->CapsOn
= TRUE
;
1012 if ((*KeyToggleState
& EFI_KEY_STATE_EXPOSED
) == EFI_KEY_STATE_EXPOSED
) {
1013 UsbKeyboardDevice
->IsSupportPartialKey
= TRUE
;
1016 SetKeyLED (UsbKeyboardDevice
);
1018 UsbKeyboardDevice
->KeyState
.KeyToggleState
= *KeyToggleState
;
1025 Register a notification function for a particular keystroke for the input device.
1027 @param This Protocol instance pointer.
1028 @param KeyData A pointer to a buffer that is filled in with the keystroke
1029 information data for the key that was pressed.
1030 @param KeyNotificationFunction Points to the function to be called when the key
1031 sequence is typed specified by KeyData.
1032 @param NotifyHandle Points to the unique handle assigned to the registered notification.
1034 @retval EFI_SUCCESS The notification function was registered successfully.
1035 @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.
1036 @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.
1041 USBKeyboardRegisterKeyNotify (
1042 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1043 IN EFI_KEY_DATA
*KeyData
,
1044 IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
1045 OUT EFI_HANDLE
*NotifyHandle
1048 USB_KB_DEV
*UsbKeyboardDevice
;
1049 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*NewNotify
;
1051 LIST_ENTRY
*NotifyList
;
1052 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1054 if (KeyData
== NULL
|| NotifyHandle
== NULL
|| KeyNotificationFunction
== NULL
) {
1055 return EFI_INVALID_PARAMETER
;
1058 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1061 // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.
1063 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1065 for (Link
= GetFirstNode (NotifyList
);
1066 !IsNull (NotifyList
, Link
);
1067 Link
= GetNextNode (NotifyList
, Link
)) {
1068 CurrentNotify
= CR (
1070 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1072 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1074 if (IsKeyRegistered (&CurrentNotify
->KeyData
, KeyData
)) {
1075 if (CurrentNotify
->KeyNotificationFn
== KeyNotificationFunction
) {
1076 *NotifyHandle
= CurrentNotify
->NotifyHandle
;
1083 // Allocate resource to save the notification function
1085 NewNotify
= (KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY
));
1086 if (NewNotify
== NULL
) {
1087 return EFI_OUT_OF_RESOURCES
;
1090 NewNotify
->Signature
= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
;
1091 NewNotify
->KeyNotificationFn
= KeyNotificationFunction
;
1092 NewNotify
->NotifyHandle
= (EFI_HANDLE
) NewNotify
;
1093 CopyMem (&NewNotify
->KeyData
, KeyData
, sizeof (EFI_KEY_DATA
));
1094 InsertTailList (&UsbKeyboardDevice
->NotifyList
, &NewNotify
->NotifyEntry
);
1097 *NotifyHandle
= NewNotify
->NotifyHandle
;
1104 Remove a registered notification function from a particular keystroke.
1106 @param This Protocol instance pointer.
1107 @param NotificationHandle The handle of the notification function being unregistered.
1109 @retval EFI_SUCCESS The notification function was unregistered successfully.
1110 @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid
1115 USBKeyboardUnregisterKeyNotify (
1116 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
1117 IN EFI_HANDLE NotificationHandle
1120 USB_KB_DEV
*UsbKeyboardDevice
;
1121 KEYBOARD_CONSOLE_IN_EX_NOTIFY
*CurrentNotify
;
1123 LIST_ENTRY
*NotifyList
;
1125 if (NotificationHandle
== NULL
) {
1126 return EFI_INVALID_PARAMETER
;
1129 if (((KEYBOARD_CONSOLE_IN_EX_NOTIFY
*) NotificationHandle
)->Signature
!= USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
) {
1130 return EFI_INVALID_PARAMETER
;
1133 UsbKeyboardDevice
= TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This
);
1136 // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.
1138 NotifyList
= &UsbKeyboardDevice
->NotifyList
;
1139 for (Link
= GetFirstNode (NotifyList
);
1140 !IsNull (NotifyList
, Link
);
1141 Link
= GetNextNode (NotifyList
, Link
)) {
1142 CurrentNotify
= CR (
1144 KEYBOARD_CONSOLE_IN_EX_NOTIFY
,
1146 USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE
1148 if (CurrentNotify
->NotifyHandle
== NotificationHandle
) {
1150 // Remove the notification function from NotifyList and free resources
1152 RemoveEntryList (&CurrentNotify
->NotifyEntry
);
1154 FreePool (CurrentNotify
);
1160 // Cannot find the matching entry in database.
1162 return EFI_INVALID_PARAMETER
;