From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 5F12582377 for ; Thu, 22 Dec 2016 05:43:31 -0800 (PST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga103.fm.intel.com with ESMTP; 22 Dec 2016 05:43:30 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,388,1477983600"; d="scan'208";a="21654138" Received: from shwdeopenpsi068.ccr.corp.intel.com ([10.239.9.9]) by orsmga002.jf.intel.com with ESMTP; 22 Dec 2016 05:43:29 -0800 From: Star Zeng To: edk2-devel@lists.01.org Cc: Star Zeng , Ruiyu Ni , Michael Kinney , Feng Tian Date: Thu, 22 Dec 2016 21:43:17 +0800 Message-Id: <1482414197-32744-1-git-send-email-star.zeng@intel.com> X-Mailer: git-send-email 2.7.0.windows.1 Subject: [PATCH] MdeModulePkg ConSplitterDxe: Support toggle state sync X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Dec 2016 13:43:31 -0000 Register key notify for toggle state (CapsLock, NumLock and ScrollLock) sync between multiple keyboards. The implementation for this feature requires keyboard driver supports EFI_KEY_STATE_EXPOSED, and turns on physical TextInEx partial key report for toggle state sync. The virtual TextInEx will report the partial key after it is required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly. Cc: Ruiyu Ni Cc: Michael Kinney Cc: Feng Tian Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Star Zeng --- .../Universal/Console/ConSplitterDxe/ConSplitter.c | 208 ++++++++++++++++++++- .../Universal/Console/ConSplitterDxe/ConSplitter.h | 5 +- 2 files changed, 206 insertions(+), 7 deletions(-) diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c index 493bcbafdf39..203ad7b06e20 100644 --- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c @@ -67,6 +67,8 @@ GLOBAL_REMOVE_IF_UNREFERENCED TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = { (LIST_ENTRY *) NULL, (LIST_ENTRY *) NULL }, + 0, + FALSE, { ConSplitterSimplePointerReset, @@ -301,6 +303,157 @@ EFI_DRIVER_BINDING_PROTOCOL gConSplitterAbsolutePointerDriverBinding = }; /** + Sync current toggle state to new console input device. + + @param TextInEx Simple Text Input Ex Input protocol pointer. + +**/ +VOID +ToggleStateSyncToNewConInDev ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx + ) +{ + // + // Sync current toggle state to this new console input device. + // + TextInEx->SetState (TextInEx, &mConIn.PhysicalKeyToggleState); +} + +/** + Key notify for toggle state sync. + + @param KeyData A pointer to a buffer that is filled in with + the keystroke information for the key that was + pressed. + + @retval EFI_SUCCESS Toggle state sync successfully. + +**/ +EFI_STATUS +EFIAPI +ToggleStateSyncKeyNotify ( + IN EFI_KEY_DATA *KeyData + ) +{ + UINTN Index; + + if (((KeyData->KeyState.KeyToggleState & KEY_STATE_VALID_EXPOSED) == KEY_STATE_VALID_EXPOSED) && + (KeyData->KeyState.KeyToggleState != mConIn.PhysicalKeyToggleState)) { + // + // There is toggle state change, sync to other console input devices. + // + for (Index = 0; Index < mConIn.CurrentNumberOfExConsoles; Index++) { + mConIn.TextInExList[Index]->SetState ( + mConIn.TextInExList[Index], + &KeyData->KeyState.KeyToggleState + ); + } + mConIn.PhysicalKeyToggleState = KeyData->KeyState.KeyToggleState; + DEBUG ((EFI_D_INFO, "Current toggle state is 0x%02x\n", mConIn.PhysicalKeyToggleState)); + } + + return EFI_SUCCESS; +} + +/** + Initialization for toggle state sync. + + @param Private Text In Splitter pointer. + +**/ +VOID +ToggleStateSyncInitialization ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private + ) +{ + EFI_KEY_DATA KeyData; + VOID *NotifyHandle; + + // + // Initialize PhysicalKeyToggleState that will be synced to new console + // input device to turn on physical TextInEx partial key report for + // toggle state sync. + // + Private->PhysicalKeyToggleState = KEY_STATE_VALID_EXPOSED; + + // + // Initialize VirtualKeyStateExported to let the virtual TextInEx not report + // the partial key even though the physical TextInEx turns on the partial + // key report. The virtual TextInEx will report the partial key after it is + // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly. + // + Private->VirtualKeyStateExported = FALSE; + + // + // Register key notify for toggle state sync. + // + KeyData.Key.ScanCode = SCAN_NULL; + KeyData.Key.UnicodeChar = CHAR_NULL; + KeyData.KeyState.KeyShiftState = 0; + KeyData.KeyState.KeyToggleState = 0; + Private->TextInEx.RegisterKeyNotify ( + &Private->TextInEx, + &KeyData, + ToggleStateSyncKeyNotify, + &NotifyHandle + ); +} + +/** + Reinitialization for toggle state sync. + + @param Private Text In Splitter pointer. + +**/ +VOID +ToggleStateSyncReInitialization ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private + ) +{ + UINTN Index; + + // + // Reinitialize PhysicalKeyToggleState that will be synced to new console + // input device to turn on physical TextInEx partial key report for + // toggle state sync. + // + Private->PhysicalKeyToggleState = KEY_STATE_VALID_EXPOSED; + + // + // Reinitialize VirtualKeyStateExported to let the virtual TextInEx not report + // the partial key even though the physical TextInEx turns on the partial + // key report. The virtual TextInEx will report the partial key after it is + // required by calling SetState(X | KEY_STATE_VALID_EXPOSED) explicitly. + // + Private->VirtualKeyStateExported = FALSE; + + for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { + Private->TextInExList[Index]->SetState ( + Private->TextInExList[Index], + &Private->PhysicalKeyToggleState + ); + } +} + +/** + Toggle state sync hook SetState. + + @param KeyToggleState Pointer to key toggle state. + +**/ +VOID +ToggleStateSyncHookSetState ( + IN OUT EFI_KEY_TOGGLE_STATE *KeyToggleState + ) +{ + // + // Always turn on physical TextInEx partial key report for + // toggle state sync. + // + *KeyToggleState |= EFI_KEY_STATE_EXPOSED; +} + +/** The Entry Point for module ConSplitter. The user code starts with this function. Installs driver module protocols and. Creates virtual device handles for ConIn, @@ -538,6 +691,8 @@ ConSplitterTextInConstructor ( InitializeListHead (&ConInPrivate->NotifyList); + ToggleStateSyncInitialization (ConInPrivate); + ConInPrivate->AbsolutePointer.Mode = &ConInPrivate->AbsolutePointerMode; // // Allocate buffer for Absolute Pointer device @@ -1890,6 +2045,8 @@ ConSplitterTextInExAddDevice ( Private->TextInExList[Private->CurrentNumberOfExConsoles] = TextInEx; Private->CurrentNumberOfExConsoles++; + ToggleStateSyncToNewConInDev (TextInEx); + // // Extra CheckEvent added to reduce the double CheckEvent(). // @@ -3321,6 +3478,10 @@ ConSplitterTextInReset ( } } + if (!EFI_ERROR (ReturnStatus)) { + ToggleStateSyncReInitialization (Private); + } + return ReturnStatus; } @@ -3363,8 +3524,18 @@ ConSplitterTextInPrivateReadKeyStroke ( &CurrentKey ); if (!EFI_ERROR (Status)) { - *Key = CurrentKey; - return Status; + // + // If it is partial keystroke, skip it. + // + if ((CurrentKey.ScanCode == CHAR_NULL) && (CurrentKey.UnicodeChar == SCAN_NULL)) { + // + // Try to read key from this physical console input device again. + // + Index--; + } else { + *Key = CurrentKey; + return Status; + } } } @@ -3542,6 +3713,10 @@ ConSplitterTextInResetEx ( } } + if (!EFI_ERROR (ReturnStatus)) { + ToggleStateSyncReInitialization (Private); + } + return ReturnStatus; } @@ -3607,8 +3782,22 @@ ConSplitterTextInReadKeyStrokeEx ( &CurrentKeyData ); if (!EFI_ERROR (Status)) { - CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData)); - return Status; + // + // If it is partial keystroke, check if virtual KeyState has been required to be exposed. + // + if ((CurrentKeyData.Key.ScanCode == CHAR_NULL) && (CurrentKeyData.Key.UnicodeChar == SCAN_NULL)) { + if (Private->VirtualKeyStateExported) { + CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData)); + return Status; + } + // + // Try to read key from this physical console input device again. + // + Index--; + } else { + CopyMem (KeyData, &CurrentKeyData, sizeof (CurrentKeyData)); + return Status; + } } } @@ -3641,6 +3830,7 @@ ConSplitterTextInSetState ( TEXT_IN_SPLITTER_PRIVATE_DATA *Private; EFI_STATUS Status; UINTN Index; + EFI_KEY_TOGGLE_STATE PhysicalKeyToggleState; if (KeyToggleState == NULL) { return EFI_INVALID_PARAMETER; @@ -3648,6 +3838,9 @@ ConSplitterTextInSetState ( Private = TEXT_IN_EX_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + PhysicalKeyToggleState = *KeyToggleState; + ToggleStateSyncHookSetState (&PhysicalKeyToggleState); + // // if no physical console input device exists, return EFI_SUCCESS; // otherwise return the status of setting state of physical console input device @@ -3655,13 +3848,16 @@ ConSplitterTextInSetState ( for (Index = 0; Index < Private->CurrentNumberOfExConsoles; Index++) { Status = Private->TextInExList[Index]->SetState ( Private->TextInExList[Index], - KeyToggleState + &PhysicalKeyToggleState ); if (EFI_ERROR (Status)) { return Status; } } + Private->PhysicalKeyToggleState = PhysicalKeyToggleState; + Private->VirtualKeyStateExported = (((*KeyToggleState) & EFI_KEY_STATE_EXPOSED) != 0); + return EFI_SUCCESS; } @@ -3765,7 +3961,7 @@ ConSplitterTextInRegisterKeyNotify ( } } - InsertTailList (&mConIn.NotifyList, &NewNotify->NotifyEntry); + InsertTailList (&Private->NotifyList, &NewNotify->NotifyEntry); *NotifyHandle = NewNotify; diff --git a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h index e32abbaea133..99ac5b55d302 100644 --- a/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h +++ b/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h @@ -1,7 +1,7 @@ /** @file Private data structures for the Console Splitter driver -Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.
+Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at @@ -88,6 +88,7 @@ typedef struct { UINTN Rows; } TEXT_OUT_SPLITTER_QUERY_DATA; +#define KEY_STATE_VALID_EXPOSED (EFI_TOGGLE_STATE_VALID | EFI_KEY_STATE_EXPOSED) #define TEXT_IN_EX_SPLITTER_NOTIFY_SIGNATURE SIGNATURE_32 ('T', 'i', 'S', 'n') @@ -128,6 +129,8 @@ typedef struct { EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL **TextInExList; UINTN TextInExListCount; LIST_ENTRY NotifyList; + EFI_KEY_TOGGLE_STATE PhysicalKeyToggleState; + BOOLEAN VirtualKeyStateExported; EFI_SIMPLE_POINTER_PROTOCOL SimplePointer; -- 2.7.0.windows.1