/** @file\r
- Console Splitter Driver. Any Handle that attatched console I/O protocols\r
+ Console Splitter Driver. Any Handle that attached console I/O protocols\r
(Console In device, Console Out device, Console Error device, Simple Pointer\r
protocol, Absolute Pointer protocol) can be bound by this driver.\r
\r
\r
Each virtual handle, that supports the Console I/O protocol, will be produced\r
in the driver entry point. The virtual handle are added on driver entry and\r
- never removed. Such design ensures sytem function well during none console\r
+ never removed. Such design ensures system function well during none console\r
device situation.\r
\r
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
-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) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "ConSplitter.h"\r
\r
//\r
-// Identify if ConIn is connected in PcdConInConnectOnDemand enabled mode. \r
+// Identify if ConIn is connected in PcdConInConnectOnDemand enabled mode.\r
// default not connect\r
//\r
BOOLEAN mConInIsConnect = FALSE;\r
(LIST_ENTRY *) NULL,\r
(LIST_ENTRY *) NULL\r
},\r
+ (EFI_KEY_DATA *) NULL,\r
+ 0,\r
+ 0,\r
+ FALSE,\r
\r
{\r
ConSplitterSimplePointerReset,\r
0,\r
(TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
0,\r
- (INT32 *) NULL\r
+ (INT32 *) NULL,\r
+ FALSE\r
};\r
\r
//\r
0,\r
(TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
0,\r
- (INT32 *) NULL\r
+ (INT32 *) NULL,\r
+ FALSE\r
};\r
\r
//\r
NULL\r
};\r
\r
+/**\r
+ Key notify for toggle state sync.\r
+\r
+ @param KeyData A pointer to a buffer that is filled in with\r
+ the keystroke information for the key that was\r
+ pressed.\r
+\r
+ @retval EFI_SUCCESS Toggle state sync successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ToggleStateSyncKeyNotify (\r
+ IN EFI_KEY_DATA *KeyData\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ if (((KeyData->KeyState.KeyToggleState & KEY_STATE_VALID_EXPOSED) == KEY_STATE_VALID_EXPOSED) &&\r
+ (KeyData->KeyState.KeyToggleState != mConIn.PhysicalKeyToggleState)) {\r
+ //\r
+ // There is toggle state change, sync to other console input devices.\r
+ //\r
+ for (Index = 0; Index < mConIn.CurrentNumberOfExConsoles; Index++) {\r
+ mConIn.TextInExList[Index]->SetState (\r
+ mConIn.TextInExList[Index],\r
+ &KeyData->KeyState.KeyToggleState\r
+ );\r
+ }\r
+ mConIn.PhysicalKeyToggleState = KeyData->KeyState.KeyToggleState;\r
+ DEBUG ((EFI_D_INFO, "Current toggle state is 0x%02x\n", mConIn.PhysicalKeyToggleState));\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Initialization for toggle state sync.\r
+\r
+ @param Private Text In Splitter pointer.\r
+\r
+**/\r
+VOID\r
+ToggleStateSyncInitialization (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ EFI_KEY_DATA KeyData;\r
+ VOID *NotifyHandle;\r
+\r
+ //\r
+ // Initialize PhysicalKeyToggleState that will be synced to new console\r
+ // input device to turn on physical TextInEx partial key report for\r
+ // toggle state sync.\r
+ //\r
+ Private->PhysicalKeyToggleState = KEY_STATE_VALID_EXPOSED;\r
+\r
+ //\r
+ // Initialize VirtualKeyStateExported to let the virtual TextInEx not report\r
+ // the partial key even though the physical TextInEx turns on the partial\r
+ // key report. The virtual TextInEx will report the partial key after it is\r
+ // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly.\r
+ //\r
+ Private->VirtualKeyStateExported = FALSE;\r
+\r
+ //\r
+ // Register key notify for toggle state sync.\r
+ //\r
+ KeyData.Key.ScanCode = SCAN_NULL;\r
+ KeyData.Key.UnicodeChar = CHAR_NULL;\r
+ KeyData.KeyState.KeyShiftState = 0;\r
+ KeyData.KeyState.KeyToggleState = 0;\r
+ Private->TextInEx.RegisterKeyNotify (\r
+ &Private->TextInEx,\r
+ &KeyData,\r
+ ToggleStateSyncKeyNotify,\r
+ &NotifyHandle\r
+ );\r
+}\r
+\r
+/**\r
+ Re-initialization for toggle state sync.\r
+\r
+ @param Private Text In Splitter pointer.\r
+\r
+**/\r
+VOID\r
+ToggleStateSyncReInitialization (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ //\r
+ // Reinitialize PhysicalKeyToggleState that will be synced to new console\r
+ // input device to turn on physical TextInEx partial key report for\r
+ // toggle state sync.\r
+ //\r
+ Private->PhysicalKeyToggleState = KEY_STATE_VALID_EXPOSED;\r
+\r
+ //\r
+ // Reinitialize VirtualKeyStateExported to let the virtual TextInEx not report\r
+ // the partial key even though the physical TextInEx turns on the partial\r
+ // key report. The virtual TextInEx will report the partial key after it is\r
+ // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly.\r
+ //\r
+ Private->VirtualKeyStateExported = FALSE;\r
+\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ Private->TextInExList[Index]->SetState (\r
+ Private->TextInExList[Index],\r
+ &Private->PhysicalKeyToggleState\r
+ );\r
+ }\r
+}\r
+\r
/**\r
The Entry Point for module ConSplitter. The user code starts with this function.\r
\r
//\r
Status = ConSplitterTextOutConstructor (&mConOut);\r
if (!EFI_ERROR (Status)) {\r
- if (!FeaturePcdGet (PcdConOutGopSupport)) {\r
- //\r
- // If Graphics Outpurt protocol not supported, UGA Draw protocol is installed\r
- // on the virtual handle.\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &mConOut.VirtualHandle,\r
- &gEfiSimpleTextOutProtocolGuid,\r
- &mConOut.TextOut,\r
- &gEfiUgaDrawProtocolGuid,\r
- &mConOut.UgaDraw,\r
- NULL\r
- );\r
- } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
- //\r
- // If UGA Draw protocol not supported, Graphics Output Protocol is installed\r
- // on virtual handle.\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &mConOut.VirtualHandle,\r
- &gEfiSimpleTextOutProtocolGuid,\r
- &mConOut.TextOut,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- &mConOut.GraphicsOutput,\r
- NULL\r
- );\r
- } else {\r
- //\r
- // Boot Graphics Output protocol and UGA Draw protocol are supported,\r
- // both they will be installed on virtual handle.\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &mConOut.VirtualHandle,\r
- &gEfiSimpleTextOutProtocolGuid,\r
- &mConOut.TextOut,\r
- &gEfiGraphicsOutputProtocolGuid,\r
- &mConOut.GraphicsOutput,\r
- &gEfiUgaDrawProtocolGuid,\r
- &mConOut.UgaDraw,\r
- NULL\r
- );\r
- }\r
-\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mConOut.VirtualHandle,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ &mConOut.TextOut,\r
+ NULL\r
+ );\r
if (!EFI_ERROR (Status)) {\r
//\r
// Update the EFI System Table with new virtual console\r
&mStdErr.TextOut,\r
NULL\r
);\r
- if (!EFI_ERROR (Status)) { \r
+ if (!EFI_ERROR (Status)) {\r
//\r
// Update the EFI System Table with new virtual console\r
// and update the pointer to Text Output protocol.\r
gST->StdErr = &mStdErr.TextOut;\r
}\r
}\r
- \r
+\r
//\r
// Update the CRC32 in the EFI System Table header\r
//\r
structure.\r
\r
@retval EFI_OUT_OF_RESOURCES Out of resources.\r
- @retval EFI_SUCCESS Text Input Devcie's private data has been constructed.\r
+ @retval EFI_SUCCESS Text Input Device's private data has been constructed.\r
@retval other Failed to construct private data.\r
\r
**/\r
)\r
{\r
EFI_STATUS Status;\r
+ UINTN TextInExListCount;\r
\r
//\r
// Allocate buffer for Simple Text Input device\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
+ //\r
+ // Allocate buffer for KeyQueue\r
+ //\r
+ TextInExListCount = ConInPrivate->TextInExListCount;\r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_KEY_DATA),\r
+ &TextInExListCount,\r
+ (VOID **) &ConInPrivate->KeyQueue\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
//\r
// Allocate buffer for Simple Text Input Ex device\r
//\r
\r
InitializeListHead (&ConInPrivate->NotifyList);\r
\r
+ ToggleStateSyncInitialization (ConInPrivate);\r
+\r
ConInPrivate->AbsolutePointer.Mode = &ConInPrivate->AbsolutePointerMode;\r
//\r
// Allocate buffer for Absolute Pointer device\r
ConInPrivate,\r
&ConInPrivate->SimplePointer.WaitForInput\r
);\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // Create Event to signal ConIn connection request\r
+ //\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ EfiEventEmptyFunction,\r
+ NULL,\r
+ &gConnectConInEventGuid,\r
+ &ConInPrivate->ConnectConInEvent\r
+ );\r
\r
return Status;\r
}\r
}\r
\r
//\r
- // Initilize console output splitter's private data.\r
+ // Initialize console output splitter's private data.\r
//\r
ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode;\r
\r
@param Guid The specified protocol.\r
\r
@retval EFI_SUCCESS The specified protocol is supported on this device.\r
- @retval EFI_UNSUPPORTED The specified protocol attempts to be installed on virtul handle.\r
+ @retval EFI_UNSUPPORTED The specified protocol attempts to be installed on virtual handle.\r
@retval other Failed to open specified protocol on this device.\r
\r
**/\r
}\r
\r
//\r
- // Open InterfaceGuid on the virtul handle.\r
+ // Open InterfaceGuid on the virtual handle.\r
//\r
Status = gBS->OpenProtocol (\r
ControllerHandle,\r
\r
//\r
// Start ConSplitter on ControllerHandle, and create the virtual\r
- // agrogated console device on first call Start for a SimpleTextIn handle.\r
+ // aggregated console device on first call Start for a SimpleTextIn handle.\r
//\r
Status = ConSplitterStart (\r
This,\r
\r
//\r
// Start ConSplitter on ControllerHandle, and create the virtual\r
- // agrogated console device on first call Start for a SimplePointer handle.\r
+ // aggregated console device on first call Start for a SimplePointer handle.\r
//\r
Status = ConSplitterStart (\r
This,\r
\r
//\r
// Start ConSplitter on ControllerHandle, and create the virtual\r
- // agrogated console device on first call Start for a AbsolutePointer handle.\r
+ // aggregated console device on first call Start for a AbsolutePointer handle.\r
//\r
Status = ConSplitterStart (\r
This,\r
\r
//\r
// Start ConSplitter on ControllerHandle, and create the virtual\r
- // agrogated console device on first call Start for a ConsoleOut handle.\r
+ // aggregated console device on first call Start for a ConsoleOut handle.\r
//\r
Status = ConSplitterStart (\r
This,\r
\r
FreePool (Info);\r
\r
- } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ } else if (UgaDraw != NULL) {\r
Status = UgaDraw->GetMode (\r
UgaDraw,\r
&mConOut.UgaHorizontalResolution,\r
\r
//\r
// Start ConSplitter on ControllerHandle, and create the virtual\r
- // agrogated console device on first call Start for a StandardError handle.\r
+ // aggregated console device on first call Start for a StandardError handle.\r
//\r
Status = ConSplitterStart (\r
This,\r
// their MaxMode and QueryData should be the intersection of both.\r
//\r
Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);\r
- ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));\r
\r
return Status;\r
}\r
return Status;\r
}\r
//\r
- // close the protocol refered.\r
+ // close the protocol referred.\r
//\r
gBS->CloseProtocol (\r
ControllerHandle,\r
\r
\r
/**\r
- Stop Console In ConSplitter on ControllerHandle by closing Console In Devcice GUID.\r
+ Stop Console In ConSplitter on ControllerHandle by closing Console In Device GUID.\r
\r
@param This Driver Binding protocol instance pointer.\r
@param ControllerHandle Handle of device to stop driver on\r
\r
\r
/**\r
- Stop Console Out ConSplitter on device handle by closing Console Out Devcice GUID.\r
+ Stop Console Out ConSplitter on device handle by closing Console Out Devcie GUID.\r
\r
@param This Driver Binding protocol instance pointer.\r
@param ControllerHandle Handle of device to stop driver on\r
return EFI_OUT_OF_RESOURCES;\r
}\r
}\r
+\r
+ TextInExListCount = Private->TextInExListCount;\r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_KEY_DATA),\r
+ &TextInExListCount,\r
+ (VOID **) &Private->KeyQueue\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
Status = ConSplitterGrowBuffer (\r
sizeof (EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *),\r
&Private->TextInExListCount,\r
Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx;\r
Private->CurrentNumberOfExConsoles++;\r
\r
+ //\r
+ // Sync current toggle state to this new console input device.\r
+ //\r
+ TextInEx->SetState (TextInEx, &Private->PhysicalKeyToggleState);\r
+\r
//\r
// Extra CheckEvent added to reduce the double CheckEvent().\r
//\r
INT32 *OldTextOutModeMap;\r
INT32 *SrcAddress;\r
INT32 Index;\r
+ UINTN OldStepSize;\r
+ UINTN NewStepSize;\r
\r
NewSize = Private->TextOutListCount * sizeof (INT32);\r
OldTextOutModeMap = Private->TextOutModeMap;\r
Size = Private->CurrentNumberOfConsoles * sizeof (INT32);\r
Index = 0;\r
SrcAddress = OldTextOutModeMap;\r
+ NewStepSize = NewSize / sizeof(INT32);\r
+ // If Private->CurrentNumberOfConsoles is not zero and OldTextOutModeMap\r
+ // is not NULL, it indicates that the original TextOutModeMap is not enough\r
+ // for the new console devices and has been enlarged by CONSOLE_SPLITTER_ALLOC_UNIT columns.\r
+ //\r
+ OldStepSize = NewStepSize - CONSOLE_SPLITTER_ALLOC_UNIT;\r
\r
//\r
// Copy the old data to the new one\r
//\r
while (Index < Private->TextOutMode.MaxMode) {\r
CopyMem (TextOutModeMap, SrcAddress, Size);\r
- TextOutModeMap += NewSize;\r
- SrcAddress += Size;\r
+ //\r
+ // Go to next row of new TextOutModeMap.\r
+ //\r
+ TextOutModeMap += NewStepSize;\r
+ //\r
+ // Go to next row of old TextOutModeMap.\r
+ //\r
+ SrcAddress += OldStepSize;\r
Index++;\r
}\r
//\r
\r
//\r
// Find the intersection of the two set of modes. If they actually intersect, the\r
- // correponding entry in the map table is set to 1.\r
+ // corresponding entry in the map table is set to 1.\r
//\r
Mode = 0;\r
while (Mode < ConOutMaxMode) {\r
\r
\r
/**\r
- Add Grahpics Output modes into Consplitter Text Out list.\r
+ Add Graphics Output modes into Consplitter Text Out list.\r
\r
@param Private Text Out Splitter pointer.\r
@param GraphicsOutput Graphics Output protocol pointer.\r
}\r
}\r
}\r
- } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ } else if (UgaDraw != NULL) {\r
//\r
// Graphics console driver can ensure the same mode for all GOP devices\r
// so we can get the current mode from this video device\r
if (GraphicsOutput != NULL) {\r
Private->CurrentNumberOfGraphicsOutput++;\r
}\r
- if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ if (UgaDraw != NULL) {\r
Private->CurrentNumberOfUgaDraw++;\r
}\r
\r
//\r
// Force GraphicsOutput mode to be set,\r
//\r
- \r
+\r
Mode = &Private->GraphicsOutputModeBuffer[CurrentIndex];\r
if ((GraphicsOutput != NULL) &&\r
(Mode->HorizontalResolution == CurrentGraphicsOutputMode->Info->HorizontalResolution) &&\r
MaxMode = (UINTN) (TextOut->Mode->MaxMode);\r
\r
MaxModeInfo.Column = 0;\r
- MaxModeInfo.Row = 0; \r
+ MaxModeInfo.Row = 0;\r
ModeInfo.Column = PcdGet32 (PcdConOutColumn);\r
ModeInfo.Row = PcdGet32 (PcdConOutRow);\r
\r
Status = TextOut->SetMode (TextOut, BaseMode);\r
ASSERT(!EFI_ERROR(Status));\r
\r
- PcdSet32 (PcdConOutColumn, 80);\r
- PcdSet32 (PcdConOutRow, 25);\r
+ Status = PcdSet32S (PcdConOutColumn, 80);\r
+ ASSERT(!EFI_ERROR(Status));\r
+ Status = PcdSet32S (PcdConOutRow, 25);\r
+ ASSERT(!EFI_ERROR(Status));\r
}\r
\r
return ;\r
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;\r
EFI_STATUS DeviceStatus;\r
\r
- Status = EFI_SUCCESS;\r
- CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;\r
+ Status = EFI_SUCCESS;\r
+ CurrentNumOfConsoles = Private->CurrentNumberOfConsoles;\r
+ Private->AddingConOutDevice = TRUE;\r
\r
//\r
// If the Text Out List is full, enlarge it by calling ConSplitterGrowBuffer().\r
ASSERT (MaxMode >= 1);\r
\r
DeviceStatus = EFI_DEVICE_ERROR;\r
- if (FeaturePcdGet (PcdConOutGopSupport)) {\r
- //\r
- // If GOP is produced by Consplitter, this device display mode will be added into Graphics Ouput modes.\r
- //\r
- if ((GraphicsOutput != NULL) || (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport))) {\r
- DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
- }\r
+ Status = EFI_DEVICE_ERROR;\r
+\r
+ //\r
+ // This device display mode will be added into Graphics Ouput modes.\r
+ //\r
+ if ((GraphicsOutput != NULL) || (UgaDraw != NULL)) {\r
+ DeviceStatus = ConSplitterAddGraphicsOutputMode (Private, GraphicsOutput, UgaDraw);\r
}\r
\r
if (FeaturePcdGet (PcdConOutUgaSupport)) {\r
\r
FreePool (Info);\r
\r
- } else if (UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ } else if (UgaDraw != NULL) {\r
Status = UgaDraw->GetMode (\r
UgaDraw,\r
&UgaHorizontalResolution,\r
}\r
}\r
\r
+ if (((!EFI_ERROR (DeviceStatus)) || (!EFI_ERROR (Status))) &&\r
+ ((Private->CurrentNumberOfGraphicsOutput + Private->CurrentNumberOfUgaDraw) == 1)) {\r
+ if (!FeaturePcdGet (PcdConOutGopSupport)) {\r
+ //\r
+ // If Graphics Outpurt protocol not supported, UGA Draw protocol is installed\r
+ // on the virtual handle.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mConOut.VirtualHandle,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ &mConOut.UgaDraw,\r
+ NULL\r
+ );\r
+ } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
+ //\r
+ // If UGA Draw protocol not supported, Graphics Output Protocol is installed\r
+ // on virtual handle.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mConOut.VirtualHandle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &mConOut.GraphicsOutput,\r
+ NULL\r
+ );\r
+ } else {\r
+ //\r
+ // Boot Graphics Output protocol and UGA Draw protocol are supported,\r
+ // both they will be installed on virtual handle.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mConOut.VirtualHandle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &mConOut.GraphicsOutput,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ &mConOut.UgaDraw,\r
+ NULL\r
+ );\r
+ }\r
+ }\r
+\r
//\r
// After adding new console device, all existing console devices should be\r
// synced to the current shared mode.\r
//\r
ConsplitterSetConsoleOutMode (Private);\r
\r
+ Private->AddingConOutDevice = FALSE;\r
+\r
return Status;\r
}\r
\r
TextOutList = Private->TextOutList;\r
while (Index >= 0) {\r
if (TextOutList->TextOut == TextOut) {\r
- if (TextOutList->UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ if (TextOutList->UgaDraw != NULL) {\r
Private->CurrentNumberOfUgaDraw--;\r
}\r
if (TextOutList->GraphicsOutput != NULL) {\r
return EFI_NOT_FOUND;\r
}\r
\r
+ if ((Private->CurrentNumberOfGraphicsOutput == 0) && (Private->CurrentNumberOfUgaDraw == 0)) {\r
+ //\r
+ // If there is not any physical GOP and UGA device in system,\r
+ // Consplitter GOP or UGA protocol will be uninstalled\r
+ //\r
+ if (!FeaturePcdGet (PcdConOutGopSupport)) {\r
+ Status = gBS->UninstallProtocolInterface (\r
+ Private->VirtualHandle,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ &Private->UgaDraw\r
+ );\r
+ } else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
+ Status = gBS->UninstallProtocolInterface (\r
+ Private->VirtualHandle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &Private->GraphicsOutput\r
+ );\r
+ } else {\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ Private->VirtualHandle,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ &Private->UgaDraw,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &Private->GraphicsOutput,\r
+ NULL\r
+ );\r
+ }\r
+ }\r
+\r
if (CurrentNumOfConsoles == 0) {\r
//\r
// If the number of consoles is zero, reset all parameters\r
return EFI_SUCCESS;\r
}\r
//\r
- // Max Mode is realy an intersection of the QueryMode command to all\r
+ // Max Mode is really an intersection of the QueryMode command to all\r
// devices. So we must copy the QueryMode of the first device to\r
// QueryData.\r
//\r
\r
\r
/**\r
- Reset the input device and optionaly run diagnostics\r
+ Reset the input device and optionally run diagnostics\r
\r
@param This Protocol instance pointer.\r
@param ExtendedVerification Driver may perform diagnostics on reset.\r
}\r
}\r
\r
+ if (!EFI_ERROR (ReturnStatus)) {\r
+ ToggleStateSyncReInitialization (Private);\r
+ //\r
+ // Empty the key queue.\r
+ //\r
+ Private->CurrentNumberOfKeys = 0;\r
+ }\r
+\r
return ReturnStatus;\r
}\r
\r
+/**\r
+ Dequeue the saved key from internal key queue.\r
+\r
+ @param Private Protocol instance pointer.\r
+ @param KeyData A pointer to a buffer that is filled in with the\r
+ keystroke state data for the key that was\r
+ pressed.\r
+ @retval EFI_NOT_FOUND Queue is empty.\r
+ @retval EFI_SUCCESS First key is dequeued and returned.\r
+**/\r
+EFI_STATUS\r
+ConSplitterTextInExDequeueKey (\r
+ IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private,\r
+ OUT EFI_KEY_DATA *KeyData\r
+ )\r
+{\r
+ if (Private->CurrentNumberOfKeys == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+ //\r
+ // Return the first saved key.\r
+ //\r
+ CopyMem (KeyData, &Private->KeyQueue[0], sizeof (EFI_KEY_DATA));\r
+ Private->CurrentNumberOfKeys--;\r
+ CopyMem (\r
+ &Private->KeyQueue[0],\r
+ &Private->KeyQueue[1],\r
+ Private->CurrentNumberOfKeys * sizeof (EFI_KEY_DATA)\r
+ );\r
+ return EFI_SUCCESS;\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
+ be used to test for existence of a keystroke via WaitForEvent () call.\r
\r
@param Private Protocol instance pointer.\r
@param Key Driver may perform diagnostics on reset.\r
{\r
EFI_STATUS Status;\r
UINTN Index;\r
- EFI_INPUT_KEY CurrentKey;\r
+ EFI_KEY_DATA KeyData;\r
+\r
+ //\r
+ // Return the first saved non-NULL key.\r
+ //\r
+ while (TRUE) {\r
+ Status = ConSplitterTextInExDequeueKey (Private, &KeyData);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ if ((KeyData.Key.ScanCode != CHAR_NULL) || (KeyData.Key.UnicodeChar != SCAN_NULL)) {\r
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+ return Status;\r
+ }\r
+ }\r
\r
Key->UnicodeChar = 0;\r
Key->ScanCode = SCAN_NULL;\r
// if any physical console input device has key input,\r
// return the key and EFI_SUCCESS.\r
//\r
- for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
+ for (Index = 0; Index < Private->CurrentNumberOfConsoles;) {\r
Status = Private->TextInList[Index]->ReadKeyStroke (\r
Private->TextInList[Index],\r
- &CurrentKey\r
+ &KeyData.Key\r
);\r
- if (!EFI_ERROR (Status)) {\r
- *Key = CurrentKey;\r
- return Status;\r
- }\r
- }\r
-\r
- return EFI_NOT_READY;\r
-}\r
-\r
-/*\r
- Connect the specific Usb device which match the short form device path,\r
- and whose bus is determined by Host Controller.\r
-\r
- @param DevicePath A short-form device path that starts with the first\r
- element being a USB WWID or a USB Class device\r
- path\r
-\r
- @return EFI_INVALID_PARAMETER DevicePath is NULL pointer.\r
- DevicePath is not a USB device path.\r
-\r
- @return EFI_SUCCESS Success to connect USB device\r
- @return EFI_NOT_FOUND Fail to find handle for USB controller to connect.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-ConSplitterConnectUsbShortFormDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE *Handles;\r
- UINTN HandleCount;\r
- UINTN Index;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- UINT8 Class[3];\r
- BOOLEAN AtLeastOneConnected;\r
-\r
- //\r
- // Check the passed in parameters\r
- //\r
- if (DevicePath == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((DevicePathType (DevicePath) != MESSAGING_DEVICE_PATH) ||\r
- ((DevicePathSubType (DevicePath) != MSG_USB_CLASS_DP) && (DevicePathSubType (DevicePath) != MSG_USB_WWID_DP))\r
- ) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Find the usb host controller firstly, then connect with the remaining device path\r
- //\r
- AtLeastOneConnected = FALSE;\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiPciIoProtocolGuid,\r
- NULL,\r
- &HandleCount,\r
- &Handles\r
- );\r
- for (Index = 0; Index < HandleCount; Index++) {\r
- Status = gBS->HandleProtocol (\r
- Handles[Index],\r
- &gEfiPciIoProtocolGuid,\r
- (VOID **) &PciIo\r
- );\r
if (!EFI_ERROR (Status)) {\r
//\r
- // Check whether the Pci device is the wanted usb host controller\r
+ // If it is not partial keystorke, return the key. Otherwise, continue\r
+ // to read key from THIS physical console input device.\r
//\r
- Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);\r
- if (!EFI_ERROR (Status) &&\r
- ((PCI_CLASS_SERIAL == Class[2]) && (PCI_CLASS_SERIAL_USB == Class[1]))\r
- ) {\r
- Status = gBS->ConnectController (\r
- Handles[Index],\r
- NULL,\r
- DevicePath,\r
- FALSE\r
- );\r
- if (!EFI_ERROR(Status)) {\r
- AtLeastOneConnected = TRUE;\r
- }\r
+ if ((KeyData.Key.ScanCode != CHAR_NULL) || (KeyData.Key.UnicodeChar != SCAN_NULL)) {\r
+ CopyMem (Key, &KeyData.Key, sizeof (EFI_INPUT_KEY));\r
+ return Status;\r
}\r
+ } else {\r
+ //\r
+ // Continue to read key from NEXT physical console input device.\r
+ //\r
+ Index++;\r
}\r
}\r
\r
- return AtLeastOneConnected ? EFI_SUCCESS : EFI_NOT_FOUND;\r
-}\r
-\r
-\r
-/**\r
- This function will create all handles associate with every device\r
- path node. If the handle associate with one device path node can not\r
- be created successfully, then still give one chance to do the dispatch,\r
- which load the missing drivers if possible.\r
-\r
- @param DevicePathToConnect The device path which will be connected, it CANNOT be\r
- a multi-instance device path\r
- @param MatchingHandle Return the controller handle closest to the DevicePathToConnect\r
-\r
- @retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL.\r
- @retval EFI_NOT_FOUND Failed to create all handles associate with every device path node.\r
- @retval EFI_SUCCESS Successful to create all handles associate with every device path node.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-ConSplitterConnectDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect,\r
- OUT EFI_HANDLE *MatchingHandle OPTIONAL\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
- EFI_HANDLE Handle;\r
- EFI_HANDLE PreviousHandle;\r
-\r
- if (DevicePathToConnect == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Start the real work of connect with RemainingDevicePath\r
- //\r
- PreviousHandle = NULL;\r
- do {\r
- //\r
- // Find the handle that best matches the Device Path. If it is only a\r
- // partial match the remaining part of the device path is returned in\r
- // RemainingDevicePath.\r
- //\r
- RemainingDevicePath = DevicePathToConnect;\r
- Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);\r
- if (!EFI_ERROR (Status)) {\r
- if (Handle == PreviousHandle) {\r
- //\r
- // If no forward progress is made try invoking the Dispatcher.\r
- // A new FV may have been added to the system an new drivers\r
- // may now be found.\r
- // Status == EFI_SUCCESS means a driver was dispatched\r
- // Status == EFI_NOT_FOUND means no new drivers were dispatched\r
- //\r
- Status = gDS->Dispatch ();\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- PreviousHandle = Handle;\r
- //\r
- // Connect all drivers that apply to Handle and RemainingDevicePath,\r
- // the Recursive flag is FALSE so only one level will be expanded.\r
- //\r
- // Do not check the connect status here, if the connect controller fail,\r
- // then still give the chance to do dispatch, because partial\r
- // RemainingDevicepath may be in the new FV\r
- //\r
- // 1. If the connect fail, RemainingDevicepath and handle will not\r
- // change, so next time will do the dispatch, then dispatch's status\r
- // will take effect\r
- // 2. If the connect success, the RemainingDevicepath and handle will\r
- // change, then avoid the dispatch, we have chance to continue the\r
- // next connection\r
- //\r
- gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);\r
- if (MatchingHandle != NULL) {\r
- *MatchingHandle = Handle;\r
- }\r
- }\r
- }\r
- //\r
- // Loop until RemainingDevicePath is an empty device path\r
- //\r
- } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));\r
-\r
- ASSERT (EFI_ERROR (Status) || IsDevicePathEnd (RemainingDevicePath));\r
-\r
- return Status;\r
-}\r
-\r
-\r
-/**\r
- Connect to all ConIn device which is in the ConIn variable.\r
-\r
- @param DevicePath A short-form device path that starts with the first\r
- element being a USB WWID or a USB Class device\r
- path\r
-\r
- @return EFI_INVALID_PARAMETER DevicePath is NULL pointer.\r
- DevicePath is not a USB device path.\r
-\r
- @return EFI_SUCCESS Success to connect USB device\r
- @return EFI_NOT_FOUND Fail to find handle for USB controller to connect.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-ConSplitterConnectConInDevicePath (\r
- \r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePathInst;\r
- EFI_DEVICE_PATH_PROTOCOL *CopyDevicePath;\r
- UINTN Size;\r
- EFI_DEVICE_PATH_PROTOCOL *Next;\r
-\r
- DevicePath = GetEfiGlobalVariable (L"ConIn");\r
-\r
- //\r
- // Check the passed in parameters\r
- //\r
- if (DevicePath == NULL) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- CopyDevicePath = DevicePath;\r
-\r
- DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
- while (DevicePathInst != NULL) {\r
-\r
- Next = DevicePathInst;\r
- while (!IsDevicePathEndType (Next)) {\r
- Next = NextDevicePathNode (Next);\r
- }\r
-\r
- SetDevicePathEndNode (Next);\r
- \r
- //\r
- // Connect the USB console\r
- // USB console device path is a short-form device path that \r
- // starts with the first element being a USB WWID\r
- // or a USB Class device path\r
- //\r
- if ((DevicePathType (DevicePathInst) == MESSAGING_DEVICE_PATH) &&\r
- ((DevicePathSubType (DevicePathInst) == MSG_USB_CLASS_DP)\r
- || (DevicePathSubType (DevicePathInst) == MSG_USB_WWID_DP)\r
- )) {\r
- ConSplitterConnectUsbShortFormDevicePath (DevicePathInst);\r
- } else {\r
- ConSplitterConnectDevicePath (DevicePathInst, NULL);\r
- } \r
- DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size);\r
- }\r
- return EFI_SUCCESS;\r
+ return EFI_NOT_READY;\r
}\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
+ be used to test for existence of a keystroke via WaitForEvent () call.\r
\r
@param This Protocol instance pointer.\r
@param Key Driver may perform diagnostics on reset.\r
Private->KeyEventSignalState = FALSE;\r
\r
//\r
- // Connect ConIn when first call in Lazy ConIn mode\r
+ // Signal ConnectConIn event on first call in Lazy ConIn mode\r
//\r
if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {\r
- DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n")); \r
- ConSplitterConnectConInDevicePath ();\r
+ DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));\r
+ gBS->SignalEvent (Private->ConnectConInEvent);\r
mConInIsConnect = TRUE;\r
}\r
\r
spliter event. This will cause the calling code to call\r
ConSplitterTextInReadKeyStroke ().\r
\r
- @param Event The Event assoicated with callback.\r
+ @param Event The Event associated with callback.\r
@param Context Context registered when Event was created.\r
\r
**/\r
pressed.\r
\r
@retval TRUE Key be pressed matches a registered key.\r
- @retval FLASE Match failed.\r
+ @retval FALSE Match failed.\r
\r
**/\r
BOOLEAN\r
\r
\r
/**\r
- Reset the input device and optionaly run diagnostics\r
+ Reset the input device and optionally run diagnostics\r
\r
@param This Protocol instance pointer.\r
@param ExtendedVerification Driver may perform diagnostics on reset.\r
}\r
}\r
\r
+ if (!EFI_ERROR (ReturnStatus)) {\r
+ ToggleStateSyncReInitialization (Private);\r
+ //\r
+ // Empty the key queue.\r
+ //\r
+ Private->CurrentNumberOfKeys = 0;\r
+ }\r
+\r
return ReturnStatus;\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
+ be used to test for existence of a keystroke via WaitForEvent () call.\r
\r
@param This Protocol instance pointer.\r
@param KeyData A pointer to a buffer that is filled in with the\r
TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
EFI_STATUS Status;\r
UINTN Index;\r
+ EFI_KEY_STATE KeyState;\r
EFI_KEY_DATA CurrentKeyData;\r
\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Private->KeyEventSignalState = FALSE;\r
+\r
//\r
- // Connect ConIn when first call in Lazy ConIn mode\r
+ // Signal ConnectConIn event on first call in Lazy ConIn mode\r
//\r
if (!mConInIsConnect && PcdGetBool (PcdConInConnectOnDemand)) {\r
- DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n")); \r
- ConSplitterConnectConInDevicePath ();\r
+ DEBUG ((EFI_D_INFO, "Connect ConIn in first ReadKeyStoke in Lazy ConIn mode.\n"));\r
+ gBS->SignalEvent (Private->ConnectConInEvent);\r
mConInIsConnect = TRUE;\r
}\r
\r
- Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- Private->KeyEventSignalState = FALSE;\r
+ //\r
+ // Return the first saved key.\r
+ //\r
+ Status = ConSplitterTextInExDequeueKey (Private, KeyData);\r
+ if (!EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ ASSERT (Private->CurrentNumberOfKeys == 0);\r
\r
- KeyData->Key.UnicodeChar = 0;\r
- KeyData->Key.ScanCode = SCAN_NULL;\r
+ ZeroMem (&KeyState, sizeof (KeyState));\r
\r
//\r
- // if no physical console input device exists, return EFI_NOT_READY;\r
- // if any physical console input device has key input,\r
- // return the key and EFI_SUCCESS.\r
+ // Iterate through all physical consoles to get key state.\r
+ // Some physical consoles may return valid key.\r
+ // Queue the valid keys.\r
//\r
for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ ZeroMem (&CurrentKeyData, sizeof (EFI_KEY_DATA));\r
Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
- Private->TextInExList[Index],\r
- &CurrentKeyData\r
- );\r
+ Private->TextInExList[Index],\r
+ &CurrentKeyData\r
+ );\r
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Consolidate the key state from all physical consoles.\r
+ //\r
+ if ((CurrentKeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) {\r
+ KeyState.KeyShiftState |= CurrentKeyData.KeyState.KeyShiftState;\r
+ }\r
+ if ((CurrentKeyData.KeyState.KeyToggleState & EFI_TOGGLE_STATE_VALID) != 0) {\r
+ KeyState.KeyToggleState |= CurrentKeyData.KeyState.KeyToggleState;\r
+ }\r
+\r
if (!EFI_ERROR (Status)) {\r
- CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\r
- return Status;\r
+ //\r
+ // If virtual KeyState has been required to be exposed, or it is not\r
+ // partial keystorke, queue the key.\r
+ // It's possible that user presses at multiple keyboards at the same moment,\r
+ // Private->KeyQueue[] are the storage to save all the keys.\r
+ //\r
+ if ((Private->VirtualKeyStateExported) ||\r
+ (CurrentKeyData.Key.ScanCode != CHAR_NULL) ||\r
+ (CurrentKeyData.Key.UnicodeChar != SCAN_NULL)) {\r
+ CopyMem (\r
+ &Private->KeyQueue[Private->CurrentNumberOfKeys],\r
+ &CurrentKeyData,\r
+ sizeof (EFI_KEY_DATA)\r
+ );\r
+ Private->CurrentNumberOfKeys++;\r
+ }\r
}\r
}\r
\r
+ //\r
+ // Consolidate the key state for all keys in Private->KeyQueue[]\r
+ //\r
+ for (Index = 0; Index < Private->CurrentNumberOfKeys; Index++) {\r
+ CopyMem (&Private->KeyQueue[Index].KeyState, &KeyState, sizeof (EFI_KEY_STATE));\r
+ }\r
+\r
+ //\r
+ // Return the first saved key.\r
+ //\r
+ Status = ConSplitterTextInExDequeueKey (Private, KeyData);\r
+ if (!EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Always return the key state even there is no key pressed.\r
+ //\r
+ ZeroMem (&KeyData->Key, sizeof (KeyData->Key));\r
+ CopyMem (&KeyData->KeyState, &KeyState, sizeof (KeyData->KeyState));\r
return EFI_NOT_READY;\r
}\r
\r
TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
EFI_STATUS Status;\r
UINTN Index;\r
+ EFI_KEY_TOGGLE_STATE PhysicalKeyToggleState;\r
\r
if (KeyToggleState == NULL) {\r
return EFI_INVALID_PARAMETER;\r
\r
Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
\r
+ //\r
+ // Always turn on physical TextInEx partial key report for\r
+ // toggle state sync.\r
+ //\r
+ PhysicalKeyToggleState = *KeyToggleState | EFI_KEY_STATE_EXPOSED;\r
+\r
//\r
// if no physical console input device exists, return EFI_SUCCESS;\r
// otherwise return the status of setting state of physical console input device\r
for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
Status = Private->TextInExList[Index]->SetState (\r
Private->TextInExList[Index],\r
- KeyToggleState\r
+ &PhysicalKeyToggleState\r
);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
}\r
\r
+ //\r
+ // Record the physical KeyToggleState.\r
+ //\r
+ Private->PhysicalKeyToggleState = PhysicalKeyToggleState;\r
+ //\r
+ // Get if virtual KeyState has been required to be exposed.\r
+ //\r
+ Private->VirtualKeyStateExported = (((*KeyToggleState) & EFI_KEY_STATE_EXPOSED) != 0);\r
+\r
return EFI_SUCCESS;\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\r
- keystroke information data for the key that was\r
- 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\r
registered notification.\r
\r
@retval EFI_SUCCESS The notification function was registered\r
successfully.\r
- @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data\r
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data\r
structures.\r
@retval EFI_INVALID_PARAMETER KeyData or KeyNotificationFunction or NotifyHandle is NULL.\r
\r
if (NewNotify == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->TextInExListCount);\r
+ NewNotify->NotifyHandleList = (VOID **) AllocateZeroPool (sizeof (VOID *) * Private->TextInExListCount);\r
if (NewNotify->NotifyHandleList == NULL) {\r
gBS->FreePool (NewNotify);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
}\r
\r
- InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+ InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);\r
\r
*NotifyHandle = NewNotify;\r
\r
\r
\r
/**\r
- Reset the input device and optionaly run diagnostics\r
+ Reset the input device and optionally run diagnostics\r
\r
@param This Protocol instance pointer.\r
@param ExtendedVerification Driver may perform diagnostics on reset.\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
+ be used to test for existence of a keystroke via WaitForEvent () call.\r
\r
@param Private Protocol instance pointer.\r
@param State The state information of simple pointer device.\r
\r
\r
/**\r
- This event agregates all the events of the ConIn devices in the spliter.\r
+ This event aggregates all the events of the ConIn devices in the spliter.\r
If any events of physical ConIn devices are signaled, signal the ConIn\r
spliter event. This will cause the calling code to call\r
ConSplitterTextInReadKeyStroke ().\r
\r
- @param Event The Event assoicated with callback.\r
+ @param Event The Event associated with callback.\r
@param Context Context registered when Event was created.\r
\r
**/\r
EFI_STATUS ReturnStatus;\r
UINTN Index;\r
EFI_ABSOLUTE_POINTER_STATE CurrentState;\r
-\r
+ UINT64 MinX;\r
+ UINT64 MinY;\r
+ UINT64 MinZ;\r
+ UINT64 MaxX;\r
+ UINT64 MaxY;\r
+ UINT64 MaxZ;\r
+ UINT64 VirtualMinX;\r
+ UINT64 VirtualMinY;\r
+ UINT64 VirtualMinZ;\r
+ UINT64 VirtualMaxX;\r
+ UINT64 VirtualMaxY;\r
+ UINT64 VirtualMaxZ;\r
\r
Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_ABSOLUTE_POINTER_THIS (This);\r
\r
State->CurrentZ = 0;\r
State->ActiveButtons = 0;\r
\r
+ VirtualMinX = Private->AbsolutePointerMode.AbsoluteMinX;\r
+ VirtualMinY = Private->AbsolutePointerMode.AbsoluteMinY;\r
+ VirtualMinZ = Private->AbsolutePointerMode.AbsoluteMinZ;\r
+ VirtualMaxX = Private->AbsolutePointerMode.AbsoluteMaxX;\r
+ VirtualMaxY = Private->AbsolutePointerMode.AbsoluteMaxY;\r
+ VirtualMaxZ = Private->AbsolutePointerMode.AbsoluteMaxZ;\r
+\r
//\r
// if no physical pointer device exists, return EFI_NOT_READY;\r
// if any physical pointer device has changed state,\r
ReturnStatus = EFI_SUCCESS;\r
}\r
\r
+ MinX = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinX;\r
+ MinY = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinY;\r
+ MinZ = Private->AbsolutePointerList[Index]->Mode->AbsoluteMinZ;\r
+ MaxX = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxX;\r
+ MaxY = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxY;\r
+ MaxZ = Private->AbsolutePointerList[Index]->Mode->AbsoluteMaxZ;\r
+\r
State->ActiveButtons = CurrentState.ActiveButtons;\r
\r
- if (!(Private->AbsolutePointerMode.AbsoluteMinX == 0 && Private->AbsolutePointerMode.AbsoluteMaxX == 0)) {\r
- State->CurrentX = CurrentState.CurrentX;\r
+ //\r
+ // Rescale to Con Splitter virtual Absolute Pointer's resolution.\r
+ //\r
+ if (!(MinX == 0 && MaxX == 0)) {\r
+ State->CurrentX = VirtualMinX + DivU64x64Remainder (\r
+ MultU64x64 (\r
+ CurrentState.CurrentX,\r
+ VirtualMaxX - VirtualMinX\r
+ ),\r
+ MaxX - MinX,\r
+ NULL\r
+ );\r
}\r
- if (!(Private->AbsolutePointerMode.AbsoluteMinY == 0 && Private->AbsolutePointerMode.AbsoluteMaxY == 0)) {\r
- State->CurrentY = CurrentState.CurrentY;\r
+ if (!(MinY == 0 && MaxY == 0)) {\r
+ State->CurrentY = VirtualMinY + DivU64x64Remainder (\r
+ MultU64x64 (\r
+ CurrentState.CurrentY,\r
+ VirtualMaxY - VirtualMinY\r
+ ),\r
+ MaxY - MinY,\r
+ NULL\r
+ );\r
}\r
- if (!(Private->AbsolutePointerMode.AbsoluteMinZ == 0 && Private->AbsolutePointerMode.AbsoluteMaxZ == 0)) {\r
- State->CurrentZ = CurrentState.CurrentZ;\r
+ if (!(MinZ == 0 && MaxZ == 0)) {\r
+ State->CurrentZ = VirtualMinZ + DivU64x64Remainder (\r
+ MultU64x64 (\r
+ CurrentState.CurrentZ,\r
+ VirtualMaxZ - VirtualMinZ\r
+ ),\r
+ MaxZ - MinZ,\r
+ NULL\r
+ );\r
}\r
\r
} else if (Status == EFI_DEVICE_ERROR) {\r
\r
\r
/**\r
- This event agregates all the events of the pointer devices in the splitter.\r
+ This event aggregates all the events of the pointer devices in the splitter.\r
If any events of physical pointer devices are signaled, signal the pointer\r
splitter event. This will cause the calling code to call\r
ConSplitterAbsolutePointerGetState ().\r
\r
- @param Event The Event assoicated with callback.\r
+ @param Event The Event associated with callback.\r
@param Context Context registered when Event was created.\r
\r
**/\r
\r
\r
/**\r
- Reset the text output device hardware and optionaly run diagnostics\r
+ Reset the text output device hardware and optionally run diagnostics\r
\r
@param This Protocol instance pointer.\r
- @param ExtendedVerification Driver may perform more exhaustive verfication\r
+ @param ExtendedVerification Driver may perform more exhaustive verification\r
operation of the device during reset.\r
\r
@retval EFI_SUCCESS The text output device was reset.\r
Private->TextOutMode.CursorRow = Private->TextOutList[0].TextOut->Mode->CursorRow;\r
} else {\r
//\r
- // When there is no real console devices in system, \r
+ // When there is no real console devices in system,\r
// update cursor position for the virtual device in consplitter.\r
//\r
Private->TextOut.QueryMode (\r
Private->TextOutMode.Mode,\r
&MaxColumn,\r
&MaxRow\r
- ); \r
+ );\r
for (; *WString != CHAR_NULL; WString++) {\r
switch (*WString) {\r
case CHAR_BACKSPACE:\r
if (Private->TextOutMode.CursorColumn == 0 && Private->TextOutMode.CursorRow > 0) {\r
Private->TextOutMode.CursorRow--;\r
- Private->TextOutMode.CursorColumn = (INT32) (MaxColumn - 1); \r
+ Private->TextOutMode.CursorColumn = (INT32) (MaxColumn - 1);\r
} else if (Private->TextOutMode.CursorColumn > 0) {\r
Private->TextOutMode.CursorColumn--;\r
}\r
break;\r
- \r
+\r
case CHAR_LINEFEED:\r
if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {\r
Private->TextOutMode.CursorRow++;\r
}\r
break;\r
- \r
+\r
case CHAR_CARRIAGE_RETURN:\r
Private->TextOutMode.CursorColumn = 0;\r
break;\r
- \r
+\r
default:\r
if (Private->TextOutMode.CursorColumn < (INT32) (MaxColumn - 1)) {\r
Private->TextOutMode.CursorColumn++;\r
//\r
TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber;\r
for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
- Status = Private->TextOutList[Index].TextOut->SetMode (\r
- Private->TextOutList[Index].TextOut,\r
- TextOutModeMap[Index]\r
- );\r
- if (EFI_ERROR (Status)) {\r
- ReturnStatus = Status;\r
+ //\r
+ // While adding a console out device do not set same mode again for the same device.\r
+ //\r
+ if ((!Private->AddingConOutDevice) ||\r
+ (TextOutModeMap[Index] != Private->TextOutList[Index].TextOut->Mode->Mode)) {\r
+ Status = Private->TextOutList[Index].TextOut->SetMode (\r
+ Private->TextOutList[Index].TextOut,\r
+ TextOutModeMap[Index]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ReturnStatus = Status;\r
+ }\r
}\r
}\r
\r
//\r
// Check whether param Attribute is valid.\r
//\r
- if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) {\r
+ if ((Attribute | 0x7F) != 0x7F) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
\r
return ReturnStatus;\r
}\r
-\r