/** @file\r
+ USB Keyboard Driver that manages USB keyboard and produces Simple Text Input\r
+ Protocol and Simple Text Input Ex Protocol.\r
\r
- USB Keyboard Driver that includes the implementation of interface.\r
-\r
-Copyright (c) 2004 - 2008, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "EfiKey.h"\r
#include "KeyBoard.h"\r
\r
-/**\r
- The Usb Keyboard Driver Entry Point.\r
-\r
- @param ImageHandle The driver image handle.\r
- @param SystemTable The system table.\r
-\r
- @return EFI_SUCCESS The component name protocol is installed.\r
- @return Others Failed to install.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-USBKeyboardDriverBindingEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- );\r
-\r
-/**\r
- Check whether USB keyboard driver support this device.\r
-\r
- @param This The USB keyboard driver binding protocol.\r
- @param Controller The controller handle to check.\r
- @param RemainingDevicePath The remaining device path.\r
-\r
- @retval EFI_SUCCESS The driver supports this controller.\r
- @retval EFI_UNSUPPORTED This device isn't supported.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-USBKeyboardDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- );\r
-\r
-/**\r
- Start running driver on the controller.\r
-\r
- @param This The USB keyboard driver binding instance.\r
- @param Controller The controller to check.\r
- @param RemainingDevicePath The remaining device patch.\r
-\r
- @retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.\r
- @return Other The keyboard driver doesn't support this controller.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-USBKeyboardDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
- );\r
-\r
-/**\r
- Stop handle the controller by this USB keyboard driver.\r
-\r
- @param This The USB keyboard driver binding protocol.\r
- @param Controller The controller to release.\r
- @param NumberOfChildren The number of handles in ChildHandleBuffer.\r
- @param ChildHandleBuffer The array of child handle.\r
-\r
- @retval EFI_SUCCESS The controller or children are stopped.\r
- @retval EFI_DEVICE_ERROR Failed to stop the driver.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-USBKeyboardDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE Controller,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
- );\r
-\r
-/**\r
- Reset Usb Keyboard.\r
-\r
- @param This The protocol instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL.\r
- @param ExtendedVerification Whether completely reset keyboard or not.\r
-\r
- @retval EFI_SUCCESS Reset keyboard successfully.\r
- @retval EFI_DEVICE_ERROR Reset keyboard failed.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-USBKeyboardReset (\r
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
- IN BOOLEAN ExtendedVerification\r
- );\r
-\r
-/**\r
- Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke() function.\r
-\r
- @param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.\r
- @param Key A pointer to a buffer that is filled in with the keystroke\r
- information for the key that was pressed.\r
-\r
- @retval EFI_SUCCESS Read key stroke successfully.\r
- @retval Other Read key stroke failed.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-USBKeyboardReadKeyStroke (\r
- IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
- OUT EFI_INPUT_KEY *Key\r
- );\r
-\r
-/**\r
- Handler function for WaitForKey event.\r
-\r
- @param Event Event to be signaled when a key is pressed.\r
- @param Context Points to USB_KB_DEV instance.\r
-\r
- @return None.\r
-**/\r
-VOID\r
-EFIAPI\r
-USBKeyboardWaitForKey (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- );\r
-\r
-/**\r
- Check whether there is key pending.\r
-\r
- @param UsbKeyboardDevice The USB_KB_DEV instance.\r
-\r
- @retval EFI_SUCCESS Have key pending to read.\r
- @retval Other Parse key failed.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-USBKeyboardCheckForKey (\r
- IN USB_KB_DEV *UsbKeyboardDevice\r
- );\r
-\r
-EFI_GUID gEfiUsbKeyboardDriverGuid = {\r
- 0xa05f5f78, 0xfb3, 0x4d10, {0x90, 0x90, 0xac, 0x4, 0x6e, 0xeb, 0x7c, 0x3c}\r
-};\r
-\r
-/**\r
- Free keyboard notify list.\r
-\r
- @param ListHead The list head.\r
-\r
- @retval EFI_SUCCESS Free the notify list successfully.\r
- @retval EFI_INVALID_PARAMETER ListHead is invalid.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-KbdFreeNotifyList (\r
- IN OUT LIST_ENTRY *ListHead\r
- ); \r
-\r
-/**\r
- Whether the pressed key matches a registered key or not.\r
-\r
- @param RegsiteredData A pointer to a buffer that is filled in with the keystroke\r
- state data for the key that was registered.\r
- @param InputData A pointer to a buffer that is filled in with the keystroke\r
- state data for the key that was pressed.\r
-\r
- @retval TRUE Key pressed matches a registered key.\r
- @retval FLASE Match failed.\r
-\r
-**/\r
-BOOLEAN\r
-EFIAPI\r
-IsKeyRegistered (\r
- IN EFI_KEY_DATA *RegsiteredData,\r
- IN EFI_KEY_DATA *InputData\r
- );\r
-\r
-\r
//\r
// USB Keyboard Driver Global Variables\r
//\r
};\r
\r
/**\r
- The Usb Keyboard Driver Entry Point.\r
+ Entrypoint of USB Keyboard Driver.\r
+\r
+ This function is the entrypoint of USB Keyboard Driver. It installs Driver Binding\r
+ Protocols together with Component Name Protocols.\r
\r
- @param ImageHandle The driver image handle.\r
- @param SystemTable The system table.\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
\r
- @return EFI_SUCCESS The component name protocol is installed.\r
- @return Others Failed to install.\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
\r
**/\r
EFI_STATUS\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- return EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gUsbKeyboardDriverBinding,\r
- ImageHandle,\r
- &gUsbKeyboardComponentName,\r
- &gUsbKeyboardComponentName2\r
- );\r
+ EFI_STATUS Status;\r
+\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gUsbKeyboardDriverBinding,\r
+ ImageHandle,\r
+ &gUsbKeyboardComponentName,\r
+ &gUsbKeyboardComponentName2\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
- Check whether USB keyboard driver support this device.\r
+ Check whether USB keyboard driver supports this device.\r
\r
@param This The USB keyboard driver binding protocol.\r
@param Controller The controller handle to check.\r
@param RemainingDevicePath The remaining device path.\r
\r
@retval EFI_SUCCESS The driver supports this controller.\r
- @retval EFI_UNSUPPORTED This device isn't supported.\r
+ @retval other This device isn't supported.\r
+\r
**/\r
EFI_STATUS\r
EFIAPI\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
- EFI_STATUS OpenStatus;\r
- EFI_USB_IO_PROTOCOL *UsbIo;\r
EFI_STATUS Status;\r
+ EFI_USB_IO_PROTOCOL *UsbIo;\r
\r
//\r
- // Check if USB_IO protocol is attached on the controller handle.\r
+ // Check if USB I/O Protocol is attached on the controller handle.\r
//\r
- OpenStatus = gBS->OpenProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- (VOID **) &UsbIo,\r
- This->DriverBindingHandle,\r
- Controller,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- if (EFI_ERROR (OpenStatus)) {\r
- return OpenStatus;\r
+ Status = gBS->OpenProtocol (\r
+ Controller,\r
+ &gEfiUsbIoProtocolGuid,\r
+ (VOID **) &UsbIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
}\r
\r
//\r
- // Use the USB I/O protocol interface to check whether the Controller is\r
- // the Keyboard controller that can be managed by this driver.\r
+ // Use the USB I/O Protocol interface to check whether Controller is\r
+ // a keyboard device that can be managed by this driver.\r
//\r
Status = EFI_SUCCESS;\r
\r
}\r
\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ Controller,\r
+ &gEfiUsbIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
\r
return Status;\r
}\r
\r
/**\r
- Start running driver on the controller.\r
+ Starts the keyboard device with this driver.\r
+\r
+ This function produces Simple Text Input Protocol and Simple Text Input Ex Protocol,\r
+ initializes the keyboard device, and submit Asynchronous Interrupt Transfer to manage\r
+ this keyboard device.\r
\r
@param This The USB keyboard driver binding instance.\r
- @param Controller The controller to check.\r
- @param RemainingDevicePath The remaining device patch.\r
+ @param Controller Handle of device to bind driver to.\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
\r
@retval EFI_SUCCESS The controller is controlled by the usb keyboard driver.\r
- @return Other The keyboard driver doesn't support this controller.\r
+ @retval EFI_UNSUPPORTED No interrupt endpoint can be found.\r
+ @retval Other This controller cannot be started.\r
\r
**/\r
EFI_STATUS\r
UINT8 PollingInterval;\r
UINT8 PacketSize;\r
BOOLEAN Found;\r
+ EFI_TPL OldTpl;\r
\r
- UsbKeyboardDevice = NULL;\r
- Found = FALSE;\r
-\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
//\r
- // Open USB_IO Protocol\r
+ // Open USB I/O Protocol\r
//\r
Status = gBS->OpenProtocol (\r
Controller,\r
EFI_OPEN_PROTOCOL_BY_DRIVER\r
);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto ErrorExit1;\r
}\r
\r
UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV));\r
- if (UsbKeyboardDevice == NULL) {\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ ASSERT (UsbKeyboardDevice != NULL);\r
+\r
//\r
// Get the Device Path Protocol on Controller's handle\r
//\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- gBS->FreePool (UsbKeyboardDevice);\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
+ goto ErrorExit;\r
}\r
//\r
- // Report that the usb keyboard is being enabled\r
+ // Report that the USB keyboard is being enabled\r
//\r
- KbdReportStatusCode (\r
- UsbKeyboardDevice->DevicePath,\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
EFI_PROGRESS_CODE,\r
- PcdGet32 (PcdStatusCodeValueKeyboardEnable)\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE),\r
+ UsbKeyboardDevice->DevicePath\r
);\r
\r
//\r
// This is pretty close to keyboard detection, so log progress\r
//\r
- KbdReportStatusCode (\r
- UsbKeyboardDevice->DevicePath,\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
EFI_PROGRESS_CODE,\r
- PcdGet32 (PcdStatusCodeValueKeyboardPresenceDetect)\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT),\r
+ UsbKeyboardDevice->DevicePath\r
);\r
\r
- //\r
- // Initialize UsbKeyboardDevice\r
- //\r
UsbKeyboardDevice->UsbIo = UsbIo;\r
\r
//\r
// Get interface & endpoint descriptor\r
//\r
UsbIo->UsbGetInterfaceDescriptor (\r
- UsbIo,\r
- &UsbKeyboardDevice->InterfaceDescriptor\r
- );\r
+ UsbIo,\r
+ &UsbKeyboardDevice->InterfaceDescriptor\r
+ );\r
\r
EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints;\r
\r
+ //\r
+ // Traverse endpoints to find interrupt endpoint IN\r
+ //\r
+ Found = FALSE;\r
for (Index = 0; Index < EndpointNumber; Index++) {\r
\r
UsbIo->UsbGetEndpointDescriptor (\r
- UsbIo,\r
- Index,\r
- &EndpointDescriptor\r
- );\r
+ UsbIo,\r
+ Index,\r
+ &EndpointDescriptor\r
+ );\r
\r
- if ((EndpointDescriptor.Attributes & 0x03) == 0x03) {\r
+ if (((EndpointDescriptor.Attributes & (BIT0 | BIT1)) == USB_ENDPOINT_INTERRUPT) &&\r
+ ((EndpointDescriptor.EndpointAddress & USB_ENDPOINT_DIR_IN) != 0)) {\r
//\r
// We only care interrupt endpoint here\r
//\r
CopyMem(&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor));\r
Found = TRUE;\r
+ break;\r
}\r
}\r
\r
if (!Found) {\r
//\r
+ // Report Status Code to indicate that there is no USB keyboard\r
+ //\r
+ REPORT_STATUS_CODE (\r
+ EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED)\r
+ );\r
+ //\r
// No interrupt endpoint found, then return unsupported.\r
//\r
- gBS->FreePool (UsbKeyboardDevice);\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return EFI_UNSUPPORTED;\r
+ Status = EFI_UNSUPPORTED;\r
+ goto ErrorExit;\r
}\r
\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+ EFI_PROGRESS_CODE,\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED),\r
+ UsbKeyboardDevice->DevicePath\r
+ );\r
+\r
UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE;\r
UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset;\r
UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke;\r
UsbKeyboardDevice->SimpleInputEx.ReadKeyStrokeEx = USBKeyboardReadKeyStrokeEx;\r
UsbKeyboardDevice->SimpleInputEx.SetState = USBKeyboardSetState;\r
UsbKeyboardDevice->SimpleInputEx.RegisterKeyNotify = USBKeyboardRegisterKeyNotify;\r
- UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify; \r
- \r
+ UsbKeyboardDevice->SimpleInputEx.UnregisterKeyNotify = USBKeyboardUnregisterKeyNotify;\r
+\r
InitializeListHead (&UsbKeyboardDevice->NotifyList);\r
- \r
+\r
Status = gBS->CreateEvent (\r
- EVT_NOTIFY_WAIT,\r
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
TPL_NOTIFY,\r
- USBKeyboardWaitForKey,\r
+ USBKeyboardTimerHandler,\r
UsbKeyboardDevice,\r
- &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)\r
+ &UsbKeyboardDevice->TimerEvent\r
);\r
-\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->SetTimer (UsbKeyboardDevice->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL);\r
+ }\r
if (EFI_ERROR (Status)) {\r
goto ErrorExit;\r
}\r
\r
- Status = InitKeyboardLayout (UsbKeyboardDevice);\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_WAIT,\r
+ TPL_NOTIFY,\r
+ USBKeyboardWaitForKey,\r
+ UsbKeyboardDevice,\r
+ &(UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx)\r
+ );\r
+\r
if (EFI_ERROR (Status)) {\r
goto ErrorExit;\r
}\r
UsbKeyboardDevice,\r
&(UsbKeyboardDevice->SimpleInput.WaitForKey)\r
);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorExit;\r
+ }\r
\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ KeyNotifyProcessHandler,\r
+ UsbKeyboardDevice,\r
+ &UsbKeyboardDevice->KeyNotifyProcessEvent\r
+ );\r
if (EFI_ERROR (Status)) {\r
- gBS->FreePool (UsbKeyboardDevice);\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
+ goto ErrorExit;\r
}\r
\r
//\r
- // Install simple txt in protocol interface\r
- // for the usb keyboard device.\r
- // Usb keyboard is a hot plug device, and expected to work immediately\r
- // when plugging into system, so a HotPlugDeviceGuid is installed onto\r
- // the usb keyboard device handle, to distinguish it from other conventional\r
- // console devices.\r
+ // Install Simple Text Input Protocol and Simple Text Input Ex Protocol\r
+ // for the USB keyboard device.\r
+ // USB keyboard is a hot plug device, and expected to work immediately\r
+ // when plugging into system, other conventional console devices could\r
+ // distinguish it by its device path.\r
//\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&Controller,\r
&UsbKeyboardDevice->SimpleInput,\r
&gEfiSimpleTextInputExProtocolGuid,\r
&UsbKeyboardDevice->SimpleInputEx,\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
- gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
- gBS->FreePool (UsbKeyboardDevice);\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
+ goto ErrorExit;\r
+ }\r
+\r
+ UsbKeyboardDevice->ControllerHandle = Controller;\r
+ Status = InitKeyboardLayout (UsbKeyboardDevice);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Controller,\r
+ &gEfiSimpleTextInProtocolGuid,\r
+ &UsbKeyboardDevice->SimpleInput,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ &UsbKeyboardDevice->SimpleInputEx,\r
+ NULL\r
+ );\r
+ goto ErrorExit;\r
}\r
\r
+\r
//\r
- // Reset USB Keyboard Device\r
+ // Reset USB Keyboard Device exhaustively.\r
//\r
- Status = UsbKeyboardDevice->SimpleInput.Reset (\r
- &UsbKeyboardDevice->SimpleInput,\r
+ Status = UsbKeyboardDevice->SimpleInputEx.Reset (\r
+ &UsbKeyboardDevice->SimpleInputEx,\r
TRUE\r
);\r
if (EFI_ERROR (Status)) {\r
&UsbKeyboardDevice->SimpleInput,\r
&gEfiSimpleTextInputExProtocolGuid,\r
&UsbKeyboardDevice->SimpleInputEx,\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
NULL\r
);\r
- gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
- gBS->FreePool (UsbKeyboardDevice);\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
+ goto ErrorExit;\r
}\r
+\r
//\r
- // submit async interrupt transfer\r
+ // Submit Asynchronous Interrupt Transfer to manage this device.\r
//\r
EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress;\r
PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval;\r
);\r
\r
if (EFI_ERROR (Status)) {\r
-\r
gBS->UninstallMultipleProtocolInterfaces (\r
Controller,\r
&gEfiSimpleTextInProtocolGuid,\r
&UsbKeyboardDevice->SimpleInput,\r
&gEfiSimpleTextInputExProtocolGuid,\r
&UsbKeyboardDevice->SimpleInputEx,\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
NULL\r
);\r
- gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
- gBS->FreePool (UsbKeyboardDevice);\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
- return Status;\r
+ goto ErrorExit;\r
}\r
\r
UsbKeyboardDevice->ControllerNameTable = NULL;\r
FALSE\r
);\r
\r
-\r
+ gBS->RestoreTPL (OldTpl);\r
return EFI_SUCCESS;\r
\r
+//\r
+// Error handler\r
+//\r
ErrorExit:\r
if (UsbKeyboardDevice != NULL) {\r
+ if (UsbKeyboardDevice->TimerEvent != NULL) {\r
+ gBS->CloseEvent (UsbKeyboardDevice->TimerEvent);\r
+ }\r
if (UsbKeyboardDevice->SimpleInput.WaitForKey != NULL) {\r
gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
}\r
if (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx != NULL) {\r
gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
}\r
- KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); \r
- gBS->FreePool (UsbKeyboardDevice);\r
+ if (UsbKeyboardDevice->KeyNotifyProcessEvent != NULL) {\r
+ gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);\r
+ }\r
+ if (UsbKeyboardDevice->KeyboardLayoutEvent != NULL) {\r
+ ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
+ gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
+ }\r
+ FreePool (UsbKeyboardDevice);\r
UsbKeyboardDevice = NULL;\r
}\r
gBS->CloseProtocol (\r
This->DriverBindingHandle,\r
Controller\r
);\r
+\r
+ErrorExit1:\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
return Status;\r
\r
}\r
\r
\r
/**\r
- Stop handle the controller by this USB keyboard driver.\r
+ Stop the USB keyboard device handled by this driver.\r
\r
@param This The USB keyboard driver binding protocol.\r
@param Controller The controller to release.\r
@param NumberOfChildren The number of handles in ChildHandleBuffer.\r
@param ChildHandleBuffer The array of child handle.\r
\r
- @retval EFI_SUCCESS The controller or children are stopped.\r
- @retval EFI_DEVICE_ERROR Failed to stop the driver.\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_UNSUPPORTED Simple Text In Protocol or Simple Text In Ex Protocol\r
+ is not installed on Controller.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+ @retval Others Fail to uninstall protocols attached on the device.\r
\r
**/\r
EFI_STATUS\r
IN EFI_HANDLE *ChildHandleBuffer\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleInput;\r
- USB_KB_DEV *UsbKeyboardDevice;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
\r
Status = gBS->OpenProtocol (\r
Controller,\r
if (EFI_ERROR (Status)) {\r
return EFI_UNSUPPORTED;\r
}\r
+\r
Status = gBS->OpenProtocol (\r
Controller,\r
&gEfiSimpleTextInputExProtocolGuid,\r
if (EFI_ERROR (Status)) {\r
return EFI_UNSUPPORTED;\r
}\r
- //\r
- // Get USB_KB_DEV instance.\r
- //\r
- UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);\r
\r
- gBS->CloseProtocol (\r
- Controller,\r
- &gEfiSimpleTextInProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput);\r
\r
//\r
- // Uninstall the Asyn Interrupt Transfer from this device\r
- // will disable the key data input from this device\r
+ // The key data input from this device will be disabled.\r
//\r
- KbdReportStatusCode (\r
- UsbKeyboardDevice->DevicePath,\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
EFI_PROGRESS_CODE,\r
- PcdGet32 (PcdStatusCodeValueKeyboardDisable)\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE),\r
+ UsbKeyboardDevice->DevicePath\r
);\r
\r
//\r
- // Destroy asynchronous interrupt transfer\r
+ // Delete the Asynchronous Interrupt Transfer from this device\r
//\r
UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer (\r
UsbKeyboardDevice->UsbIo,\r
);\r
\r
gBS->CloseProtocol (\r
- Controller,\r
- &gEfiUsbIoProtocolGuid,\r
- This->DriverBindingHandle,\r
- Controller\r
- );\r
+ Controller,\r
+ &gEfiUsbIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
\r
Status = gBS->UninstallMultipleProtocolInterfaces (\r
Controller,\r
&UsbKeyboardDevice->SimpleInput,\r
&gEfiSimpleTextInputExProtocolGuid,\r
&UsbKeyboardDevice->SimpleInputEx,\r
- &gEfiHotPlugDeviceGuid,\r
- NULL,\r
NULL\r
);\r
//\r
- // free all the resources.\r
+ // Free all resources.\r
//\r
+ gBS->CloseEvent (UsbKeyboardDevice->TimerEvent);\r
gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer);\r
gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent);\r
- gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey);\r
- gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx); \r
- KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList); \r
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey);\r
+ gBS->CloseEvent (UsbKeyboardDevice->SimpleInputEx.WaitForKeyEx);\r
+ gBS->CloseEvent (UsbKeyboardDevice->KeyNotifyProcessEvent);\r
+ KbdFreeNotifyList (&UsbKeyboardDevice->NotifyList);\r
\r
ReleaseKeyboardLayoutResources (UsbKeyboardDevice);\r
gBS->CloseEvent (UsbKeyboardDevice->KeyboardLayoutEvent);\r
FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable);\r
}\r
\r
- gBS->FreePool (UsbKeyboardDevice);\r
+ DestroyQueue (&UsbKeyboardDevice->UsbKeyQueue);\r
+ DestroyQueue (&UsbKeyboardDevice->EfiKeyQueue);\r
+ DestroyQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify);\r
\r
- return Status;\r
+ FreePool (UsbKeyboardDevice);\r
\r
+ return Status;\r
}\r
\r
/**\r
- Reads the next keystroke from the input device. The WaitForKey Event can\r
- be used to test for existance of a keystroke via WaitForEvent () call.\r
+ Internal function to read the next keystroke from the keyboard buffer.\r
\r
- @param UsbKeyboardDevice Usb keyboard's private structure.\r
- @param KeyData A pointer to a buffer that is filled in with the keystroke\r
- state data for the key that was pressed.\r
+ @param UsbKeyboardDevice USB keyboard's private structure.\r
+ @param KeyData A pointer to buffer to hold the keystroke\r
+ data for the key that was pressed.\r
\r
- @return EFI_SUCCESS The keystroke information was returned.\r
- @return EFI_NOT_READY There was no keystroke data availiable.\r
- @return EFI_DEVICE_ERROR The keystroke information was not returned due to\r
+ @retval EFI_SUCCESS The keystroke information was returned.\r
+ @retval EFI_NOT_READY There was no keystroke data availiable.\r
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
hardware errors.\r
- @return EFI_INVALID_PARAMETER KeyData is NULL.\r
+ @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
+ @retval Others Fail to translate keycode into EFI_INPUT_KEY\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
USBKeyboardReadKeyStrokeWorker (\r
- IN USB_KB_DEV *UsbKeyboardDevice,\r
- OUT EFI_KEY_DATA *KeyData\r
+ IN OUT USB_KB_DEV *UsbKeyboardDevice,\r
+ OUT EFI_KEY_DATA *KeyData\r
)\r
{\r
-\r
- EFI_STATUS Status;\r
- UINT8 KeyChar; \r
- LIST_ENTRY *Link;\r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
- EFI_KEY_DATA OriginalKeyData;\r
-\r
if (KeyData == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- //\r
- // if there is no saved ASCII byte, fetch it\r
- // by calling USBKeyboardCheckForKey().\r
- //\r
- if (UsbKeyboardDevice->CurKeyChar == 0) {\r
- Status = USBKeyboardCheckForKey (UsbKeyboardDevice);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ if (IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {\r
+ ZeroMem (&KeyData->Key, sizeof (KeyData->Key));\r
+ InitializeKeyState (UsbKeyboardDevice, &KeyData->KeyState);\r
+ return EFI_NOT_READY;\r
}\r
\r
- KeyData->Key.UnicodeChar = 0;\r
- KeyData->Key.ScanCode = SCAN_NULL;\r
-\r
- KeyChar = UsbKeyboardDevice->CurKeyChar;\r
-\r
- UsbKeyboardDevice->CurKeyChar = 0;\r
-\r
- //\r
- // Translate saved ASCII byte into EFI_INPUT_KEY\r
- //\r
- Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, &KeyData->Key);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- CopyMem (&KeyData->KeyState, &UsbKeyboardDevice->KeyState, sizeof (KeyData->KeyState));\r
- \r
- UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
- UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
-\r
- //\r
- //Switch the control value to their original characters. In USBKeyCodeToEFIScanCode() the CTRL-Alpha characters have been switched to \r
- // their corresponding control value (ctrl-a = 0x0001 through ctrl-Z = 0x001A), here switch them back for notification function.\r
- //\r
- CopyMem (&OriginalKeyData, KeyData, sizeof (EFI_KEY_DATA));\r
- if (UsbKeyboardDevice->CtrlOn != 0) {\r
- if (OriginalKeyData.Key.UnicodeChar >= 0x01 && OriginalKeyData.Key.UnicodeChar <= 0x1A) {\r
- if (UsbKeyboardDevice->CapsOn != 0) {\r
- OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'A' - 1);\r
- } else {\r
- OriginalKeyData.Key.UnicodeChar = (CHAR16)(OriginalKeyData.Key.UnicodeChar + 'a' - 1);\r
- } \r
- }\r
- }\r
- \r
- //\r
- // Invoke notification functions if exist\r
- //\r
- for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
- CurrentNotify = CR (\r
- Link, \r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
- NotifyEntry, \r
- USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
- );\r
- if (IsKeyRegistered (&CurrentNotify->KeyData, &OriginalKeyData)) { \r
- CurrentNotify->KeyNotificationFn (&OriginalKeyData);\r
- }\r
- }\r
+ Dequeue (&UsbKeyboardDevice->EfiKeyQueue, KeyData, sizeof (*KeyData));\r
\r
return EFI_SUCCESS;\r
- \r
}\r
\r
/**\r
- Reset Usb Keyboard.\r
+ Reset the input device and optionally run diagnostics\r
+\r
+ There are 2 types of reset for USB keyboard.\r
+ For non-exhaustive reset, only keyboard buffer is cleared.\r
+ For exhaustive reset, in addition to clearance of keyboard buffer, the hardware status\r
+ is also re-initialized.\r
\r
- @param This The protocol instance of EFI_SIMPLE_TEXT_INPUT_PROTOCOL.\r
- @param ExtendedVerification Whether completely reset keyboard or not.\r
+ @param This Protocol instance pointer.\r
+ @param ExtendedVerification Driver may perform diagnostics on reset.\r
\r
- @retval EFI_SUCCESS Reset keyboard successfully.\r
- @retval EFI_DEVICE_ERROR Reset keyboard failed.\r
+ @retval EFI_SUCCESS The device was reset.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardReset (\r
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
- IN BOOLEAN ExtendedVerification\r
+ IN BOOLEAN ExtendedVerification\r
)\r
{\r
EFI_STATUS Status;\r
\r
UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
\r
- KbdReportStatusCode (\r
- UsbKeyboardDevice->DevicePath,\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
EFI_PROGRESS_CODE,\r
- PcdGet32 (PcdStatusCodeValueKeyboardReset)\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET),\r
+ UsbKeyboardDevice->DevicePath\r
);\r
\r
//\r
- // Non Exhaustive reset:\r
+ // Non-exhaustive reset:\r
// only reset private data structures.\r
//\r
if (!ExtendedVerification) {\r
- //\r
- // Clear the key buffer of this Usb keyboard\r
- //\r
- KbdReportStatusCode (\r
- UsbKeyboardDevice->DevicePath,\r
+ REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
EFI_PROGRESS_CODE,\r
- PcdGet32 (PcdStatusCodeValueKeyboardClearBuffer)\r
+ (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER),\r
+ UsbKeyboardDevice->DevicePath\r
);\r
+ //\r
+ // Clear the key buffer of this USB keyboard\r
+ //\r
+ InitQueue (&UsbKeyboardDevice->UsbKeyQueue, sizeof (USB_KEY));\r
+ InitQueue (&UsbKeyboardDevice->EfiKeyQueue, sizeof (EFI_KEY_DATA));\r
+ InitQueue (&UsbKeyboardDevice->EfiKeyQueueForNotify, sizeof (EFI_KEY_DATA));\r
\r
- InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer));\r
- UsbKeyboardDevice->CurKeyChar = 0;\r
return EFI_SUCCESS;\r
}\r
\r
//\r
// Exhaustive reset\r
//\r
- Status = InitUSBKeyboard (UsbKeyboardDevice);\r
- UsbKeyboardDevice->CurKeyChar = 0;\r
+ Status = InitUSBKeyboard (UsbKeyboardDevice);\r
if (EFI_ERROR (Status)) {\r
return EFI_DEVICE_ERROR;\r
}\r
\r
\r
/**\r
- Implements EFI_SIMPLE_TEXT_INPUT_PROTOCOL.ReadKeyStroke() function.\r
+ Reads the next keystroke from the input device.\r
\r
@param This The EFI_SIMPLE_TEXT_INPUT_PROTOCOL instance.\r
@param Key A pointer to a buffer that is filled in with the keystroke\r
information for the key that was pressed.\r
\r
- @retval EFI_SUCCESS Read key stroke successfully.\r
- @retval Other Read key stroke failed.\r
+ @retval EFI_SUCCESS The keystroke information was returned.\r
+ @retval EFI_NOT_READY There was no keystroke data availiable.\r
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
+ hardware errors.\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardReadKeyStroke (\r
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
- OUT EFI_INPUT_KEY *Key\r
+ OUT EFI_INPUT_KEY *Key\r
)\r
{\r
USB_KB_DEV *UsbKeyboardDevice;\r
\r
UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This);\r
\r
- Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
-\r
- return EFI_SUCCESS;\r
+ //\r
+ // Considering if the partial keystroke is enabled, there maybe a partial\r
+ // keystroke in the queue, so here skip the partial keystroke and get the\r
+ // next key from the queue\r
+ //\r
+ while (1) {\r
+ Status = USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, &KeyData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // SimpleTextIn Protocol doesn't support partial keystroke;\r
+ //\r
+ if (KeyData.Key.ScanCode == CHAR_NULL && KeyData.Key.UnicodeChar == SCAN_NULL) {\r
+ continue;\r
+ }\r
+ //\r
+ // Translate the CTRL-Alpha characters to their corresponding control value\r
+ // (ctrl-a = 0x0001 through ctrl-Z = 0x001A)\r
+ //\r
+ if ((KeyData.KeyState.KeyShiftState & (EFI_LEFT_CONTROL_PRESSED | EFI_RIGHT_CONTROL_PRESSED)) != 0) {\r
+ if (KeyData.Key.UnicodeChar >= L'a' && KeyData.Key.UnicodeChar <= L'z') {\r
+ KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'a' + 1);\r
+ } else if (KeyData.Key.UnicodeChar >= L'A' && KeyData.Key.UnicodeChar <= L'Z') {\r
+ KeyData.Key.UnicodeChar = (CHAR16) (KeyData.Key.UnicodeChar - L'A' + 1);\r
+ }\r
+ }\r
\r
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+ return EFI_SUCCESS;\r
+ }\r
}\r
\r
\r
/**\r
- Handler function for WaitForKey event.\r
+ Event notification function registered for EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.WaitForKeyEx\r
+ and EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey.\r
\r
@param Event Event to be signaled when a key is pressed.\r
@param Context Points to USB_KB_DEV instance.\r
\r
- @return None.\r
**/\r
VOID\r
EFIAPI\r
)\r
{\r
USB_KB_DEV *UsbKeyboardDevice;\r
+ EFI_KEY_DATA KeyData;\r
+ EFI_TPL OldTpl;\r
\r
UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
\r
- if (UsbKeyboardDevice->CurKeyChar == 0) {\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
\r
- if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) {\r
- return ;\r
+ //\r
+ // WaitforKey doesn't suppor the partial key.\r
+ // Considering if the partial keystroke is enabled, there maybe a partial\r
+ // keystroke in the queue, so here skip the partial keystroke and get the\r
+ // next key from the queue\r
+ //\r
+ while (!IsQueueEmpty (&UsbKeyboardDevice->EfiKeyQueue)) {\r
+ //\r
+ // If there is pending key, signal the event.\r
+ //\r
+ CopyMem (\r
+ &KeyData,\r
+ UsbKeyboardDevice->EfiKeyQueue.Buffer[UsbKeyboardDevice->EfiKeyQueue.Head],\r
+ sizeof (EFI_KEY_DATA)\r
+ );\r
+ if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {\r
+ Dequeue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (EFI_KEY_DATA));\r
+ continue;\r
}\r
+ gBS->SignalEvent (Event);\r
+ break;\r
}\r
//\r
- // If has key pending, signal the event.\r
+ // Leave critical section and return\r
//\r
- gBS->SignalEvent (Event);\r
+ gBS->RestoreTPL (OldTpl);\r
}\r
\r
-\r
/**\r
- Check whether there is key pending.\r
-\r
- @param UsbKeyboardDevice The USB_KB_DEV instance.\r
-\r
- @retval EFI_SUCCESS Have key pending to read.\r
- @retval Other Parse key failed.\r
+ Timer handler to convert the key from USB.\r
\r
+ @param Event Indicates the event that invoke this function.\r
+ @param Context Indicates the calling context.\r
**/\r
-EFI_STATUS\r
+VOID\r
EFIAPI\r
-USBKeyboardCheckForKey (\r
- IN USB_KB_DEV *UsbKeyboardDevice\r
+USBKeyboardTimerHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT8 KeyChar;\r
+ EFI_STATUS Status;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ UINT8 KeyCode;\r
+ EFI_KEY_DATA KeyData;\r
+\r
+ UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
\r
//\r
- // Fetch raw data from the USB keyboard input,\r
- // and translate it into ASCII data.\r
+ // Fetch raw data from the USB keyboard buffer,\r
+ // and translate it into USB keycode.\r
//\r
- Status = USBParseKey (UsbKeyboardDevice, &KeyChar);\r
+ Status = USBParseKey (UsbKeyboardDevice, &KeyCode);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ return ;\r
}\r
\r
- UsbKeyboardDevice->CurKeyChar = KeyChar;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Report Status Code in Usb Keyboard Driver.\r
-\r
- @param DevicePath Use this to get Device Path.\r
- @param CodeType Status Code Type.\r
- @param CodeValue Status Code Value.\r
-\r
- @return None.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-KbdReportStatusCode (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- IN EFI_STATUS_CODE_TYPE CodeType,\r
- IN EFI_STATUS_CODE_VALUE Value\r
- )\r
-{\r
+ //\r
+ // Translate saved USB keycode into EFI_INPUT_KEY\r
+ //\r
+ Status = UsbKeyCodeToEfiInputKey (UsbKeyboardDevice, KeyCode, &KeyData);\r
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
\r
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
- CodeType,\r
- Value,\r
- DevicePath\r
- );\r
+ //\r
+ // Insert to the EFI Key queue\r
+ //\r
+ Enqueue (&UsbKeyboardDevice->EfiKeyQueue, &KeyData, sizeof (KeyData));\r
}\r
\r
/**\r
Free keyboard notify list.\r
\r
- @param ListHead The list head.\r
+ @param NotifyList The keyboard notify list to free.\r
\r
@retval EFI_SUCCESS Free the notify list successfully.\r
- @retval EFI_INVALID_PARAMETER ListHead is invalid.\r
+ @retval EFI_INVALID_PARAMETER NotifyList is NULL.\r
\r
**/\r
EFI_STATUS\r
-EFIAPI\r
KbdFreeNotifyList (\r
- IN OUT LIST_ENTRY *ListHead\r
+ IN OUT LIST_ENTRY *NotifyList\r
)\r
{\r
KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;\r
+ LIST_ENTRY *Link;\r
\r
- if (ListHead == NULL) {\r
+ if (NotifyList == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- while (!IsListEmpty (ListHead)) {\r
- NotifyNode = CR (\r
- ListHead->ForwardLink, \r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
- NotifyEntry, \r
- USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
- );\r
- RemoveEntryList (ListHead->ForwardLink);\r
- gBS->FreePool (NotifyNode);\r
+ while (!IsListEmpty (NotifyList)) {\r
+ Link = GetFirstNode (NotifyList);\r
+ NotifyNode = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
+ RemoveEntryList (Link);\r
+ FreePool (NotifyNode);\r
}\r
- \r
+\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Whether the pressed key matches a registered key or not.\r
+ Check whether the pressed key matches a registered key or not.\r
\r
- @param RegsiteredData A pointer to a buffer that is filled in with the keystroke\r
- state data for the key that was registered.\r
- @param InputData A pointer to a buffer that is filled in with the keystroke\r
- state data for the key that was pressed.\r
+ @param RegsiteredData A pointer to keystroke data for the key that was registered.\r
+ @param InputData A pointer to keystroke data for the key that was pressed.\r
\r
@retval TRUE Key pressed matches a registered key.\r
- @retval FLASE Match failed.\r
+ @retval FLASE Key pressed does not matches a registered key.\r
\r
**/\r
BOOLEAN\r
-EFIAPI\r
IsKeyRegistered (\r
IN EFI_KEY_DATA *RegsiteredData,\r
IN EFI_KEY_DATA *InputData\r
)\r
{\r
ASSERT (RegsiteredData != NULL && InputData != NULL);\r
- \r
+\r
if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||\r
(RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {\r
- return FALSE; \r
- } \r
- \r
+ return FALSE;\r
+ }\r
+\r
//\r
// Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.\r
//\r
if (RegsiteredData->KeyState.KeyShiftState != 0 &&\r
RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {\r
- return FALSE; \r
- } \r
+ return FALSE;\r
+ }\r
if (RegsiteredData->KeyState.KeyToggleState != 0 &&\r
RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {\r
- return FALSE; \r
- } \r
- \r
- return TRUE;\r
+ return FALSE;\r
+ }\r
\r
+ return TRUE;\r
}\r
\r
//\r
-// Simple Text Input Ex protocol functions \r
+// Simple Text Input Ex protocol functions\r
//\r
/**\r
- The extension routine to reset the input device.\r
+ Resets the input device hardware.\r
+\r
+ The Reset() function resets the input device hardware. As part\r
+ of initialization process, the firmware/device will make a quick\r
+ but reasonable attempt to verify that the device is functioning.\r
+ If the ExtendedVerification flag is TRUE the firmware may take\r
+ an extended amount of time to verify the device is operating on\r
+ reset. Otherwise the reset operation is to occur as quickly as\r
+ possible. The hardware verification process is not defined by\r
+ this specification and is left up to the platform firmware or\r
+ driver to implement.\r
\r
- @param This Protocol instance pointer.\r
- @param ExtendedVerification Driver may perform diagnostics on reset.\r
+ @param This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.\r
\r
- @retval EFI_SUCCESS The device was reset.\r
- @retval EFI_DEVICE_ERROR The device is not functioning properly and could\r
- not be reset.\r
+ @param ExtendedVerification Indicates that the driver may perform a more exhaustive\r
+ verification operation of the device during reset.\r
+\r
+ @retval EFI_SUCCESS The device was reset.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.\r
\r
**/\r
EFI_STATUS\r
{\r
EFI_STATUS Status;\r
USB_KB_DEV *UsbKeyboardDevice;\r
- EFI_TPL OldTpl;\r
- \r
\r
UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
\r
return EFI_DEVICE_ERROR;\r
}\r
\r
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
UsbKeyboardDevice->KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;\r
UsbKeyboardDevice->KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID;\r
- gBS->RestoreTPL (OldTpl);\r
\r
return EFI_SUCCESS;\r
\r
}\r
\r
/**\r
- Reads the next keystroke from the input device. The WaitForKey Event can\r
- be used to test for existance of a keystroke via WaitForEvent () call.\r
+ Reads the next keystroke from the input device.\r
\r
- @param This Protocol instance pointer.\r
- @param KeyData A pointer to a buffer that is filled in with the keystroke\r
- state data for the key that was pressed.\r
+ @param This Protocol instance pointer.\r
+ @param KeyData A pointer to a buffer that is filled in with the keystroke\r
+ state data for the key that was pressed.\r
\r
- @return EFI_SUCCESS The keystroke information was returned successfully.\r
- @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
- @retval Other Read key stroke information failed.\r
+ @retval EFI_SUCCESS The keystroke information was returned.\r
+ @retval EFI_NOT_READY There was no keystroke data available.\r
+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to\r
+ hardware errors.\r
+ @retval EFI_INVALID_PARAMETER KeyData is NULL.\r
\r
**/\r
EFI_STATUS\r
UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
\r
return USBKeyboardReadKeyStrokeWorker (UsbKeyboardDevice, KeyData);\r
- \r
+\r
}\r
\r
/**\r
@param KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the\r
state for the input device.\r
\r
- @retval EFI_SUCCESS The device state was set successfully.\r
- @retval EFI_UNSUPPORTED The device does not have the ability to set its state.\r
+ @retval EFI_SUCCESS The device state was set appropriately.\r
+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could\r
+ not have the setting adjusted.\r
+ @retval EFI_UNSUPPORTED The device does not support the ability to have its state set.\r
@retval EFI_INVALID_PARAMETER KeyToggleState is NULL.\r
\r
**/\r
// Update the status light\r
//\r
\r
- UsbKeyboardDevice->ScrollOn = 0;\r
- UsbKeyboardDevice->NumLockOn = 0;\r
- UsbKeyboardDevice->CapsOn = 0;\r
- \r
+ UsbKeyboardDevice->ScrollOn = FALSE;\r
+ UsbKeyboardDevice->NumLockOn = FALSE;\r
+ UsbKeyboardDevice->CapsOn = FALSE;\r
+ UsbKeyboardDevice->IsSupportPartialKey = FALSE;\r
+\r
if ((*KeyToggleState & EFI_SCROLL_LOCK_ACTIVE) == EFI_SCROLL_LOCK_ACTIVE) {\r
- UsbKeyboardDevice->ScrollOn = 1;\r
+ UsbKeyboardDevice->ScrollOn = TRUE;\r
}\r
if ((*KeyToggleState & EFI_NUM_LOCK_ACTIVE) == EFI_NUM_LOCK_ACTIVE) {\r
- UsbKeyboardDevice->NumLockOn = 1;\r
+ UsbKeyboardDevice->NumLockOn = TRUE;\r
}\r
if ((*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE) {\r
- UsbKeyboardDevice->CapsOn = 1;\r
+ UsbKeyboardDevice->CapsOn = TRUE;\r
+ }\r
+ if ((*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED) {\r
+ UsbKeyboardDevice->IsSupportPartialKey = TRUE;\r
}\r
\r
SetKeyLED (UsbKeyboardDevice);\r
UsbKeyboardDevice->KeyState.KeyToggleState = *KeyToggleState;\r
\r
return EFI_SUCCESS;\r
- \r
+\r
}\r
\r
/**\r
Register a notification function for a particular keystroke for the input device.\r
\r
@param This Protocol instance pointer.\r
- @param KeyData A pointer to a buffer that is filled in with the keystroke\r
- information data for the key that was pressed.\r
+ @param KeyData A pointer to a buffer that is filled in with\r
+ the keystroke information for the key that was\r
+ pressed. If KeyData.Key, KeyData.KeyState.KeyToggleState\r
+ and KeyData.KeyState.KeyShiftState are 0, then any incomplete\r
+ keystroke will trigger a notification of the KeyNotificationFunction.\r
@param KeyNotificationFunction Points to the function to be called when the key\r
- sequence is typed specified by KeyData.\r
+ sequence is typed specified by KeyData. This notification function\r
+ should be called at <=TPL_CALLBACK.\r
@param NotifyHandle Points to the unique handle assigned to the registered notification.\r
\r
@retval EFI_SUCCESS The notification function was registered successfully.\r
- @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data structures.\r
- @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle is NULL.\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.\r
+ @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.\r
\r
**/\r
EFI_STATUS\r
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
IN EFI_KEY_DATA *KeyData,\r
IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,\r
- OUT EFI_HANDLE *NotifyHandle\r
+ OUT VOID **NotifyHandle\r
)\r
{\r
USB_KB_DEV *UsbKeyboardDevice;\r
- EFI_STATUS Status;\r
KEYBOARD_CONSOLE_IN_EX_NOTIFY *NewNotify;\r
LIST_ENTRY *Link;\r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify; \r
+ LIST_ENTRY *NotifyList;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
\r
if (KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {\r
return EFI_INVALID_PARAMETER;\r
//\r
// Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
//\r
- for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
+ NotifyList = &UsbKeyboardDevice->NotifyList;\r
+\r
+ for (Link = GetFirstNode (NotifyList);\r
+ !IsNull (NotifyList, Link);\r
+ Link = GetNextNode (NotifyList, Link)) {\r
CurrentNotify = CR (\r
- Link, \r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
- NotifyEntry, \r
+ Link,\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+ NotifyEntry,\r
USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
);\r
- if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { \r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {\r
if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {\r
- *NotifyHandle = CurrentNotify->NotifyHandle; \r
+ *NotifyHandle = CurrentNotify;\r
return EFI_SUCCESS;\r
}\r
}\r
}\r
- \r
+\r
//\r
// Allocate resource to save the notification function\r
- // \r
+ //\r
NewNotify = (KEYBOARD_CONSOLE_IN_EX_NOTIFY *) AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_EX_NOTIFY));\r
if (NewNotify == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE; \r
+ NewNotify->Signature = USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE;\r
NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
InsertTailList (&UsbKeyboardDevice->NotifyList, &NewNotify->NotifyEntry);\r
\r
- //\r
- // Use gSimpleTextInExNotifyGuid to get a valid EFI_HANDLE\r
- // \r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &NewNotify->NotifyHandle,\r
- &gSimpleTextInExNotifyGuid,\r
- NULL,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- \r
- *NotifyHandle = NewNotify->NotifyHandle; \r
- \r
+\r
+ *NotifyHandle = NewNotify;\r
+\r
return EFI_SUCCESS;\r
- \r
+\r
}\r
\r
/**\r
@param NotificationHandle The handle of the notification function being unregistered.\r
\r
@retval EFI_SUCCESS The notification function was unregistered successfully.\r
- @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid or opening gSimpleTextInExNotifyGuid\r
- on NotificationHandle fails.\r
- @retval EFI_NOT_FOUND Can not find the matching entry in database.\r
+ @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
USBKeyboardUnregisterKeyNotify (\r
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
- IN EFI_HANDLE NotificationHandle\r
+ IN VOID *NotificationHandle\r
)\r
{\r
USB_KB_DEV *UsbKeyboardDevice;\r
- EFI_STATUS Status;\r
KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
LIST_ENTRY *Link;\r
+ LIST_ENTRY *NotifyList;\r
\r
if (NotificationHandle == NULL) {\r
return EFI_INVALID_PARAMETER;\r
- } \r
- \r
- UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
- \r
- Status = gBS->OpenProtocol (\r
- NotificationHandle,\r
- &gSimpleTextInExNotifyGuid,\r
- NULL,\r
- NULL,\r
- NULL,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return EFI_INVALID_PARAMETER;\r
}\r
\r
- for (Link = UsbKeyboardDevice->NotifyList.ForwardLink; Link != &UsbKeyboardDevice->NotifyList; Link = Link->ForwardLink) {\r
+ UsbKeyboardDevice = TEXT_INPUT_EX_USB_KB_DEV_FROM_THIS (This);\r
+\r
+ //\r
+ // Traverse notify list of USB keyboard and remove the entry of NotificationHandle.\r
+ //\r
+ NotifyList = &UsbKeyboardDevice->NotifyList;\r
+ for (Link = GetFirstNode (NotifyList);\r
+ !IsNull (NotifyList, Link);\r
+ Link = GetNextNode (NotifyList, Link)) {\r
CurrentNotify = CR (\r
- Link, \r
- KEYBOARD_CONSOLE_IN_EX_NOTIFY, \r
- NotifyEntry, \r
+ Link,\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY,\r
+ NotifyEntry,\r
USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE\r
- ); \r
- if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ );\r
+ if (CurrentNotify == NotificationHandle) {\r
//\r
// Remove the notification function from NotifyList and free resources\r
//\r
- RemoveEntryList (&CurrentNotify->NotifyEntry); \r
- Status = gBS->UninstallMultipleProtocolInterfaces (\r
- CurrentNotify->NotifyHandle,\r
- &gSimpleTextInExNotifyGuid,\r
- NULL,\r
- NULL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- gBS->FreePool (CurrentNotify); \r
+ RemoveEntryList (&CurrentNotify->NotifyEntry);\r
+\r
+ FreePool (CurrentNotify);\r
return EFI_SUCCESS;\r
}\r
}\r
\r
- return EFI_NOT_FOUND; \r
+ //\r
+ // Cannot find the matching entry in database.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+}\r
+\r
+/**\r
+ Process key notify.\r
+\r
+ @param Event Indicates the event that invoke this function.\r
+ @param Context Indicates the calling context.\r
+**/\r
+VOID\r
+EFIAPI\r
+KeyNotifyProcessHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ USB_KB_DEV *UsbKeyboardDevice;\r
+ EFI_KEY_DATA KeyData;\r
+ LIST_ENTRY *Link;\r
+ LIST_ENTRY *NotifyList;\r
+ KEYBOARD_CONSOLE_IN_EX_NOTIFY *CurrentNotify;\r
+ EFI_TPL OldTpl;\r
+\r
+ UsbKeyboardDevice = (USB_KB_DEV *) Context;\r
+\r
+ //\r
+ // Invoke notification functions.\r
+ //\r
+ NotifyList = &UsbKeyboardDevice->NotifyList;\r
+ while (TRUE) {\r
+ //\r
+ // Enter critical section\r
+ //\r
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
+ Status = Dequeue (&UsbKeyboardDevice->EfiKeyQueueForNotify, &KeyData, sizeof (KeyData));\r
+ //\r
+ // Leave critical section\r
+ //\r
+ gBS->RestoreTPL (OldTpl);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {\r
+ CurrentNotify = CR (Link, KEYBOARD_CONSOLE_IN_EX_NOTIFY, NotifyEntry, USB_KB_CONSOLE_IN_EX_NOTIFY_SIGNATURE);\r
+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {\r
+ CurrentNotify->KeyNotificationFn (&KeyData);\r
+ }\r
+ }\r
+ }\r
}\r
\r