never removed. Such design ensures sytem function well during none console\r
device situation.\r
\r
-Copyright (c) 2006 - 2010, 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
+// default not connect\r
+//\r
+BOOLEAN mConInIsConnect = FALSE;\r
+\r
//\r
// Text In Splitter Private Data template\r
//\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
(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,\r
0,\r
0,\r
- TRUE,\r
\r
0,\r
(TEXT_OUT_AND_GOP_DATA *) NULL,\r
0,\r
(TEXT_OUT_SPLITTER_QUERY_DATA *) NULL,\r
0,\r
- (INT32 *) NULL\r
+ (INT32 *) NULL,\r
+ FALSE\r
};\r
\r
//\r
(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *) NULL,\r
0,\r
0,\r
- TRUE,\r
\r
0,\r
(TEXT_OUT_AND_GOP_DATA *) NULL,\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
+ Reinitialization 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
FeaturePcdGet (PcdConOutUgaSupport));\r
\r
//\r
- // The driver creates virtual handles for ConIn, ConOut.\r
+ // The driver creates virtual handles for ConIn, ConOut, StdErr.\r
// The virtual handles will always exist even if no console exist in the\r
// system. This is need to support hotplug devices like USB.\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
}\r
\r
}\r
+\r
+ //\r
+ // Create virtual device handle for StdErr Splitter\r
+ //\r
+ Status = ConSplitterTextOutConstructor (&mStdErr);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mStdErr.VirtualHandle,\r
+ &gEfiSimpleTextOutProtocolGuid,\r
+ &mStdErr.TextOut,\r
+ NULL\r
+ );\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
+ //\r
+ gST->StandardErrorHandle = mStdErr.VirtualHandle;\r
+ gST->StdErr = &mStdErr.TextOut;\r
+ }\r
+ }\r
+\r
//\r
// Update the CRC32 in the EFI System Table header\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
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
EFI_STATUS Status;\r
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
\r
- if (mStdErr.CurrentNumberOfConsoles == 0) {\r
- //\r
- // Construct console output devices' private data\r
- //\r
- Status = ConSplitterTextOutConstructor (&mStdErr);\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Create virtual device handle for StdErr Splitter\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &mStdErr.VirtualHandle,\r
- &gEfiSimpleTextOutProtocolGuid,\r
- &mStdErr.TextOut,\r
- NULL\r
- );\r
- }\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
//\r
// Start ConSplitter on ControllerHandle, and create the virtual\r
// agrogated console device on first call Start for a StandardError handle.\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
-\r
- if (mStdErr.CurrentNumberOfConsoles == 1) {\r
- gST->StandardErrorHandle = mStdErr.VirtualHandle;\r
- gST->StdErr = &mStdErr.TextOut;\r
- //\r
- // Update the CRC32 in the EFI System Table header\r
- //\r
- gST->Hdr.CRC32 = 0;\r
- gBS->CalculateCrc32 (\r
- (UINT8 *) &gST->Hdr,\r
- gST->Hdr.HeaderSize,\r
- &gST->Hdr.CRC32\r
- );\r
- }\r
\r
return Status;\r
}\r
//\r
// Delete this console error out device's data structures.\r
//\r
- Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- if (mStdErr.CurrentNumberOfConsoles == 0) {\r
- mStdErr.VirtualHandle = NULL;\r
-\r
- gST->StandardErrorHandle = NULL;\r
- gST->StdErr = NULL;\r
- //\r
- // Update the CRC32 in the EFI System Table header\r
- //\r
- gST->Hdr.CRC32 = 0;\r
- gBS->CalculateCrc32 (\r
- (UINT8 *) &gST->Hdr,\r
- gST->Hdr.HeaderSize,\r
- &gST->Hdr.CRC32\r
- );\r
-\r
- //\r
- // Uninstall Simple Text Output protocol from StdErr Handle.\r
- //\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- mStdErr.VirtualHandle,\r
- &gEfiSimpleTextOutProtocolGuid,\r
- &mStdErr.TextOut,\r
- NULL\r
- );\r
- }\r
-\r
- return Status;\r
+ return ConSplitterTextOutDeleteDevice (&mStdErr, TextOut);\r
}\r
\r
\r
/**\r
- Take the passed in Buffer of size SizeOfCount and grow the buffer\r
- by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount\r
- bytes. Copy the current data in Buffer to the new version of Buffer\r
- and free the old version of buffer.\r
+ Take the passed in Buffer of size ElementSize and grow the buffer\r
+ by CONSOLE_SPLITTER_ALLOC_UNIT * ElementSize bytes.\r
+ Copy the current data in Buffer to the new version of Buffer and\r
+ free the old version of buffer.\r
\r
- @param SizeOfCount Size of element in array.\r
+ @param ElementSize Size of element in array.\r
@param Count Current number of elements in array.\r
@param Buffer Bigger version of passed in Buffer with all the\r
data.\r
**/\r
EFI_STATUS\r
ConSplitterGrowBuffer (\r
- IN UINTN SizeOfCount,\r
+ IN UINTN ElementSize,\r
IN OUT UINTN *Count,\r
IN OUT VOID **Buffer\r
)\r
// copy the old buffer's content to the new-size buffer,\r
// then free the old buffer.\r
//\r
- *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT;\r
Ptr = ReallocatePool (\r
- SizeOfCount * ((*Count) - CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT),\r
- SizeOfCount * (*Count),\r
+ ElementSize * (*Count),\r
+ ElementSize * ((*Count) + CONSOLE_SPLITTER_ALLOC_UNIT),\r
*Buffer\r
);\r
if (Ptr == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
+ *Count += CONSOLE_SPLITTER_ALLOC_UNIT;\r
*Buffer = Ptr;\r
return EFI_SUCCESS;\r
}\r
//\r
for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) {\r
if (Private->TextInList[Index] == TextIn) {\r
- for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) {\r
+ for (; Index < Private->CurrentNumberOfConsoles - 1; Index++) {\r
Private->TextInList[Index] = Private->TextInList[Index + 1];\r
}\r
\r
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *Link;\r
+ TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
+ UINTN TextInExListCount;\r
\r
//\r
- // If the Text Input Ex List is full, enlarge it by calling ConSplitterGrowBuffer().\r
+ // Enlarge the NotifyHandleList and the TextInExList\r
//\r
if (Private->CurrentNumberOfExConsoles >= Private->TextInExListCount) {\r
+ for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);\r
+ TextInExListCount = Private->TextInExListCount;\r
+\r
+ Status = ConSplitterGrowBuffer (\r
+ sizeof (EFI_HANDLE),\r
+ &TextInExListCount,\r
+ (VOID **) &CurrentNotify->NotifyHandleList\r
+ );\r
+ if (EFI_ERROR (Status)) {\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
return EFI_OUT_OF_RESOURCES;\r
}\r
}\r
+\r
+ //\r
+ // Register the key notify in the new text-in device\r
+ //\r
+ for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
+ CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);\r
+ Status = TextInEx->RegisterKeyNotify (\r
+ TextInEx,\r
+ &CurrentNotify->KeyData,\r
+ CurrentNotify->KeyNotificationFn,\r
+ &CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ for (Link = Link->BackLink; Link != &Private->NotifyList; Link = Link->BackLink) {\r
+ CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);\r
+ TextInEx->UnregisterKeyNotify (\r
+ TextInEx,\r
+ CurrentNotify->NotifyHandleList[Private->CurrentNumberOfExConsoles]\r
+ );\r
+ }\r
+ return Status;\r
+ }\r
+ }\r
+\r
//\r
// Add the new text-in device data structure into the Text Input Ex List.\r
//\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
//\r
for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
if (Private->TextInExList[Index] == TextInEx) {\r
- for (Index = Index; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
+ for (; Index < Private->CurrentNumberOfExConsoles - 1; Index++) {\r
Private->TextInExList[Index] = Private->TextInExList[Index + 1];\r
}\r
\r
//\r
for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) {\r
if (Private->PointerList[Index] == SimplePointer) {\r
- for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) {\r
+ for (; Index < Private->CurrentNumberOfPointers - 1; Index++) {\r
Private->PointerList[Index] = Private->PointerList[Index + 1];\r
}\r
\r
//\r
for (Index = 0; Index < Private->CurrentNumberOfAbsolutePointers; Index++) {\r
if (Private->AbsolutePointerList[Index] == AbsolutePointer) {\r
- for (Index = Index; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {\r
+ for (; Index < Private->CurrentNumberOfAbsolutePointers - 1; Index++) {\r
Private->AbsolutePointerList[Index] = Private->AbsolutePointerList[Index + 1];\r
}\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
- } 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
- // regardless whether the console is in EfiConsoleControlScreenGraphics or EfiConsoleControlScreenText mode\r
//\r
- Private->HardwareNeedsStarting = TRUE;\r
- \r
+\r
Mode = &Private->GraphicsOutputModeBuffer[CurrentIndex];\r
if ((GraphicsOutput != NULL) &&\r
(Mode->HorizontalResolution == CurrentGraphicsOutputMode->Info->HorizontalResolution) &&\r
UINTN MaxMode;\r
EFI_STATUS Status;\r
CONSOLE_OUT_MODE ModeInfo;\r
+ CONSOLE_OUT_MODE MaxModeInfo;\r
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *TextOut;\r
\r
PreferMode = 0xFF;\r
TextOut = &Private->TextOut;\r
MaxMode = (UINTN) (TextOut->Mode->MaxMode);\r
\r
- ModeInfo.Column = PcdGet32 (PcdConOutColumn);\r
- ModeInfo.Row = PcdGet32 (PcdConOutRow);\r
+ MaxModeInfo.Column = 0;\r
+ MaxModeInfo.Row = 0;\r
+ ModeInfo.Column = PcdGet32 (PcdConOutColumn);\r
+ ModeInfo.Row = PcdGet32 (PcdConOutRow);\r
\r
//\r
// To find the prefer mode and basic mode from Text Out mode list\r
for (Mode = 0; Mode < MaxMode; Mode++) {\r
Status = TextOut->QueryMode (TextOut, Mode, &Col, &Row);\r
if (!EFI_ERROR(Status)) {\r
- if (Col == ModeInfo.Column && Row == ModeInfo.Row) {\r
- PreferMode = Mode;\r
+ if ((ModeInfo.Column != 0) && (ModeInfo.Row != 0)) {\r
+ //\r
+ // Use user defined column and row\r
+ //\r
+ if (Col == ModeInfo.Column && Row == ModeInfo.Row) {\r
+ PreferMode = Mode;\r
+ }\r
+ } else {\r
+ //\r
+ // If user sets PcdConOutColumn or PcdConOutRow to 0,\r
+ // find and set the highest text mode.\r
+ //\r
+ if ((Col >= MaxModeInfo.Column) && (Row >= MaxModeInfo.Row)) {\r
+ MaxModeInfo.Column = Col;\r
+ MaxModeInfo.Row = Row;\r
+ PreferMode = Mode;\r
+ }\r
}\r
if (Col == 80 && Row == 25) {\r
BaseMode = Mode;\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
- CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
- CurrentNumOfConsoles--;\r
- if (TextOutList->UgaDraw != NULL && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
+ if (TextOutList->UgaDraw != NULL) {\r
Private->CurrentNumberOfUgaDraw--;\r
}\r
if (TextOutList->GraphicsOutput != NULL) {\r
Private->CurrentNumberOfGraphicsOutput--;\r
}\r
+ CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_GOP_DATA) * Index);\r
+ CurrentNumOfConsoles--;\r
break;\r
}\r
\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
}\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
{\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
+ // If it is not partial keystorke, return the key. Otherwise, continue\r
+ // to read key from THIS physical console input device.\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
}\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
\r
Private->KeyEventSignalState = FALSE;\r
\r
+ //\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
+ gBS->SignalEvent (Private->ConnectConInEvent);\r
+ mConInIsConnect = TRUE;\r
+ }\r
+\r
return ConSplitterTextInPrivateReadKeyStroke (Private, Key);\r
}\r
\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
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
\r
Private->KeyEventSignalState = FALSE;\r
\r
- KeyData->Key.UnicodeChar = 0;\r
- KeyData->Key.ScanCode = SCAN_NULL;\r
+ //\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
+ gBS->SignalEvent (Private->ConnectConInEvent);\r
+ mConInIsConnect = TRUE;\r
+ }\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
+ // 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
+ ZeroMem (&KeyState, sizeof (KeyState));\r
+\r
+ //\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
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
TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
\r
Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
\r
- //\r
- // If no physical console input device exists,\r
- // return EFI_SUCCESS directly.\r
- //\r
- if (Private->CurrentNumberOfExConsoles <= 0) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
//\r
// Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.\r
//\r
CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);\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
if (NewNotify == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->CurrentNumberOfExConsoles);\r
+ NewNotify->NotifyHandleList = (EFI_HANDLE *) AllocateZeroPool (sizeof (EFI_HANDLE) * Private->TextInExListCount);\r
if (NewNotify->NotifyHandleList == NULL) {\r
gBS->FreePool (NewNotify);\r
return EFI_OUT_OF_RESOURCES;\r
}\r
NewNotify->Signature = TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE;\r
NewNotify->KeyNotificationFn = KeyNotificationFunction;\r
- NewNotify->NotifyHandle = (EFI_HANDLE) NewNotify;\r
- CopyMem (&NewNotify->KeyData, KeyData, sizeof (KeyData));\r
+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));\r
\r
//\r
// Return the wrong status of registering key notify of\r
&NewNotify->NotifyHandleList[Index]\r
);\r
if (EFI_ERROR (Status)) {\r
+ //\r
+ // Un-register the key notify on all physical console input devices\r
+ //\r
+ while (Index-- != 0) {\r
+ Private->TextInExList[Index]->UnregisterKeyNotify (\r
+ Private->TextInExList[Index],\r
+ NewNotify->NotifyHandleList[Index]\r
+ );\r
+ }\r
gBS->FreePool (NewNotify->NotifyHandleList);\r
gBS->FreePool (NewNotify);\r
return Status;\r
}\r
}\r
\r
- InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+ InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);\r
\r
- *NotifyHandle = NewNotify->NotifyHandle;\r
+ *NotifyHandle = NewNotify;\r
\r
return EFI_SUCCESS;\r
\r
EFIAPI\r
ConSplitterTextInUnregisterKeyNotify (\r
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,\r
- IN EFI_HANDLE NotificationHandle\r
+ IN VOID *NotificationHandle\r
)\r
{\r
TEXT_IN_SPLITTER_PRIVATE_DATA *Private;\r
- EFI_STATUS Status;\r
UINTN Index;\r
TEXT_IN_EX_SPLITTER_NOTIFY *CurrentNotify;\r
LIST_ENTRY *Link;\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (((TEXT_IN_EX_SPLITTER_NOTIFY *) NotificationHandle)->Signature != TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
\r
- //\r
- // if no physical console input device exists,\r
- // return EFI_SUCCESS directly.\r
- //\r
- if (Private->CurrentNumberOfExConsoles <= 0) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
for (Link = Private->NotifyList.ForwardLink; Link != &Private->NotifyList; Link = Link->ForwardLink) {\r
CurrentNotify = TEXT_IN_EX_SPLITTER_NOTIFY_FROM_THIS (Link);\r
- if (CurrentNotify->NotifyHandle == NotificationHandle) {\r
+ if (CurrentNotify == NotificationHandle) {\r
for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
- Status = Private->TextInExList[Index]->UnregisterKeyNotify (\r
- Private->TextInExList[Index],\r
- CurrentNotify->NotifyHandleList[Index]\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ Private->TextInExList[Index]->UnregisterKeyNotify (\r
+ Private->TextInExList[Index],\r
+ CurrentNotify->NotifyHandleList[Index]\r
+ );\r
}\r
RemoveEntryList (&CurrentNotify->NotifyEntry);\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
EFI_STATUS Status;\r
TEXT_OUT_SPLITTER_PRIVATE_DATA *Private;\r
UINTN Index;\r
- UINTN BackSpaceCount;\r
EFI_STATUS ReturnStatus;\r
- CHAR16 *TargetString;\r
+ UINTN MaxColumn;\r
+ UINTN MaxRow;\r
\r
This->SetAttribute (This, This->Mode->Attribute);\r
\r
Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This);\r
\r
- BackSpaceCount = 0;\r
-\r
- for (TargetString = WString; *TargetString != L'\0'; TargetString++) {\r
- if (*TargetString == CHAR_BACKSPACE) {\r
- BackSpaceCount++;\r
- }\r
- }\r
-\r
- if (BackSpaceCount == 0) {\r
- TargetString = WString;\r
- } else {\r
- TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1));\r
- ASSERT (TargetString != NULL);\r
-\r
- StrCpy (TargetString, WString);\r
- }\r
//\r
// return the worst status met\r
//\r
for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) {\r
Status = Private->TextOutList[Index].TextOut->OutputString (\r
Private->TextOutList[Index].TextOut,\r
- TargetString\r
+ WString\r
);\r
if (EFI_ERROR (Status)) {\r
ReturnStatus = Status;\r
if (Private->CurrentNumberOfConsoles > 0) {\r
Private->TextOutMode.CursorColumn = Private->TextOutList[0].TextOut->Mode->CursorColumn;\r
Private->TextOutMode.CursorRow = Private->TextOutList[0].TextOut->Mode->CursorRow;\r
- }\r
+ } else {\r
+ //\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->TextOut,\r
+ Private->TextOutMode.Mode,\r
+ &MaxColumn,\r
+ &MaxRow\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
+ } else if (Private->TextOutMode.CursorColumn > 0) {\r
+ Private->TextOutMode.CursorColumn--;\r
+ }\r
+ break;\r
+\r
+ case CHAR_LINEFEED:\r
+ if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {\r
+ Private->TextOutMode.CursorRow++;\r
+ }\r
+ break;\r
\r
- if (BackSpaceCount > 0) {\r
- FreePool (TargetString);\r
+ case CHAR_CARRIAGE_RETURN:\r
+ Private->TextOutMode.CursorColumn = 0;\r
+ break;\r
+\r
+ default:\r
+ if (Private->TextOutMode.CursorColumn < (INT32) (MaxColumn - 1)) {\r
+ Private->TextOutMode.CursorColumn++;\r
+ } else {\r
+ Private->TextOutMode.CursorColumn = 0;\r
+ if (Private->TextOutMode.CursorRow < (INT32) (MaxRow - 1)) {\r
+ Private->TextOutMode.CursorRow++;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ }\r
}\r
\r
return ReturnStatus;\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