never removed. Such design ensures sytem 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
+ 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
&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
)\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
Status = gBS->CreateEventEx (\r
EVT_NOTIFY_SIGNAL,\r
TPL_CALLBACK,\r
- ConSplitterEmptyCallbackFunction,\r
+ EfiEventEmptyFunction,\r
NULL,\r
&gConnectConInEventGuid,\r
&ConInPrivate->ConnectConInEvent\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
return Status;\r
}\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
Size = Private->CurrentNumberOfConsoles * sizeof (INT32);\r
Index = 0;\r
SrcAddress = OldTextOutModeMap;\r
- NewStepSize = NewSize / sizeof(INT32); \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
//\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
// 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
\r
DeviceStatus = EFI_DEVICE_ERROR;\r
Status = EFI_DEVICE_ERROR;\r
- \r
+\r
//\r
// This device display mode will be added into Graphics Ouput modes.\r
//\r
//\r
ConsplitterSetConsoleOutMode (Private);\r
\r
+ Private->AddingConOutDevice = FALSE;\r
+\r
return Status;\r
}\r
\r
Private->VirtualHandle,\r
&gEfiUgaDrawProtocolGuid,\r
&Private->UgaDraw\r
- ); \r
+ );\r
} else if (!FeaturePcdGet (PcdConOutUgaSupport)) {\r
Status = gBS->UninstallProtocolInterface (\r
Private->VirtualHandle,\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
// 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
+ 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
\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
//\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
+ 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
}\r
}\r
\r
- InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+ InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);\r
\r
*NotifyHandle = NewNotify;\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
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
-\r
-/**\r
- An empty function to pass error checking of CreateEventEx ().\r
-\r
- @param Event Event whose notification function is being invoked.\r
- @param Context Pointer to the notification function's context,\r
- which is implementation-dependent.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-ConSplitterEmptyCallbackFunction (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
-}\r