(LIST_ENTRY *) NULL,\r
(LIST_ENTRY *) NULL\r
},\r
+ 0,\r
+ FALSE,\r
\r
{\r
ConSplitterSimplePointerReset,\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
\r
InitializeListHead (&ConInPrivate->NotifyList);\r
\r
+ ToggleStateSyncInitialization (ConInPrivate);\r
+\r
ConInPrivate->AbsolutePointer.Mode = &ConInPrivate->AbsolutePointerMode;\r
//\r
// Allocate buffer for Absolute Pointer device\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
}\r
\r
+ if (!EFI_ERROR (ReturnStatus)) {\r
+ ToggleStateSyncReInitialization (Private);\r
+ }\r
+\r
return ReturnStatus;\r
}\r
\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
);\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 ((CurrentKey.ScanCode != CHAR_NULL) || (CurrentKey.UnicodeChar != SCAN_NULL)) {\r
+ *Key = CurrentKey;\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
+ if (!EFI_ERROR (ReturnStatus)) {\r
+ ToggleStateSyncReInitialization (Private);\r
+ }\r
+\r
return ReturnStatus;\r
\r
}\r
// if any physical console input device has key input,\r
// return the key and EFI_SUCCESS.\r
//\r
- for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) {\r
+ for (Index = 0; Index < Private->CurrentNumberOfExConsoles;) {\r
Status = Private->TextInExList[Index]->ReadKeyStrokeEx (\r
Private->TextInExList[Index],\r
&CurrentKeyData\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, return the key. Otherwise, continue to read key\r
+ // from THIS physical console input device.\r
+ //\r
+ if ((Private->VirtualKeyStateExported) ||\r
+ (CurrentKeyData.Key.ScanCode != CHAR_NULL) ||\r
+ (CurrentKeyData.Key.UnicodeChar != SCAN_NULL)) {\r
+ CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData));\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
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
}\r
}\r
\r
- InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry);\r
+ InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry);\r
\r
*NotifyHandle = NewNotify;\r
\r