mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
820 lines
20 KiB
C
820 lines
20 KiB
C
/** @file
|
|
|
|
AppleEventDxe
|
|
|
|
Copyright (c) 2018, vit9696
|
|
|
|
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
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include <AppleMacEfi.h>
|
|
|
|
#include <IndustryStandard/AppleHid.h>
|
|
|
|
#include <Protocol/AppleKeyMapAggregator.h>
|
|
#include <Protocol/ConsoleControl.h>
|
|
|
|
#include <Library/AppleEventLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiLib.h>
|
|
|
|
#include "AppleEventInternal.h"
|
|
|
|
// KEY_STROKE_DELAY
|
|
#define KEY_STROKE_DELAY 5
|
|
|
|
// KEY_STROKE_POLL_FREQUENCY
|
|
#define KEY_STROKE_POLL_FREQUENCY EFI_TIMER_PERIOD_MILLISECONDS (10)
|
|
|
|
// KEY_STROKE_INFORMATION
|
|
typedef struct {
|
|
APPLE_KEY_CODE AppleKeyCode; ///<
|
|
UINTN NumberOfStrokes; ///<
|
|
BOOLEAN CurrentStroke; ///<
|
|
} KEY_STROKE_INFORMATION;
|
|
|
|
// mCLockOn
|
|
STATIC BOOLEAN mCLockOn = FALSE;
|
|
|
|
// mKeyStrokePollEvent
|
|
STATIC EFI_EVENT mKeyStrokePollEvent = NULL;
|
|
|
|
// mModifiers
|
|
STATIC APPLE_MODIFIER_MAP mModifiers = 0;
|
|
|
|
// mPreviousModifiers
|
|
STATIC APPLE_MODIFIER_MAP mPreviousModifiers = 0;
|
|
|
|
// mInitialized
|
|
STATIC BOOLEAN mInitialized = FALSE;
|
|
|
|
// mKeyInformation
|
|
STATIC KEY_STROKE_INFORMATION mKeyStrokeInfo[10];
|
|
|
|
// mCLockChanged
|
|
STATIC BOOLEAN mCLockChanged = FALSE;
|
|
|
|
// mKeyInitialDelay
|
|
// mKeySubsequentDelay
|
|
// Apple implementation default values
|
|
STATIC UINTN mKeyInitialDelay = 50;
|
|
STATIC UINTN mKeySubsequentDelay = 5;
|
|
|
|
// mGraphicsInputMirroring
|
|
STATIC BOOLEAN mGraphicsInputMirroring = FALSE;
|
|
|
|
// mAppleKeyMapAggregator
|
|
STATIC APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *mKeyMapAggregator = NULL;
|
|
|
|
// InternalSetKeyBehaviour
|
|
VOID
|
|
InternalSetKeyBehaviour (
|
|
IN BOOLEAN CustomDelays,
|
|
IN UINT16 KeyInitialDelay,
|
|
IN UINT16 KeySubsequentDelay,
|
|
IN BOOLEAN GraphicsInputMirroring
|
|
)
|
|
{
|
|
if (CustomDelays) {
|
|
//
|
|
// Zero is meaningful
|
|
//
|
|
mKeyInitialDelay = KeyInitialDelay;
|
|
|
|
//
|
|
// Zero is meaningless (also div by zero expception): warn and use 1
|
|
//
|
|
if (KeySubsequentDelay == 0) {
|
|
KeySubsequentDelay = 1;
|
|
DEBUG ((DEBUG_WARN, "OCAE: Illegal KeySubsequentDelay value 0, using 1\n"));
|
|
}
|
|
|
|
mKeySubsequentDelay = KeySubsequentDelay;
|
|
|
|
DEBUG ((DEBUG_INFO, "OCAE: Using key delays %d (%d0ms) and %d (%d0ms)\n", mKeyInitialDelay, mKeyInitialDelay, mKeySubsequentDelay, mKeySubsequentDelay));
|
|
}
|
|
|
|
mGraphicsInputMirroring = GraphicsInputMirroring;
|
|
}
|
|
|
|
// InternalGetAppleKeyStrokes
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalGetAppleKeyStrokes (
|
|
OUT APPLE_MODIFIER_MAP *Modifiers,
|
|
OUT UINTN *NumberOfKeyCodes,
|
|
OUT APPLE_KEY_CODE **KeyCodes
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalGetAppleKeyStrokes\n"));
|
|
|
|
Status = EFI_UNSUPPORTED;
|
|
|
|
if (mKeyMapAggregator != NULL) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
|
|
if ( (Modifiers != NULL)
|
|
&& (NumberOfKeyCodes != NULL)
|
|
&& (KeyCodes != NULL))
|
|
{
|
|
*NumberOfKeyCodes = 0;
|
|
*KeyCodes = NULL;
|
|
Status = mKeyMapAggregator->GetKeyStrokes (
|
|
mKeyMapAggregator,
|
|
Modifiers,
|
|
NumberOfKeyCodes,
|
|
NULL
|
|
);
|
|
|
|
if (!EFI_ERROR (Status) || (Status == EFI_BUFFER_TOO_SMALL)) {
|
|
if (*NumberOfKeyCodes == 0) {
|
|
*KeyCodes = NULL;
|
|
} else {
|
|
*KeyCodes = AllocateZeroPool (
|
|
*NumberOfKeyCodes * sizeof (**KeyCodes)
|
|
);
|
|
|
|
if (*KeyCodes == NULL) {
|
|
*NumberOfKeyCodes = 0;
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
DEBUG ((DEBUG_VERBOSE, "InternalGetAppleKeyStrokes alloc failure\n"));
|
|
} else {
|
|
Status = mKeyMapAggregator->GetKeyStrokes (
|
|
mKeyMapAggregator,
|
|
Modifiers,
|
|
NumberOfKeyCodes,
|
|
*KeyCodes
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool ((VOID *)*KeyCodes);
|
|
|
|
*KeyCodes = NULL;
|
|
*NumberOfKeyCodes = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// InternalGetModifierStrokes
|
|
APPLE_MODIFIER_MAP
|
|
InternalGetModifierStrokes (
|
|
VOID
|
|
)
|
|
{
|
|
APPLE_MODIFIER_MAP Modifiers;
|
|
EFI_STATUS Status;
|
|
UINTN NumberOfKeyCodes;
|
|
APPLE_KEY_CODE *KeyCodes;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalGetModifierStrokes\n"));
|
|
|
|
Status = InternalGetAppleKeyStrokes (
|
|
&Modifiers,
|
|
&NumberOfKeyCodes,
|
|
&KeyCodes
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
if (KeyCodes != NULL) {
|
|
FreePool ((VOID *)KeyCodes);
|
|
}
|
|
} else {
|
|
Modifiers = 0;
|
|
}
|
|
|
|
return Modifiers;
|
|
}
|
|
|
|
// InternalAppleKeyEventDataFromInputKey
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalAppleKeyEventDataFromInputKey (
|
|
OUT APPLE_EVENT_DATA *EventData,
|
|
IN APPLE_KEY_CODE *AppleKeyCode,
|
|
IN EFI_INPUT_KEY *InputKey
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
APPLE_KEY_EVENT_DATA *KeyEventData;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalAppleKeyEventDataFromInputKey\n"));
|
|
|
|
Status = EFI_INVALID_PARAMETER;
|
|
|
|
if ((EventData != NULL) && (AppleKeyCode != NULL) && (InputKey != NULL)) {
|
|
KeyEventData = AllocateZeroPool (sizeof (*KeyEventData));
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
|
|
if (KeyEventData != NULL) {
|
|
KeyEventData->NumberOfKeyPairs = 1;
|
|
KeyEventData->InputKey = *InputKey;
|
|
|
|
CopyMem (
|
|
(VOID *)&KeyEventData->AppleKeyCode,
|
|
(VOID *)AppleKeyCode,
|
|
sizeof (*AppleKeyCode)
|
|
);
|
|
|
|
EventData->KeyData = KeyEventData;
|
|
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// InternalGetAndRemoveReleasedKeys
|
|
STATIC
|
|
UINTN
|
|
InternalGetAndRemoveReleasedKeys (
|
|
IN CONST UINTN *NumberOfKeyCodes,
|
|
IN CONST APPLE_KEY_CODE *KeyCodes,
|
|
OUT APPLE_KEY_CODE **ReleasedKeys
|
|
)
|
|
{
|
|
UINTN NumberOfReleasedKeys;
|
|
UINTN Index;
|
|
UINTN Index2;
|
|
APPLE_KEY_CODE ReleasedKeysBuffer[12];
|
|
UINTN ReleasedKeysSize;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalGetAndRemoveReleasedKeys\n"));
|
|
|
|
NumberOfReleasedKeys = 0;
|
|
|
|
for (Index = 0; Index < ARRAY_SIZE (mKeyStrokeInfo); ++Index) {
|
|
for (Index2 = 0; Index2 < *NumberOfKeyCodes; ++Index2) {
|
|
if (mKeyStrokeInfo[Index].AppleKeyCode == KeyCodes[Index2]) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (*NumberOfKeyCodes == Index2) {
|
|
if (mKeyStrokeInfo[Index].AppleKeyCode != 0) {
|
|
ReleasedKeysBuffer[NumberOfReleasedKeys] = mKeyStrokeInfo[Index].AppleKeyCode;
|
|
++NumberOfReleasedKeys;
|
|
}
|
|
|
|
ZeroMem (
|
|
&mKeyStrokeInfo[Index],
|
|
sizeof (mKeyStrokeInfo[Index])
|
|
);
|
|
}
|
|
}
|
|
|
|
// Add CLock to released keys if applicable and set bool to FALSE.
|
|
|
|
if (mCLockChanged) {
|
|
for (Index = 0; Index < *NumberOfKeyCodes; ++Index) {
|
|
if (KeyCodes[Index] == AppleHidUsbKbUsageKeyCLock) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (*NumberOfKeyCodes == Index) {
|
|
mCLockChanged = FALSE;
|
|
|
|
ReleasedKeysBuffer[NumberOfReleasedKeys] = AppleHidUsbKbUsageKeyCLock;
|
|
++NumberOfReleasedKeys;
|
|
}
|
|
}
|
|
|
|
// Allocate a heap buffer to return.
|
|
|
|
*ReleasedKeys = NULL;
|
|
|
|
if (NumberOfReleasedKeys > 0) {
|
|
ReleasedKeysSize = (sizeof (**ReleasedKeys) * NumberOfReleasedKeys);
|
|
*ReleasedKeys = AllocateZeroPool (ReleasedKeysSize);
|
|
|
|
if (*ReleasedKeys != NULL) {
|
|
CopyMem (
|
|
(VOID *)*ReleasedKeys,
|
|
(VOID *)&ReleasedKeysBuffer[0],
|
|
ReleasedKeysSize
|
|
);
|
|
} else {
|
|
NumberOfReleasedKeys = 0;
|
|
}
|
|
}
|
|
|
|
return NumberOfReleasedKeys;
|
|
}
|
|
|
|
// InternalIsCLockOn
|
|
STATIC
|
|
BOOLEAN
|
|
InternalIsCLockOn (
|
|
IN CONST UINTN *NumberOfKeyCodes,
|
|
IN CONST APPLE_KEY_CODE *KeyCodes
|
|
)
|
|
{
|
|
BOOLEAN CLockOn;
|
|
UINTN Index;
|
|
UINTN Index2;
|
|
KEY_STROKE_INFORMATION *KeyInfo;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalIsCLockOn\n"));
|
|
|
|
//
|
|
// Check against invalid usage
|
|
//
|
|
if ( (NumberOfKeyCodes == NULL)
|
|
|| ((*NumberOfKeyCodes != 0) && (KeyCodes == NULL)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Return the previous value by default
|
|
//
|
|
CLockOn = mCLockOn;
|
|
|
|
for (Index = 0; Index < *NumberOfKeyCodes; ++Index) {
|
|
KeyInfo = NULL;
|
|
|
|
for (Index2 = 0; Index2 < ARRAY_SIZE (mKeyStrokeInfo); ++Index2) {
|
|
if (mKeyStrokeInfo[Index2].AppleKeyCode == KeyCodes[Index]) {
|
|
KeyInfo = &mKeyStrokeInfo[Index2];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( (KeyInfo == NULL)
|
|
&& (KeyCodes[Index] == AppleHidUsbKbUsageKeyCLock)
|
|
&& !mCLockChanged)
|
|
{
|
|
CLockOn = (BOOLEAN)mCLockOn == FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return CLockOn;
|
|
}
|
|
|
|
// InternalGetCurrentStroke
|
|
STATIC
|
|
KEY_STROKE_INFORMATION *
|
|
InternalGetCurrentStroke (
|
|
VOID
|
|
)
|
|
{
|
|
KEY_STROKE_INFORMATION *KeyInfo;
|
|
UINTN Index;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalGetCurrentStroke\n"));
|
|
|
|
KeyInfo = NULL;
|
|
|
|
for (Index = 0; Index < ARRAY_SIZE (mKeyStrokeInfo); ++Index) {
|
|
if (mKeyStrokeInfo[Index].CurrentStroke) {
|
|
KeyInfo = &mKeyStrokeInfo[Index];
|
|
break;
|
|
}
|
|
}
|
|
|
|
return KeyInfo;
|
|
}
|
|
|
|
// InternalGetCurrentKeyStroke
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalGetCurrentKeyStroke (
|
|
IN APPLE_MODIFIER_MAP Modifiers,
|
|
IN OUT UINTN *NumberOfKeyCodes,
|
|
IN OUT APPLE_KEY_CODE *KeyCodes,
|
|
IN OUT EFI_INPUT_KEY *Key
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
KEY_STROKE_INFORMATION *KeyInfo;
|
|
UINTN Index;
|
|
UINTN NumberOfReleasedKeys;
|
|
APPLE_KEY_CODE *ReleasedKeys;
|
|
BOOLEAN CLockOn;
|
|
APPLE_MODIFIER_MAP AppleModifiers;
|
|
BOOLEAN ShiftPressed;
|
|
EFI_INPUT_KEY InputKey;
|
|
APPLE_EVENT_DATA AppleEventData;
|
|
UINTN NewKeyIndex;
|
|
BOOLEAN AcceptStroke;
|
|
BOOLEAN Shifted;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalGetCurrentKeyStroke\n"));
|
|
|
|
if (mModifiers != Modifiers) {
|
|
for (Index = 0; Index < ARRAY_SIZE (mKeyStrokeInfo); ++Index) {
|
|
mKeyStrokeInfo[Index].CurrentStroke = FALSE;
|
|
}
|
|
}
|
|
|
|
NumberOfReleasedKeys = InternalGetAndRemoveReleasedKeys (
|
|
NumberOfKeyCodes,
|
|
KeyCodes,
|
|
&ReleasedKeys
|
|
);
|
|
|
|
CLockOn = InternalIsCLockOn (NumberOfKeyCodes, KeyCodes);
|
|
|
|
AppleModifiers = Modifiers;
|
|
|
|
if (CLockOn) {
|
|
AppleModifiers |= APPLE_MODIFIERS_SHIFT;
|
|
}
|
|
|
|
ShiftPressed = (BOOLEAN)((AppleModifiers & APPLE_MODIFIERS_SHIFT) != 0);
|
|
|
|
for (Index = 0; Index < NumberOfReleasedKeys; ++Index) {
|
|
EventInputKeyFromAppleKeyCode (
|
|
ReleasedKeys[Index],
|
|
&InputKey,
|
|
ShiftPressed
|
|
);
|
|
|
|
AppleEventData.KeyData = NULL;
|
|
Status = InternalAppleKeyEventDataFromInputKey (
|
|
&AppleEventData,
|
|
&ReleasedKeys[Index],
|
|
&InputKey
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
|
|
EventCreateEventQueue (
|
|
AppleEventData,
|
|
APPLE_EVENT_TYPE_KEY_UP,
|
|
AppleModifiers
|
|
);
|
|
}
|
|
|
|
if (ReleasedKeys != NULL) {
|
|
FreePool ((VOID *)ReleasedKeys);
|
|
}
|
|
|
|
if (CLockOn != mCLockOn) {
|
|
mCLockOn = CLockOn;
|
|
mCLockChanged = TRUE;
|
|
}
|
|
|
|
//
|
|
// Increase the number of strokes for all currently pressed keys.
|
|
//
|
|
for (NewKeyIndex = 0; NewKeyIndex < *NumberOfKeyCodes; ++NewKeyIndex) {
|
|
KeyInfo = NULL;
|
|
|
|
for (Index = 0; Index < ARRAY_SIZE (mKeyStrokeInfo); ++Index) {
|
|
if (mKeyStrokeInfo[Index].AppleKeyCode == KeyCodes[NewKeyIndex]) {
|
|
KeyInfo = &mKeyStrokeInfo[Index];
|
|
KeyInfo->NumberOfStrokes++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Indicates a key has been pressed which is not part of mKeyInformation.
|
|
//
|
|
if (KeyInfo == NULL) {
|
|
//
|
|
// If a new key is pressed, cancel all previous inputs.
|
|
//
|
|
for (Index = 0; Index < ARRAY_SIZE (mKeyStrokeInfo); ++Index) {
|
|
mKeyStrokeInfo[Index].CurrentStroke = FALSE;
|
|
}
|
|
|
|
//
|
|
// Insert the new key into a buffer
|
|
//
|
|
for (Index = 0; Index < ARRAY_SIZE (mKeyStrokeInfo); ++Index) {
|
|
if (mKeyStrokeInfo[Index].AppleKeyCode == 0) {
|
|
KeyInfo = &mKeyStrokeInfo[Index];
|
|
KeyInfo->AppleKeyCode = KeyCodes[NewKeyIndex];
|
|
KeyInfo->CurrentStroke = TRUE;
|
|
KeyInfo->NumberOfStrokes = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// CHECKME: is it intentional?
|
|
break;
|
|
}
|
|
}
|
|
|
|
KeyInfo = InternalGetCurrentStroke ();
|
|
|
|
Status = EFI_NOT_READY;
|
|
|
|
if ((KeyInfo != NULL) || (mModifiers != Modifiers)) {
|
|
mModifiers = Modifiers;
|
|
|
|
//
|
|
// Verify the timeframe the key has been pressed.
|
|
//
|
|
|
|
if (KeyInfo != NULL) {
|
|
AcceptStroke = (BOOLEAN)(
|
|
(KeyInfo->NumberOfStrokes < mKeyInitialDelay)
|
|
? (KeyInfo->NumberOfStrokes == 0)
|
|
: (((KeyInfo->NumberOfStrokes - mKeyInitialDelay) % mKeySubsequentDelay) == 0)
|
|
);
|
|
|
|
if (AcceptStroke) {
|
|
*NumberOfKeyCodes = 1;
|
|
*KeyCodes = KeyInfo->AppleKeyCode;
|
|
|
|
Shifted = (BOOLEAN)(
|
|
(IS_APPLE_KEY_LETTER (KeyInfo->AppleKeyCode) && CLockOn)
|
|
!= ((mModifiers & APPLE_MODIFIERS_SHIFT) != 0)
|
|
);
|
|
|
|
EventInputKeyFromAppleKeyCode (
|
|
KeyInfo->AppleKeyCode,
|
|
Key,
|
|
Shifted
|
|
);
|
|
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
} else {
|
|
//
|
|
// Report that no keys were pressed.
|
|
//
|
|
*NumberOfKeyCodes = 0;
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// CreateAppleKeyCodeDescriptorsFromKeyStrokes
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalAppleEventDataFromCurrentKeyStroke (
|
|
IN OUT APPLE_EVENT_DATA *EventData,
|
|
IN OUT APPLE_MODIFIER_MAP *Modifiers
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_INPUT_KEY InputKey;
|
|
APPLE_KEY_CODE *KeyCodes;
|
|
APPLE_MODIFIER_MAP AppleModifiers;
|
|
UINTN NumberOfKeyCodes;
|
|
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl;
|
|
EFI_CONSOLE_CONTROL_SCREEN_MODE Mode;
|
|
UINTN Index;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalAppleEventDataFromCurrentKeyStroke\n"));
|
|
|
|
ZeroMem (&InputKey, sizeof (InputKey));
|
|
|
|
KeyCodes = NULL;
|
|
|
|
Status = EFI_UNSUPPORTED;
|
|
|
|
if ( (mKeyMapAggregator != NULL)
|
|
&& (EventData != NULL)
|
|
&& (Modifiers != NULL))
|
|
{
|
|
AppleModifiers = 0;
|
|
NumberOfKeyCodes = 0;
|
|
|
|
InternalGetAppleKeyStrokes (
|
|
&AppleModifiers,
|
|
&NumberOfKeyCodes,
|
|
&KeyCodes
|
|
);
|
|
|
|
if (!mGraphicsInputMirroring) {
|
|
//
|
|
// Apple OEM AppleEvent unconditionally includes this logic, but
|
|
// when an AppleEvent handler such as CrScreenshotDxe is active
|
|
// this code will run and (not entirely consistently across different
|
|
// firmware) may prevent keystrokes from reaching ConIn-based UEFI GUI
|
|
// apps such as Windows BitLocker.
|
|
// REF: https://github.com/acidanthera/bugtracker/issues/1716
|
|
//
|
|
Mode = EfiConsoleControlScreenGraphics;
|
|
Status = gBS->LocateProtocol (
|
|
&gEfiConsoleControlProtocolGuid,
|
|
NULL,
|
|
(VOID *)&ConsoleControl
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
ConsoleControl->GetMode (ConsoleControl, &Mode, NULL, NULL);
|
|
}
|
|
|
|
if (Mode == EfiConsoleControlScreenGraphics) {
|
|
for (Index = 0; Index < (NumberOfKeyCodes + 1); ++Index) {
|
|
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &InputKey);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
*Modifiers = AppleModifiers;
|
|
Status = InternalGetCurrentKeyStroke (
|
|
AppleModifiers,
|
|
&NumberOfKeyCodes,
|
|
KeyCodes,
|
|
&InputKey
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = EFI_SUCCESS;
|
|
if (NumberOfKeyCodes > 0) {
|
|
InternalAppleKeyEventDataFromInputKey (EventData, KeyCodes, &InputKey);
|
|
}
|
|
}
|
|
|
|
if (KeyCodes) {
|
|
FreePool (KeyCodes);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// InternalKeyStrokePollNotifyFunction
|
|
STATIC
|
|
VOID
|
|
EFIAPI
|
|
InternalKeyStrokePollNotifyFunction (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
APPLE_EVENT_DATA EventData;
|
|
APPLE_MODIFIER_MAP Modifiers;
|
|
APPLE_MODIFIER_MAP PartialModifers;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "InternalKeyStrokePollNotifyFunction\n"));
|
|
|
|
EventData.KeyData = NULL;
|
|
Modifiers = 0;
|
|
Status = InternalAppleEventDataFromCurrentKeyStroke (
|
|
&EventData,
|
|
&Modifiers
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
if (EventData.KeyData != NULL) {
|
|
EventCreateEventQueue (EventData, APPLE_EVENT_TYPE_KEY_DOWN, Modifiers);
|
|
}
|
|
|
|
if (mPreviousModifiers != Modifiers) {
|
|
PartialModifers = ((mPreviousModifiers ^ Modifiers) & mPreviousModifiers);
|
|
|
|
if (PartialModifers != 0) {
|
|
EventData.KeyData = NULL;
|
|
|
|
EventCreateEventQueue (
|
|
EventData,
|
|
APPLE_EVENT_TYPE_MODIFIER_UP,
|
|
PartialModifers
|
|
);
|
|
}
|
|
|
|
PartialModifers = ((mPreviousModifiers ^ Modifiers) & Modifiers);
|
|
|
|
if (PartialModifers != 0) {
|
|
EventData.KeyData = NULL;
|
|
|
|
EventCreateEventQueue (
|
|
EventData,
|
|
APPLE_EVENT_TYPE_MODIFIER_DOWN,
|
|
PartialModifers
|
|
);
|
|
}
|
|
|
|
mPreviousModifiers = Modifiers;
|
|
}
|
|
}
|
|
}
|
|
|
|
// InternalInitializeKeyHandler
|
|
STATIC
|
|
VOID
|
|
InternalInitializeKeyHandler (
|
|
VOID
|
|
)
|
|
{
|
|
DEBUG ((DEBUG_VERBOSE, "InternalInitializeKeyHandler\n"));
|
|
|
|
if (!mInitialized) {
|
|
mInitialized = TRUE;
|
|
|
|
ZeroMem ((VOID *)&mKeyStrokeInfo[0], sizeof (mKeyStrokeInfo));
|
|
|
|
mModifiers = 0;
|
|
mCLockOn = FALSE;
|
|
mCLockChanged = FALSE;
|
|
}
|
|
}
|
|
|
|
// EventCreateKeyStrokePollEvent
|
|
EFI_STATUS
|
|
EventCreateKeyStrokePollEvent (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "EventCreateKeyStrokePollEvent\n"));
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gAppleKeyMapAggregatorProtocolGuid,
|
|
NULL,
|
|
(VOID **)&mKeyMapAggregator
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
InternalInitializeKeyHandler ();
|
|
|
|
mKeyStrokePollEvent = EventLibCreateNotifyTimerEvent (
|
|
InternalKeyStrokePollNotifyFunction,
|
|
NULL,
|
|
KEY_STROKE_POLL_FREQUENCY,
|
|
TRUE
|
|
);
|
|
|
|
Status = ((mKeyStrokePollEvent == NULL)
|
|
? EFI_OUT_OF_RESOURCES
|
|
: EFI_SUCCESS);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
// EventCancelKeyStrokePollEvent
|
|
VOID
|
|
EventCancelKeyStrokePollEvent (
|
|
VOID
|
|
)
|
|
{
|
|
DEBUG ((DEBUG_VERBOSE, "EventCancelKeyStrokePollEvent\n"));
|
|
|
|
EventLibCancelEvent (mKeyStrokePollEvent);
|
|
|
|
mKeyStrokePollEvent = NULL;
|
|
}
|
|
|
|
// EventIsCapsLockOnImpl
|
|
|
|
/** Retrieves the state of the CapsLock key.
|
|
|
|
@param[in,out] CLockOn This parameter indicates the state of the CapsLock
|
|
key.
|
|
|
|
@retval EFI_SUCCESS The CapsLock state was successfully returned
|
|
in CLockOn.
|
|
@retval EFI_INVALID_PARAMETER CLockOn is NULL.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EventIsCapsLockOnImpl (
|
|
IN OUT BOOLEAN *CLockOn
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "EventIsCapsLockOnImpl\n"));
|
|
|
|
Status = EFI_INVALID_PARAMETER;
|
|
|
|
if (CLockOn != NULL) {
|
|
*CLockOn = mCLockOn;
|
|
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|