OcInputLib: Initial import

This commit is contained in:
Download-Fritz 2019-09-28 15:33:57 +02:00
parent 4740f35ff9
commit eedf63f106
25 changed files with 5351 additions and 0 deletions

View File

@ -428,6 +428,20 @@
OC_ARRAY (OC_STRING, _, __)
OC_DECLARE (OC_UEFI_DRIVER_ARRAY)
///
/// Input is a set of options to support advanced input.
///
#define OC_UEFI_INPUT_FIELDS(_, __) \
_(UINT8 , KeyForgetThreshold , , 0 , ()) \
_(UINT8 , KeyMergeThreshold , , 0 , ()) \
_(BOOLEAN , KeySupport , , FALSE , ()) \
_(OC_STRING , KeySupportMode , , OC_STRING_CONSTR ("", _, __) , OC_DESTR (OC_STRING)) \
_(BOOLEAN , KeySwap , , FALSE , ()) \
_(BOOLEAN , PointerSupport , , FALSE , ()) \
_(OC_STRING , PointerSupportMode , , OC_STRING_CONSTR ("", _, __) , OC_DESTR (OC_STRING)) \
_(UINT32 , TimerResolution , , 0 , ())
OC_DECLARE (OC_UEFI_INPUT)
///
/// Prefer own protocol implementation for these protocols.
///
@ -467,6 +481,7 @@
#define OC_UEFI_CONFIG_FIELDS(_, __) \
_(BOOLEAN , ConnectDrivers , , FALSE , ()) \
_(OC_UEFI_DRIVER_ARRAY , Drivers , , OC_CONSTR2 (OC_UEFI_DRIVER_ARRAY, _, __) , OC_DESTR (OC_UEFI_DRIVER_ARRAY)) \
_(OC_UEFI_INPUT , Input , , OC_CONSTR2 (OC_UEFI_INPUT, _, __) , OC_DESTR (OC_UEFI_INPUT)) \
_(OC_UEFI_PROTOCOLS , Protocols , , OC_CONSTR2 (OC_UEFI_PROTOCOLS, _, __) , OC_DESTR (OC_UEFI_PROTOCOLS)) \
_(OC_UEFI_QUIRKS , Quirks , , OC_CONSTR2 (OC_UEFI_QUIRKS, _, __) , OC_DESTR (OC_UEFI_QUIRKS))
OC_DECLARE (OC_UEFI_CONFIG)

View File

@ -0,0 +1,63 @@
/** @file
OC Apple generic input library.
Copyright (c) 2019, vit9696. All rights reserved.<BR>
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.
**/
#ifndef OC_APPLE_GENERIC_INPUT_LIB_H
#define OC_APPLE_GENERIC_INPUT_LIB_H
typedef enum {
OcInputPointerModeAsus,
OcInputPointerModeMax
} OC_INPUT_POINTER_MODE;
typedef enum {
OcInputKeyModeAuto,
OcInputKeyModeV1,
OcInputKeyModeV2,
OcInputKeyModeAmi,
OcInputKeyModeMax
} OC_INPUT_KEY_MODE;
EFI_STATUS
OcAppleGenericInputTimerQuirkInit (
IN UINT32 TimerResolution
);
EFI_STATUS
OcAppleGenericInputTimerQuirkExit (
VOID
);
EFI_STATUS
OcAppleGenericInputPointerInit (
IN OC_INPUT_POINTER_MODE Mode
);
EFI_STATUS
OcAppleGenericInputPointerExit (
VOID
);
EFI_STATUS
OcAppleGenericInputKeycodeInit (
IN OC_INPUT_KEY_MODE Mode,
IN UINT8 KeyForgotThreshold,
IN UINT8 KeyMergeThreshold
);
EFI_STATUS
OcAppleGenericInputKeycodeExit (
VOID
);
#endif // OC_APPLE_GENERIC_INPUT_LIB_H

View File

@ -0,0 +1,59 @@
/** @file
Header file for AMI EfiKeycode protocol definitions.
Copyright (c) 2016, vit9696. All rights reserved.<BR>
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.
**/
#ifndef AMI_KEYCODE_H
#define AMI_KEYCODE_H
// 0ADFB62D-FF74-484C-8944-F85C4BEA87A8
#define AMI_EFIKEYCODE_PROTOCOL_GUID \
{ 0x0ADFB62D, 0xFF74, 0x484C, { 0x89, 0x44, 0xF8, 0x5C, 0x4B, 0xEA, 0x87, 0xA8 } }
extern EFI_GUID gAmiEfiKeycodeProtocolGuid;
typedef struct _AMI_EFIKEYCODE_PROTOCOL AMI_EFIKEYCODE_PROTOCOL;
#ifndef KEY_STATE_EXPOSED
#define KEY_STATE_EXPOSED 0x40
#endif
typedef struct {
EFI_INPUT_KEY Key;
EFI_KEY_STATE KeyState;
EFI_KEY EfiKey;
UINT8 EfiKeyIsValid;
UINT8 PS2ScanCode;
UINT8 PS2ScanCodeIsValid;
} AMI_EFI_KEY_DATA;
typedef EFI_STATUS (EFIAPI *AMI_READ_EFI_KEY) (
IN AMI_EFIKEYCODE_PROTOCOL *This,
OUT AMI_EFI_KEY_DATA *KeyData
);
typedef
EFI_STATUS
(EFIAPI *AMI_RESET_EX) (
IN AMI_EFIKEYCODE_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
struct _AMI_EFIKEYCODE_PROTOCOL {
AMI_RESET_EX Reset;
AMI_READ_EFI_KEY ReadEfikey;
EFI_EVENT WaitForKeyEx;
EFI_SET_STATE SetState;
EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify;
EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify;
};
#endif // AMI_KEYCODE_H

View File

@ -0,0 +1,82 @@
/** @file
Header file for AMI EfiPointer protocol definitions.
Copyright (c) 2016, vit9696. All rights reserved.<BR>
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.
**/
#ifndef AMI_POINTER_H
#define AMI_POINTER_H
#include <Library/OcGuardLib.h>
// 15A10CE7-EAB5-43BF-9042-74432E696377
#define AMI_EFIPOINTER_PROTOCOL_GUID \
{ 0x15A10CE7, 0xEAB5, 0x43BF, { 0x90, 0x42, 0x74, 0x43, 0x2E, 0x69, 0x63, 0x77 } }
extern EFI_GUID gAmiEfiPointerProtocolGuid;
typedef struct _AMI_EFIPOINTER_PROTOCOL AMI_EFIPOINTER_PROTOCOL;
// Unless Changed == 1, no data is provided
typedef struct {
UINT8 Absolute;
UINT8 One;
UINT8 Changed;
UINT8 Reserved;
INT32 PositionX;
INT32 PositionY;
INT32 PositionZ;
} AMI_POINTER_POSITION_STATE_DATA;
OC_STATIC_ASSERT (
sizeof (AMI_POINTER_POSITION_STATE_DATA) == 16,
"AMI_POINTER_POSITION_STATE_DATA is expected to be 16 bytes"
);
// Unless Changed == 1, no data is provided
typedef struct {
UINT8 Changed;
UINT8 LeftButton;
UINT8 MiddleButton;
UINT8 RightButton;
} AMI_POINTER_BUTTON_STATE_DATA;
OC_STATIC_ASSERT (
sizeof (AMI_POINTER_BUTTON_STATE_DATA) == 4,
"AMI_POINTER_BUTTON_STATE_DATA is expected to be 4 bytes"
);
typedef
VOID
(EFIAPI *AMI_EFIPOINTER_RESET) (
IN AMI_EFIPOINTER_PROTOCOL *This
);
typedef
VOID
(EFIAPI *AMI_EFIPOINTER_GET_BUTTON_STATE) (
IN AMI_EFIPOINTER_PROTOCOL *This,
OUT AMI_POINTER_BUTTON_STATE_DATA *State
);
typedef
VOID
(EFIAPI *AMI_EFIPOINTER_GET_POSITION_STATE) (
IN AMI_EFIPOINTER_PROTOCOL *This,
OUT AMI_POINTER_POSITION_STATE_DATA *State
);
struct _AMI_EFIPOINTER_PROTOCOL {
AMI_EFIPOINTER_RESET Reset;
AMI_EFIPOINTER_GET_POSITION_STATE GetPositionState;
AMI_EFIPOINTER_GET_BUTTON_STATE GetButtonState;
};
#endif // AMI_POINTER_H

View File

@ -63,6 +63,7 @@ OC_STRUCTORS (OC_PLATFORM_SMBIOS_CONFIG, ())
OC_STRUCTORS (OC_PLATFORM_CONFIG, ())
OC_ARRAY_STRUCTORS (OC_UEFI_DRIVER_ARRAY)
OC_STRUCTORS (OC_UEFI_INPUT, ())
OC_STRUCTORS (OC_UEFI_PROTOCOLS, ())
OC_STRUCTORS (OC_UEFI_QUIRKS, ())
OC_STRUCTORS (OC_UEFI_CONFIG, ())
@ -518,11 +519,25 @@ mUefiProtocolsSchema[] = {
OC_SCHEMA_BOOLEAN_IN ("UnicodeCollation", OC_GLOBAL_CONFIG, Uefi.Protocols.UnicodeCollation)
};
STATIC
OC_SCHEMA
mUefiInputSchema[] = {
OC_SCHEMA_INTEGER_IN ("KeyForgetThreshold", OC_GLOBAL_CONFIG, Uefi.Input.KeyForgetThreshold),
OC_SCHEMA_INTEGER_IN ("KeyMergeThreshold", OC_GLOBAL_CONFIG, Uefi.Input.KeyMergeThreshold),
OC_SCHEMA_BOOLEAN_IN ("KeySupport", OC_GLOBAL_CONFIG, Uefi.Input.KeySupport),
OC_SCHEMA_STRING_IN ("KeySupportMode", OC_GLOBAL_CONFIG, Uefi.Input.KeySupportMode),
OC_SCHEMA_BOOLEAN_IN ("KeySwap", OC_GLOBAL_CONFIG, Uefi.Input.KeySwap),
OC_SCHEMA_BOOLEAN_IN ("PointerSupport", OC_GLOBAL_CONFIG, Uefi.Input.PointerSupport),
OC_SCHEMA_STRING_IN ("PointerSupportMode", OC_GLOBAL_CONFIG, Uefi.Input.PointerSupportMode),
OC_SCHEMA_INTEGER_IN ("TimerResolution", OC_GLOBAL_CONFIG, Uefi.Input.TimerResolution)
};
STATIC
OC_SCHEMA
mUefiConfigurationSchema[] = {
OC_SCHEMA_BOOLEAN_IN ("ConnectDrivers", OC_GLOBAL_CONFIG, Uefi.ConnectDrivers),
OC_SCHEMA_ARRAY_IN ("Drivers", OC_GLOBAL_CONFIG, Uefi.Drivers, &mUefiDriversSchema),
OC_SCHEMA_DICT ("Input", mUefiInputSchema),
OC_SCHEMA_DICT ("Protocols", mUefiProtocolsSchema),
OC_SCHEMA_DICT ("Quirks", mUefiQuirksSchema)
};

View File

@ -0,0 +1,262 @@
/** @file
AmiEfiKeycode to KeyMapDb translator.
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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 <Uefi.h>
#include "AIK.h"
#include <Library/DebugLib.h>
#include <Library/OcInputLib.h>
#include <Library/UefiBootServicesTableLib.h>
AIK_SELF gAikSelf;
STATIC
VOID
EFIAPI
AIKProtocolArriveHandler (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
AIK_SELF *Keycode;
Keycode = (AIK_SELF *) Context;
if (Keycode == NULL || Keycode->OurJobIsDone) {
DEBUG ((DEBUG_INFO, "AIKProtocolArriveHandler got null handler or called when done\n"));
return;
}
Status = AIKInstall (Keycode);
if (!EFI_ERROR (Status)) {
//
// We are successful, so can remove the protocol polling event if any
//
AIKProtocolArriveUninstall (Keycode);
} else {
DEBUG ((DEBUG_INFO, "AIKProtocolArriveHandler AIKInstall failed - %r\n", Status));
}
}
EFI_STATUS
AIKProtocolArriveInstall (
AIK_SELF *Keycode
)
{
EFI_STATUS Status;
VOID *Registration;
Status = EFI_SUCCESS;
if (Keycode->KeyMapDbArriveEvent == NULL) {
Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, AIKProtocolArriveHandler, Keycode, &Keycode->KeyMapDbArriveEvent);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "KeyMapDbArriveEvent creation failed - %r\n", Status));
} else {
Status = gBS->RegisterProtocolNotify (&gAppleKeyMapDatabaseProtocolGuid, Keycode->KeyMapDbArriveEvent, &Registration);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "KeyMapDbArriveEvent registration failed - %r\n", Status));
gBS->CloseEvent (Keycode->KeyMapDbArriveEvent);
Keycode->KeyMapDbArriveEvent = NULL;
}
}
}
return Status;
}
VOID
AIKProtocolArriveUninstall (
AIK_SELF *Keycode
)
{
if (Keycode->KeyMapDbArriveEvent != NULL) {
gBS->CloseEvent (Keycode->KeyMapDbArriveEvent);
Keycode->KeyMapDbArriveEvent = NULL;
}
}
VOID
EFIAPI
AIKPollKeyboardHandler (
IN EFI_EVENT Event,
IN VOID *Context
)
{
AIK_SELF *Keycode;
UINT64 Counter;
UINTN Index;
AMI_EFI_KEY_DATA KeyData;
EFI_STATUS Status;
Keycode = (AIK_SELF *) Context;
if (Keycode == NULL || Keycode->OurJobIsDone) {
DEBUG ((DEBUG_INFO, "AIKPollKeyboardHandler got null handler or called when done\n"));
return;
}
Keycode->InPollKeyboardEvent = TRUE;
//
// Counter is here for debugging purposes only.
//
Counter = AIKTargetRefresh (&Keycode->Target);
//
// Some implementations return "partial key", which is a modifier without
// a key. When a modifier is held, we will get partial keys infinitely, so make sure
// we break after some time.
//
Index = 0;
do {
Status = AIKSourceGrabEfiKey (
&Keycode->Source,
&KeyData
);
if (!EFI_ERROR (Status)) {
(VOID) Counter;
DEBUG ((DEBUG_VERBOSE, "Read key with scan 0x%X and unicode 0x%X at %Lu\n",
KeyData.Key.ScanCode, KeyData.Key.UnicodeChar, Counter
));
AIKDataWriteEntry (&Keycode->Data, &KeyData);
AIKTargetWriteEntry (&Keycode->Target, &KeyData);
}
Index++;
} while (!EFI_ERROR (Status) && Index < AIK_KEY_POLL_LIMIT);
AIKTargetSubmit (&Keycode->Target);
Keycode->InPollKeyboardEvent = FALSE;
}
EFI_STATUS
AIKInstall (
AIK_SELF *Keycode
)
{
EFI_STATUS Status;
Status = AIKTargetInstall (
&Keycode->Target,
Keycode->KeyForgotThreshold,
Keycode->KeyMergeThreshold
);
if (EFI_ERROR (Status)) {
//
// Working AppleKeyMapAggregator is not here yet.
//
return Status;
}
Status = AIKSourceInstall (&Keycode->Source, Keycode->Mode);
if (EFI_ERROR (Status)) {
//
// Cannot work with these sources.
//
AIKTargetUninstall (&Keycode->Target);
return Status;
}
AIKDataReset (&Keycode->Data);
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY,
AIKPollKeyboardHandler,
Keycode, &Keycode->PollKeyboardEvent
);
if (!EFI_ERROR (Status)) {
Status = gBS->SetTimer (Keycode->PollKeyboardEvent, TimerPeriodic, AIK_KEY_POLL_INTERVAL);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AIKPollKeyboardHandler timer setting failed - %r\n", Status));
gBS->CloseEvent (Keycode->PollKeyboardEvent);
Keycode->PollKeyboardEvent = NULL;
}
} else {
DEBUG ((DEBUG_INFO, "AIKPollKeyboardHandler event creation failed - %r\n", Status));
}
if (EFI_ERROR (Status)) {
AIKSourceUninstall (&Keycode->Source);
AIKTargetUninstall (&Keycode->Target);
}
return Status;
}
VOID
AIKUninstall (
AIK_SELF *Keycode
)
{
Keycode->OurJobIsDone = TRUE;
AIKProtocolArriveUninstall (Keycode);
if (Keycode->PollKeyboardEvent) {
gBS->SetTimer (Keycode->PollKeyboardEvent, TimerCancel, 0);
gBS->CloseEvent (Keycode->PollKeyboardEvent);
Keycode->PollKeyboardEvent = NULL;
}
AIKSourceUninstall (&Keycode->Source);
AIKTargetUninstall (&Keycode->Target);
}
EFI_STATUS
OcAppleGenericInputKeycodeInit (
IN OC_INPUT_KEY_MODE Mode,
IN UINT8 KeyForgotThreshold,
IN UINT8 KeyMergeThreshold
)
{
EFI_STATUS Status;
AIKTranslateConfigure ();
gAikSelf.Mode = Mode;
gAikSelf.KeyForgotThreshold = KeyForgotThreshold;
gAikSelf.KeyMergeThreshold = KeyMergeThreshold;
Status = AIKInstall (&gAikSelf);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AIKInstall failed - %r\n", Status));
//
// No AppleKeyMapAggregator present, install on its availability.
//
Status = AIKProtocolArriveInstall (&gAikSelf);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AIK is NOT waiting for protocols - %r\n", Status));
}
}
return Status;
}
EFI_STATUS
OcAppleGenericInputKeycodeExit (
VOID
)
{
AIKUninstall (&gAikSelf);
return EFI_SUCCESS;
}

View File

@ -0,0 +1,113 @@
/** @file
Header file for AmiEfiKeycode to KeyMapDb translator.
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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.
**/
#ifndef AIK_SELF_H
#define AIK_SELF_H
#include "AIKData.h"
#include "AIKSource.h"
#include "AIKTarget.h"
#include "AIKTranslate.h"
#include <Library/OcInputLib.h>
#include <Library/UefiLib.h>
//
// Maximum amount of keys polled at once
//
#define AIK_KEY_POLL_LIMIT (AIK_TARGET_BUFFER_SIZE)
//
// Defines key polling frequency
//
#define AIK_KEY_POLL_INTERVAL EFI_TIMER_PERIOD_MILLISECONDS(10)
typedef struct {
//
// Input mode
//
OC_INPUT_KEY_MODE Mode;
//
// Remove key if it was not submitted after this value.
//
UINT8 KeyForgotThreshold;
//
// Assume simultaneous press if within this value.
//
UINT8 KeyMergeThreshold;
//
// Input sources
//
AIK_SOURCE Source;
//
// Output targets
//
AIK_TARGET Target;
//
// Key data
//
AIK_DATA Data;
//
// AppleKeyMapAggregator polling event
//
EFI_EVENT KeyMapDbArriveEvent;
//
// Keyboard input polling event
//
EFI_EVENT PollKeyboardEvent;
//
// Indicates keyboard input polling event to avoid reentrancy if any
//
BOOLEAN InPollKeyboardEvent;
//
// Indicates we are done for any event in case it gets fired.
// Not really needed, put in case of bogus firmwares.
//
BOOLEAN OurJobIsDone;
} AIK_SELF;
//
// This is only used in Shims, where no other way exists.
//
extern AIK_SELF gAikSelf;
EFI_STATUS
AIKProtocolArriveInstall (
AIK_SELF *Keycode
);
VOID
AIKProtocolArriveUninstall (
AIK_SELF *Keycode
);
EFI_STATUS
AIKInstall (
AIK_SELF *Keycode
);
VOID
AIKUninstall (
AIK_SELF *Keycode
);
#endif

View File

@ -0,0 +1,81 @@
/** @file
Key code ring
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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 "AIKData.h"
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
VOID
AIKDataReset (
IN OUT AIK_DATA *Data
)
{
Data->KeyBufferHead = Data->KeyBufferTail = Data->KeyBuffer;
Data->KeyBufferSize = 0;
}
BOOLEAN
AIKDataEmpty (
IN AIK_DATA *Data
)
{
return Data->KeyBufferSize == 0;
}
EFI_STATUS
AIKDataReadEntry (
IN OUT AIK_DATA *Data,
OUT AMI_EFI_KEY_DATA *KeyData
)
{
if (Data->KeyBufferSize == 0) {
return EFI_NOT_READY;
}
CopyMem (KeyData, Data->KeyBufferTail, sizeof (*KeyData));
Data->KeyBufferSize--;
Data->KeyBufferTail++;
if (Data->KeyBufferTail == &Data->KeyBuffer[AIK_DATA_BUFFER_SIZE]) {
Data->KeyBufferTail = Data->KeyBuffer;
}
return EFI_SUCCESS;
}
VOID
AIKDataWriteEntry (
IN OUT AIK_DATA *Data,
IN AMI_EFI_KEY_DATA *KeyData
)
{
//
// Eat the first entry if we have no room
//
if (Data->KeyBufferSize == AIK_DATA_BUFFER_SIZE) {
Data->KeyBufferSize--;
Data->KeyBufferTail++;
if (Data->KeyBufferTail == &Data->KeyBuffer[AIK_DATA_BUFFER_SIZE]) {
Data->KeyBufferTail = Data->KeyBuffer;
}
}
Data->KeyBufferSize++;
CopyMem (Data->KeyBufferHead, KeyData, sizeof (*KeyData));
Data->KeyBufferHead++;
if (Data->KeyBufferHead == &Data->KeyBuffer[AIK_DATA_BUFFER_SIZE]) {
Data->KeyBufferHead = Data->KeyBuffer;
}
}

View File

@ -0,0 +1,57 @@
/** @file
Key code ring
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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.
**/
#ifndef AIK_DATA_H
#define AIK_DATA_H
#include <Protocol/AmiKeycode.h>
//
// Maximum amount of keys queued for non-Apple protocols
//
#define AIK_DATA_BUFFER_SIZE 12
typedef struct {
//
// Stored key buffer for responding to non-Apple protocols
//
AMI_EFI_KEY_DATA KeyBuffer[AIK_DATA_BUFFER_SIZE];
AMI_EFI_KEY_DATA *KeyBufferHead;
AMI_EFI_KEY_DATA *KeyBufferTail;
UINTN KeyBufferSize;
} AIK_DATA;
VOID
AIKDataReset (
IN OUT AIK_DATA *Data
);
BOOLEAN
AIKDataEmpty (
IN AIK_DATA *Data
);
EFI_STATUS
AIKDataReadEntry (
IN OUT AIK_DATA *Data,
OUT AMI_EFI_KEY_DATA *KeyData
);
VOID
AIKDataWriteEntry (
IN OUT AIK_DATA *Data,
IN AMI_EFI_KEY_DATA *KeyData
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,198 @@
/** @file
Key shimming code
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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 "AIK.h"
#include "AIKShim.h"
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
EFI_STATUS
EFIAPI
AIKShimAmiKeycodeReset (
IN AMI_EFIKEYCODE_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
if (This == NULL || gAikSelf.OurJobIsDone) {
return EFI_INVALID_PARAMETER;
}
if (This == gAikSelf.Source.AmiKeycode && !gAikSelf.InPollKeyboardEvent) {
//
// Do not touch any protocol but ours.
//
AIKDataReset (&gAikSelf.Data);
}
return gAikSelf.Source.AmiReset (This, ExtendedVerification);
}
EFI_STATUS
EFIAPI
AIKShimAmiKeycodeReadEfikey (
IN AMI_EFIKEYCODE_PROTOCOL *This,
OUT AMI_EFI_KEY_DATA *KeyData
)
{
DEBUG ((DEBUG_VERBOSE, "AIKAmiKeycodeReadEfikey %p %p ours %p event %d",
This, KeyData, gAikSelf.Source.AmiKeycode, gAikSelf.InPollKeyboardEvent));
if (This == NULL || KeyData == NULL || gAikSelf.OurJobIsDone) {
return EFI_INVALID_PARAMETER;
}
if (This == gAikSelf.Source.AmiKeycode && !gAikSelf.InPollKeyboardEvent) {
//
// Do not touch any protocol but ours.
//
return AIKDataReadEntry (&gAikSelf.Data, KeyData);
}
return gAikSelf.Source.AmiReadEfikey (This, KeyData);
}
EFI_STATUS
EFIAPI
AIKShimTextInputReset (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
if (This == NULL || gAikSelf.OurJobIsDone) {
return EFI_INVALID_PARAMETER;
}
if (This == gAikSelf.Source.TextInput && !gAikSelf.InPollKeyboardEvent) {
//
// Do not touch any protocol but ours.
//
AIKDataReset (&gAikSelf.Data);
}
return gAikSelf.Source.TextReset (This, ExtendedVerification);
}
EFI_STATUS
EFIAPI
AIKShimTextInputReadKeyStroke (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
OUT EFI_INPUT_KEY *Key
)
{
EFI_STATUS Status;
AMI_EFI_KEY_DATA AmiKeyData;
DEBUG ((DEBUG_VERBOSE, "AIKTextInputReadKeyStroke %p %p ours %p event %d",
This, Key, gAikSelf.Source.TextInput, gAikSelf.InPollKeyboardEvent));
if (This == NULL || Key == NULL || gAikSelf.OurJobIsDone) {
return EFI_INVALID_PARAMETER;
}
if (This == gAikSelf.Source.TextInput && !gAikSelf.InPollKeyboardEvent) {
//
// Do not touch any protocol but ours.
//
Status = AIKDataReadEntry (&gAikSelf.Data, &AmiKeyData);
if (!EFI_ERROR (Status)) {
//
// 'Partial' keys should not be returned by SimpleTextInput protocols.
//
if (AmiKeyData.Key.ScanCode == 0 && AmiKeyData.Key.UnicodeChar == 0
&& (AmiKeyData.KeyState.KeyToggleState & KEY_STATE_EXPOSED)) {
Status = EFI_NOT_READY;
} else {
CopyMem (Key, &AmiKeyData.Key, sizeof (AmiKeyData.Key));
}
}
return Status;
}
return gAikSelf.Source.TextReadKeyStroke (This, Key);
}
EFI_STATUS
EFIAPI
AIKShimTextInputResetEx (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
)
{
if (This == NULL || gAikSelf.OurJobIsDone) {
return EFI_INVALID_PARAMETER;
}
if (This == gAikSelf.Source.TextInputEx && !gAikSelf.InPollKeyboardEvent) {
//
// Do not touch any protocol but ours.
//
AIKDataReset (&gAikSelf.Data);
}
return gAikSelf.Source.TextResetEx (This, ExtendedVerification);
}
EFI_STATUS
EFIAPI
AIKShimTextInputReadKeyStrokeEx (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
OUT EFI_KEY_DATA *KeyData
)
{
EFI_STATUS Status;
AMI_EFI_KEY_DATA AmiKeyData;
DEBUG ((DEBUG_VERBOSE, "AIKTextInputReadKeyStrokeEx %p %p ours %p event %d",
This, KeyData, gAikSelf.Source.TextInputEx, gAikSelf.InPollKeyboardEvent));
if (This == NULL || KeyData == NULL || gAikSelf.OurJobIsDone) {
return EFI_INVALID_PARAMETER;
}
if (This == gAikSelf.Source.TextInputEx && !gAikSelf.InPollKeyboardEvent) {
//
// Do not touch any protocol but ours.
//
Status = AIKDataReadEntry (&gAikSelf.Data, &AmiKeyData);
if (!EFI_ERROR (Status)) {
CopyMem (&KeyData->Key, &AmiKeyData.Key, sizeof (AmiKeyData.Key));
CopyMem (&KeyData->KeyState, &AmiKeyData.KeyState, sizeof (AmiKeyData.KeyState));
}
return Status;
}
return gAikSelf.Source.TextReadKeyStrokeEx (This, KeyData);
}
VOID
EFIAPI
AIKShimWaitForKeyHandler (
IN EFI_EVENT Event,
IN VOID *Context
)
{
if (gAikSelf.OurJobIsDone) {
DEBUG ((DEBUG_INFO, "AIKShimWaitForKeyHandler got null handler or called when done\n"));
return;
}
if (!AIKDataEmpty (&gAikSelf.Data)) {
DEBUG ((DEBUG_VERBOSE, "Caught KeyBufferSize non-zero\n"));
gBS->SignalEvent (Event);
}
}

View File

@ -0,0 +1,72 @@
/** @file
Key shimming code
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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.
**/
#ifndef AIK_SHIM_H
#define AIK_SHIM_H
#include <Protocol/AmiKeycode.h>
#include <Protocol/SimpleTextIn.h>
#include <Protocol/SimpleTextInEx.h>
EFI_STATUS
EFIAPI
AIKShimAmiKeycodeReset (
IN AMI_EFIKEYCODE_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
EFI_STATUS
EFIAPI
AIKShimAmiKeycodeReadEfikey (
IN AMI_EFIKEYCODE_PROTOCOL *This,
OUT AMI_EFI_KEY_DATA *KeyData
);
EFI_STATUS
EFIAPI
AIKShimTextInputReset (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
EFI_STATUS
EFIAPI
AIKShimTextInputReadKeyStroke (
IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
OUT EFI_INPUT_KEY *Key
);
EFI_STATUS
EFIAPI
AIKShimTextInputResetEx (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
);
EFI_STATUS
EFIAPI
AIKShimTextInputReadKeyStrokeEx (
IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,
OUT EFI_KEY_DATA *KeyData
);
VOID
EFIAPI
AIKShimWaitForKeyHandler (
IN EFI_EVENT Event,
IN VOID *Context
);
#endif

View File

@ -0,0 +1,212 @@
/** @file
Key provider
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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 "AIKSource.h"
#include "AIKShim.h"
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/OcInputLib.h>
#include <Library/UefiBootServicesTableLib.h>
EFI_STATUS
AIKSourceGrabEfiKey (
AIK_SOURCE *Source,
AMI_EFI_KEY_DATA *KeyData
)
{
EFI_STATUS Status;
EFI_EVENT Event;
ZeroMem (KeyData, sizeof (*KeyData));
if (Source->AmiKeycode != NULL && Source->AmiReadEfikey) {
Status = Source->AmiReadEfikey (Source->AmiKeycode, KeyData);
Event = Source->AmiKeycode->WaitForKeyEx;
} else if (Source->TextInputEx != NULL && Source->TextReadKeyStrokeEx) {
Status = Source->TextReadKeyStrokeEx (Source->TextInputEx, (EFI_KEY_DATA *) KeyData);
Event = Source->TextInputEx->WaitForKeyEx;
} else if (Source->TextInput != NULL && Source->TextReadKeyStroke) {
Status = Source->TextReadKeyStroke (Source->TextInput, &KeyData->Key);
Event = Source->TextInput->WaitForKey;
} else {
//
// Should never happen.
//
Status = EFI_NOT_FOUND;
Event = NULL;
}
if (Event != NULL) {
gBS->SignalEvent (Event);
}
return Status;
}
EFI_STATUS
AIKSourceInstall (
AIK_SOURCE *Source,
OC_INPUT_KEY_MODE Mode
)
{
EFI_STATUS Status;
if (Source->AmiKeycode != NULL || Source->TextInput != NULL || Source->TextInputEx != NULL) {
return EFI_SUCCESS;
}
Source->ConSplitHandler = gST->ConsoleInHandle;
if (Mode == OcInputKeyModeAuto || Mode == OcInputKeyModeAmi) {
Status = gBS->HandleProtocol (Source->ConSplitHandler, &gAmiEfiKeycodeProtocolGuid,
(VOID * *)& Source->AmiKeycode);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AmiEfiKeycodeProtocol is unavailable on gST->ConsoleHandle - %r\n", Status));
}
}
if (Mode == OcInputKeyModeAuto || Mode == OcInputKeyModeV1) {
Status = gBS->HandleProtocol (Source->ConSplitHandler, &gEfiSimpleTextInProtocolGuid,
(VOID * *)& Source->TextInput);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "EfiSimpleTextInProtocol is unavailable on gST->ConsoleHandle - %r\n", Status));
}
}
if (Mode == OcInputKeyModeAuto || Mode == OcInputKeyModeV2) {
Status = gBS->HandleProtocol (Source->ConSplitHandler, &gEfiSimpleTextInputExProtocolGuid,
(VOID * *)& Source->TextInputEx);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "EfiSimpleTextInputExProtocol is unavailable on gST->ConsoleHandle - %r\n", Status));
}
}
if (Source->AmiKeycode == NULL && Source->TextInput == NULL && Source->TextInputEx == NULL) {
DEBUG ((DEBUG_INFO, "No ConSplitter input protocol is unavailable\n"));
return EFI_NOT_FOUND;
}
DEBUG ((DEBUG_INFO, "gST->ConIn %p vs found %p\n", gST->ConIn, Source->TextInput));
//
// We additionally reset the protocols as our buffers are empty, and we do not want old data.
//
if (Source->AmiKeycode) {
Source->AmiKeycode->Reset (Source->AmiKeycode, FALSE);
Source->AmiReset = Source->AmiKeycode->Reset;
Source->AmiReadEfikey = Source->AmiKeycode->ReadEfikey;
Source->AmiWait = Source->AmiKeycode->WaitForKeyEx;
Source->AmiKeycode->Reset = AIKShimAmiKeycodeReset;
Source->AmiKeycode->ReadEfikey = AIKShimAmiKeycodeReadEfikey;
Status = gBS->CreateEvent (
EVT_NOTIFY_WAIT, TPL_NOTIFY, AIKShimWaitForKeyHandler,
NULL, &Source->AmiKeycode->WaitForKeyEx
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AmiEfiKeycodeProtocol WaitForKey replace failed - %r", Status));
Source->AmiKeycode->WaitForKeyEx = Source->AmiWait;
Source->AmiWait = NULL;
}
}
if (Source->TextInput) {
Source->TextInput->Reset (Source->TextInput, FALSE);
Source->TextReset = Source->TextInput->Reset;
Source->TextReadKeyStroke = Source->TextInput->ReadKeyStroke;
Source->TextWait = Source->TextInput->WaitForKey;
Source->TextInput->Reset = AIKShimTextInputReset;
Source->TextInput->ReadKeyStroke = AIKShimTextInputReadKeyStroke;
Status = gBS->CreateEvent (
EVT_NOTIFY_WAIT, TPL_NOTIFY, AIKShimWaitForKeyHandler,
NULL, &Source->TextInput->WaitForKey
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "EfiSimpleTextInProtocol WaitForKey replace failed - %r", Status));
Source->TextInput->WaitForKey = Source->TextWait;
Source->TextWait = NULL;
}
}
if (Source->TextInputEx) {
Source->TextInputEx->Reset (Source->TextInputEx, FALSE);
Source->TextResetEx = Source->TextInputEx->Reset;
Source->TextWaitEx = Source->TextInputEx->WaitForKeyEx;
Source->TextReadKeyStrokeEx = Source->TextInputEx->ReadKeyStrokeEx;
Source->TextInputEx->Reset = AIKShimTextInputResetEx;
Source->TextInputEx->ReadKeyStrokeEx = AIKShimTextInputReadKeyStrokeEx;
Status = gBS->CreateEvent (
EVT_NOTIFY_WAIT, TPL_NOTIFY, AIKShimWaitForKeyHandler,
NULL, &Source->TextInputEx->WaitForKeyEx
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "EfiSimpleTextInputExProtocol WaitForKey replace failed - %r", Status));
Source->TextInputEx->WaitForKeyEx = Source->TextWaitEx;
Source->TextWaitEx = NULL;
}
}
return EFI_SUCCESS;
}
VOID
AIKSourceUninstall (
AIK_SOURCE *Source
)
{
if (Source->AmiKeycode) {
Source->AmiKeycode->Reset = Source->AmiReset;
Source->AmiKeycode->ReadEfikey = Source->AmiReadEfikey;
if (Source->AmiWait != NULL && Source->AmiWait != Source->AmiKeycode->WaitForKeyEx) {
gBS->CloseEvent (Source->AmiKeycode->WaitForKeyEx);
Source->AmiKeycode->WaitForKeyEx = Source->AmiWait;
}
Source->AmiReset = NULL;
Source->AmiReadEfikey = NULL;
Source->AmiWait = NULL;
Source->AmiKeycode = NULL;
}
if (Source->TextInput) {
Source->TextInput->Reset = Source->TextReset;
Source->TextInput->ReadKeyStroke = Source->TextReadKeyStroke;
if (Source->TextWait != NULL && Source->TextWait != Source->TextInput->WaitForKey) {
gBS->CloseEvent (Source->TextInput->WaitForKey);
Source->TextInput->WaitForKey = Source->TextWait;
}
Source->TextInput = NULL;
Source->TextReset = NULL;
Source->TextWait = NULL;
Source->TextReadKeyStroke = NULL;
}
if (Source->TextInputEx) {
Source->TextInputEx->Reset = Source->TextResetEx;
Source->TextInputEx->ReadKeyStrokeEx = Source->TextReadKeyStrokeEx;
if (Source->TextWaitEx != NULL && Source->TextWaitEx != Source->TextInputEx->WaitForKeyEx) {
gBS->CloseEvent (Source->TextInputEx->WaitForKeyEx);
Source->TextInputEx->WaitForKeyEx = Source->TextWaitEx;
}
Source->TextInputEx = NULL;
Source->TextResetEx = NULL;
Source->TextWaitEx = NULL;
Source->TextReadKeyStrokeEx = NULL;
}
if (Source->ConSplitHandler != NULL) {
gBS->DisconnectController (Source->ConSplitHandler, NULL, NULL);
Source->ConSplitHandler = NULL;
}
}

View File

@ -0,0 +1,71 @@
/** @file
Key provider
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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.
**/
#ifndef AIK_SOURCE_H
#define AIK_SOURCE_H
#include <Protocol/AmiKeycode.h>
#include <Protocol/SimpleTextIn.h>
#include <Protocol/SimpleTextInEx.h>
#include <Library/OcInputLib.h>
typedef struct {
//
// Preserved handle of gST->ConsoleInHandle
//
EFI_HANDLE ConSplitHandler;
//
// Solved input protocol instances from ConSplitHandler
// We override their ReadKey and Reset handlers and implement
// them ourselves via polled data from one of these protocols.
// Polled proto is prioritised as present: AMI, EX, Legacy.
//
AMI_EFIKEYCODE_PROTOCOL *AmiKeycode;
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *TextInput;
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
//
// Original implementations of the protocols.
//
AMI_RESET_EX AmiReset;
AMI_READ_EFI_KEY AmiReadEfikey;
EFI_EVENT AmiWait;
EFI_INPUT_RESET TextReset;
EFI_EVENT TextWait;
EFI_INPUT_READ_KEY TextReadKeyStroke;
EFI_INPUT_RESET_EX TextResetEx;
EFI_INPUT_READ_KEY_EX TextReadKeyStrokeEx;
EFI_EVENT TextWaitEx;
} AIK_SOURCE;
EFI_STATUS
AIKSourceGrabEfiKey (
AIK_SOURCE *Source,
AMI_EFI_KEY_DATA *KeyData
);
EFI_STATUS
AIKSourceInstall (
AIK_SOURCE *Source,
OC_INPUT_KEY_MODE Mode
);
VOID
AIKSourceUninstall (
AIK_SOURCE *Source
);
#endif

View File

@ -0,0 +1,196 @@
/** @file
Key consumer
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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 "AIKTarget.h"
#include "AIKTranslate.h"
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
EFI_STATUS
AIKTargetInstall (
IN OUT AIK_TARGET *Target,
IN UINT8 KeyForgotThreshold,
IN UINT8 KeyMergeThreshold
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
Target->KeyForgotThreshold = KeyForgotThreshold;
Target->KeyMergeThreshold = KeyMergeThreshold;
if (Target->KeyMapDb == NULL) {
Status = gBS->LocateProtocol (&gAppleKeyMapDatabaseProtocolGuid, NULL, (VOID **) &Target->KeyMapDb);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AppleKeyMapDatabaseProtocol is unavailable - %r\n", Status));
return EFI_NOT_FOUND;
}
Status = Target->KeyMapDb->CreateKeyStrokesBuffer (
Target->KeyMapDb, AIK_TARGET_BUFFER_SIZE, &Target->KeyMapDbIndex
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "CreateKeyStrokesBuffer failed - %r\n", Status));
Target->KeyMapDb = NULL;
}
}
return Status;
}
VOID
AIKTargetUninstall (
IN OUT AIK_TARGET *Target
)
{
if (Target->KeyMapDb != NULL) {
Target->KeyMapDb->RemoveKeyStrokesBuffer (Target->KeyMapDb, Target->KeyMapDbIndex);
Target->KeyMapDb = NULL;
}
Target->NumberOfKeys = 0;
Target->Modifiers = 0;
Target->ModifierCounter = 0;
ZeroMem (Target->Keys, sizeof (Target->Keys));
ZeroMem (Target->KeyCounters, sizeof (Target->KeyCounters));
}
UINT64
AIKTargetRefresh (
IN OUT AIK_TARGET *Target
)
{
UINTN Index;
UINTN Left;
Target->Counter++;
for (Index = 0; Index < Target->NumberOfKeys; Index++) {
//
// We reported this key Target->KeyForgetThreshold times, time to say goodbye.
//
if (Target->KeyCounters[Index] + Target->KeyForgotThreshold <= Target->Counter) {
Left = Target->NumberOfKeys - (Index + 1);
if (Left > 0) {
CopyMem (
&Target->KeyCounters[Index],
&Target->KeyCounters[Index+1],
sizeof (Target->KeyCounters[0]) * Left);
CopyMem (
&Target->Keys[Index],
&Target->Keys[Index+1],
sizeof (Target->Keys[0]) * Left);
}
Target->NumberOfKeys--;
}
}
//
// No keys were pressed, so we did not enter AIKTargetWriteEntry.
// However, we still need to reset modifiers after time.
//
if (Target->ModifierCounter + Target->KeyForgotThreshold <= Target->Counter) {
Target->Modifiers = 0;
}
return Target->Counter;
}
VOID
AIKTargetWriteEntry (
IN OUT AIK_TARGET *Target,
IN AMI_EFI_KEY_DATA *KeyData
)
{
APPLE_MODIFIER_MAP Modifiers;
APPLE_KEY_CODE Key;
UINTN Index;
UINTN InsertIndex;
UINT64 OldestCounter;
AIKTranslate (KeyData, &Modifiers, &Key);
Target->Modifiers = Modifiers;
Target->ModifierCounter = Target->Counter;
if (Key == UsbHidUndefined) {
//
// This is just a modifier or an unsupported key.
//
return;
}
for (Index = 0; Index < Target->NumberOfKeys; Index++) {
if (Target->Keys[Index] == Key) {
//
// This key was added previously, just update its counter.
//
Target->KeyCounters[Index] = Target->Counter;
return;
}
}
InsertIndex = Target->NumberOfKeys;
//
// This should not happen, but we have no room, replace the oldest key.
//
if (InsertIndex == AIK_TARGET_BUFFER_SIZE) {
InsertIndex = 0;
OldestCounter = Target->KeyCounters[InsertIndex];
for (Index = 1; Index < Target->NumberOfKeys; Index++) {
if (OldestCounter > Target->KeyCounters[Index]) {
OldestCounter = Target->KeyCounters[Index];
InsertIndex = Index;
}
}
Target->NumberOfKeys--;
}
//
// Insert the new key
//
Target->Keys[InsertIndex] = Key;
Target->KeyCounters[InsertIndex] = Target->Counter;
Target->NumberOfKeys++;
}
VOID
AIKTargetSubmit (
IN OUT AIK_TARGET *Target
)
{
EFI_STATUS Status;
if (Target->KeyMapDb != NULL) {
Status = Target->KeyMapDb->SetKeyStrokeBufferKeys (
Target->KeyMapDb,
Target->KeyMapDbIndex,
Target->Modifiers,
Target->NumberOfKeys,
Target->Keys
);
} else {
Status = EFI_NOT_FOUND;
}
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Failed to submit keys to AppleMapDb - %r", Status));
}
}

View File

@ -0,0 +1,116 @@
/** @file
Key consumer
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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.
**/
#ifndef AIK_TARGET_H
#define AIK_TARGET_H
#include <IndustryStandard/AppleHid.h>
#include <Protocol/AppleKeyMapDatabase.h>
#include <Protocol/AmiKeycode.h>
//
// Maximum amount of keys reported to Apple protocols
//
#define AIK_TARGET_BUFFER_SIZE 6
//
// Known values for key repeat (single key hold):
// VMware - 2, APTIO V - 3 or 4
// Known values for different keys (quick press one after other):
// VMware - 6+, APTIO V - 10+
// Known values for simultaneous keys (dual key hold):
// VMware - 2, APTIO V - 1
//
typedef struct {
//
// Apple output protocol we submit data to.
//
APPLE_KEY_MAP_DATABASE_PROTOCOL *KeyMapDb;
//
// Apple output buffer index
//
UINTN KeyMapDbIndex;
//
// Apple modifier map (previously reported)
//
APPLE_MODIFIER_MAP Modifiers;
//
// Previously reported Apple modifiers timestamp
//
UINT64 ModifierCounter;
//
// Previously reported Apple active keys
//
APPLE_KEY_CODE Keys[AIK_TARGET_BUFFER_SIZE];
//
// Previously reported Apple key timestamps
//
UINT64 KeyCounters[AIK_TARGET_BUFFER_SIZE];
//
// Amount of active keys previously reported
//
UINTN NumberOfKeys;
//
// Timestamp counter incremented every refresh
//
UINT64 Counter;
//
// Remove key if it was not submitted after this value.
//
UINT8 KeyForgotThreshold;
//
// Assume simultaneous press if within this value.
//
UINT8 KeyMergeThreshold;
} AIK_TARGET;
EFI_STATUS
AIKTargetInstall (
IN OUT AIK_TARGET *Target,
IN UINT8 KeyForgotThreshold,
IN UINT8 KeyMergeThreshold
);
VOID
AIKTargetUninstall (
IN OUT AIK_TARGET *Target
);
UINT64
AIKTargetRefresh (
IN OUT AIK_TARGET *Target
);
VOID
AIKTargetWriteEntry (
IN OUT AIK_TARGET *Target,
IN AMI_EFI_KEY_DATA *KeyData
);
VOID
AIKTargetSubmit (
IN OUT AIK_TARGET *Target
);
#endif

View File

@ -0,0 +1,199 @@
/** @file
Key translator
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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 "AIKTranslate.h"
#include <Library/DebugLib.h>
STATIC
APPLE_MODIFIER_MAP mModifierRemap[AIK_MODIFIER_MAX];
STATIC
VOID
AIKTranslateModifiers (
IN AMI_EFI_KEY_DATA *KeyData,
OUT APPLE_MODIFIER_MAP *Modifiers
)
{
UINT32 KeyShiftState;
KeyShiftState = KeyData->KeyState.KeyShiftState;
*Modifiers = 0;
//
// Handle EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL Shift support, which is not included
// in KeyShiftState on APTIO and VMware.
// UPD: Recent APTIO V also does not include it in its own protocol.
//
if ((KeyShiftState & EFI_SHIFT_STATE_VALID) && KeyData->Key.UnicodeChar < AIK_MAX_EFIKEY_NUM) {
KeyShiftState |= gAikAsciiToUsbMap[KeyData->Key.UnicodeChar].ShiftState;
}
//
// Handle legacy EFI_SIMPLE_TEXT_INPUT_PROTOCOL by guessing from EfiKey
//
if ((KeyShiftState & EFI_SHIFT_STATE_VALID) != EFI_SHIFT_STATE_VALID
&& KeyData->Key.UnicodeChar < AIK_MAX_EFIKEY_NUM) {
KeyShiftState = gAikAsciiToUsbMap[KeyData->Key.UnicodeChar].ShiftState;
}
if (KeyShiftState & EFI_SHIFT_STATE_VALID) {
if (KeyShiftState & EFI_RIGHT_SHIFT_PRESSED) {
*Modifiers |= mModifierRemap[AIK_RIGHT_SHIFT];
}
if (KeyShiftState & EFI_LEFT_SHIFT_PRESSED) {
*Modifiers |= mModifierRemap[AIK_LEFT_SHIFT];
}
if (KeyShiftState & EFI_RIGHT_CONTROL_PRESSED) {
*Modifiers |= mModifierRemap[AIK_RIGHT_CONTROL];
}
if (KeyShiftState & EFI_LEFT_CONTROL_PRESSED) {
*Modifiers |= mModifierRemap[AIK_LEFT_CONTROL];
}
if (KeyShiftState & EFI_RIGHT_ALT_PRESSED) {
*Modifiers |= mModifierRemap[AIK_RIGHT_ALT];
}
if (KeyShiftState & EFI_LEFT_ALT_PRESSED) {
*Modifiers |= mModifierRemap[AIK_LEFT_ALT];
}
if (KeyShiftState & EFI_RIGHT_LOGO_PRESSED) {
*Modifiers |= mModifierRemap[AIK_RIGHT_GUI];
}
if (KeyShiftState & EFI_LEFT_LOGO_PRESSED) {
*Modifiers |= mModifierRemap[AIK_LEFT_GUI];
}
}
}
STATIC
VOID
AIKTranslateNumpad (
IN OUT UINT8 *UsbKey,
IN EFI_KEY EfiKey
)
{
switch (EfiKey) {
case EfiKeyZero:
*UsbKey = UsbHidUsageIdKbKpKeyZero;
break;
case EfiKeyOne:
*UsbKey = UsbHidUsageIdKbKpKeyOne;
break;
case EfiKeyTwo:
*UsbKey = UsbHidUsageIdKbKpKeyTwo;
break;
case EfiKeyThree:
*UsbKey = UsbHidUsageIdKbKpKeyThree;
break;
case EfiKeyFour:
*UsbKey = UsbHidUsageIdKbKpKeyFour;
break;
case EfiKeyFive:
*UsbKey = UsbHidUsageIdKbKpKeyFive;
break;
case EfiKeySix:
*UsbKey = UsbHidUsageIdKbKpKeySix;
break;
case EfiKeySeven:
*UsbKey = UsbHidUsageIdKbKpKeySeven;
break;
case EfiKeyEight:
*UsbKey = UsbHidUsageIdKbKpKeyEight;
break;
case EfiKeyNine:
*UsbKey = UsbHidUsageIdKbKpKeyNine;
break;
default:
break;
}
}
VOID
AIKTranslateConfigure (
VOID
)
{
UINTN Index;
CONST APPLE_MODIFIER_MAP DefaultModifierMap[AIK_MODIFIER_MAX] = {
USB_HID_KB_KP_MODIFIER_RIGHT_SHIFT,
USB_HID_KB_KP_MODIFIER_LEFT_SHIFT,
USB_HID_KB_KP_MODIFIER_RIGHT_CONTROL,
USB_HID_KB_KP_MODIFIER_LEFT_CONTROL,
USB_HID_KB_KP_MODIFIER_RIGHT_ALT,
USB_HID_KB_KP_MODIFIER_LEFT_ALT,
USB_HID_KB_KP_MODIFIER_RIGHT_GUI,
USB_HID_KB_KP_MODIFIER_LEFT_GUI
};
//TODO: This should be user-configurable, perhaps via a nvram variable.
// You can swap Alt with Gui, to get Apple layout on a PC keyboard
CONST UINTN DefaultModifierConfig[AIK_MODIFIER_MAX/2] = {
AIK_RIGHT_SHIFT,
AIK_RIGHT_CONTROL,
AIK_RIGHT_ALT,
AIK_RIGHT_GUI
};
for (Index = 0; Index < AIK_MODIFIER_MAX/2; Index++) {
mModifierRemap[Index*2] = DefaultModifierMap[DefaultModifierConfig[Index]];
mModifierRemap[Index*2+1] = DefaultModifierMap[DefaultModifierConfig[Index]+1];
}
}
VOID
AIKTranslate (
IN AMI_EFI_KEY_DATA *KeyData,
OUT APPLE_MODIFIER_MAP *Modifiers,
OUT APPLE_KEY_CODE *Key
)
{
AIK_PS2KEY_TO_USB Ps2Key;
AIKTranslateModifiers (KeyData, Modifiers);
*Key = UsbHidUndefined;
//
// Firstly check for APTIO protocol, which reported a PS/2 key to us.
// Otherwise try to decode UnicodeChar and Scancode from simple input.
//
if (KeyData->PS2ScanCodeIsValid == 1 && KeyData->PS2ScanCode < AIK_MAX_PS2KEY_NUM) {
Ps2Key = gAikPs2KeyToUsbMap[KeyData->PS2ScanCode];
if (Ps2Key.UsbCode != UsbHidUndefined) {
//
// We need to process numpad keys separately.
//
AIKTranslateNumpad (&Ps2Key.UsbCode, KeyData->EfiKey);
*Key = APPLE_HID_USB_KB_KP_USAGE (Ps2Key.UsbCode);
}
} else if (KeyData->Key.UnicodeChar >= 0
&& KeyData->Key.UnicodeChar < AIK_MAX_ASCII_NUM
&& gAikAsciiToUsbMap[KeyData->Key.UnicodeChar].UsbCode != UsbHidUndefined) {
*Key = APPLE_HID_USB_KB_KP_USAGE (gAikAsciiToUsbMap[KeyData->Key.UnicodeChar].UsbCode);
} else if (KeyData->Key.ScanCode < AIK_MAX_SCANCODE_NUM
&& gAikScanCodeToUsbMap[KeyData->Key.ScanCode].UsbCode != UsbHidUndefined) {
*Key = APPLE_HID_USB_KB_KP_USAGE (gAikScanCodeToUsbMap[KeyData->Key.ScanCode].UsbCode);
}
if (*Key != UsbHidUndefined) {
DEBUG ((DEBUG_VERBOSE, "\nAIKTranslate P1 MOD %a APPLE 0x%X (%a) PS2 0x%X Ps2Name %a\n",
AIK_MODIFIERS_TO_NAME (*Modifiers), *Key, AIK_APPLEKEY_TO_NAME (*Key),
KeyData->PS2ScanCode, AIK_PS2KEY_TO_NAME (KeyData->PS2ScanCode, *Modifiers)));
DEBUG ((DEBUG_VERBOSE, "AIKTranslate P2 AsciiName %a ScanName %a EfiKey %a Scan 0x%X Uni 0x%X SState 0x%X\n",
AIK_ASCII_TO_NAME (KeyData->Key.UnicodeChar), AIK_SCANCODE_TO_NAME (KeyData->Key.ScanCode),
AIK_EFIKEY_TO_NAME (KeyData->EfiKey), KeyData->Key.ScanCode, KeyData->Key.UnicodeChar, KeyData->KeyState.KeyShiftState));
}
}

View File

@ -0,0 +1,126 @@
/** @file
Key translator
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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.
**/
#ifndef AIK_TRANSLATE_H
#define AIK_TRANSLATE_H
#include <IndustryStandard/AppleHid.h>
#include <Protocol/AmiKeycode.h>
#define AIK_MAX_PS2KEY_NUM 128
#define AIK_MAX_EFIKEY_NUM 128
#define AIK_MAX_ASCII_NUM 128
#define AIK_MAX_SCANCODE_NUM 24
#define AIK_MAX_MODIFIERS_NUM ( \
USB_HID_KB_KP_MODIFIER_RIGHT_SHIFT \
| USB_HID_KB_KP_MODIFIER_LEFT_SHIFT \
| USB_HID_KB_KP_MODIFIER_RIGHT_CONTROL \
| USB_HID_KB_KP_MODIFIER_LEFT_CONTROL \
| USB_HID_KB_KP_MODIFIER_RIGHT_ALT \
| USB_HID_KB_KP_MODIFIER_LEFT_ALT \
| USB_HID_KB_KP_MODIFIER_RIGHT_GUI \
| USB_HID_KB_KP_MODIFIER_LEFT_GUI \
)
#define AIK_APPLEKEY_MIN AppleHidUsbKbUsageKeyA
#define AIK_APPLEKEY_MAX AppleHidUsbKbUsageKeyUpArrow
#define AIK_MAX_APPLEKEY_NUM ((AIK_APPLEKEY_MAX) - (AIK_APPLEKEY_MIN) + 1)
typedef struct {
UINT8 UsbCode;
CONST CHAR8 *KeyName;
CONST CHAR8 *ShiftKeyName;
} AIK_PS2KEY_TO_USB;
typedef struct {
UINT8 UsbCode;
UINT32 ShiftState;
CONST CHAR8 *KeyName;
} AIK_EFIKEY_TO_USB;
typedef struct {
UINT8 UsbCode;
UINT32 ShiftState;
CONST CHAR8 *KeyName;
} AIK_ASCII_TO_USB;
typedef struct {
UINT8 UsbCode;
CONST CHAR8 *KeyName;
} AIK_SCANCODE_TO_USB;
extern AIK_PS2KEY_TO_USB gAikPs2KeyToUsbMap[AIK_MAX_PS2KEY_NUM];
extern AIK_EFIKEY_TO_USB gAikEfiKeyToUsbMap[AIK_MAX_EFIKEY_NUM];
extern AIK_ASCII_TO_USB gAikAsciiToUsbMap[AIK_MAX_ASCII_NUM];
extern AIK_SCANCODE_TO_USB gAikScanCodeToUsbMap[AIK_MAX_SCANCODE_NUM];
extern CONST CHAR8 * gAikModifiersToNameMap[AIK_MAX_MODIFIERS_NUM];
extern CONST CHAR8 * gAikAppleKeyToNameMap[AIK_MAX_APPLEKEY_NUM];
#define AIK_PS2KEY_TO_NAME(k, m) \
(((k) < AIK_MAX_PS2KEY_NUM && gAikPs2KeyToUsbMap[k].KeyName) \
? (((m) & (EFI_LEFT_SHIFT_PRESSED|EFI_RIGHT_SHIFT_PRESSED)) \
? gAikPs2KeyToUsbMap[k].ShiftKeyName : gAikPs2KeyToUsbMap[k].KeyName) \
: "<ps2key>")
#define AIK_EFIKEY_TO_NAME(k) \
(((k) < AIK_MAX_EFIKEY_NUM && gAikEfiKeyToUsbMap[k].KeyName) \
? gAikEfiKeyToUsbMap[k].KeyName \
: "<efikey>")
#define AIK_ASCII_TO_NAME(k) \
(((k) >= 0 && (k) < AIK_MAX_ASCII_NUM && gAikAsciiToUsbMap[k].KeyName) \
? gAikAsciiToUsbMap[k].KeyName \
: "<ascii>")
#define AIK_SCANCODE_TO_NAME(k) \
(((k) < AIK_MAX_SCANCODE_NUM && gAikScanCodeToUsbMap[k].KeyName) \
? gAikScanCodeToUsbMap[k].KeyName \
: "<scancode>")
#define AIK_MODIFIERS_TO_NAME(k) \
(((k) < AIK_MAX_MODIFIERS_NUM && gAikModifiersToNameMap[k]) \
? gAikModifiersToNameMap[k] \
: "<none>")
#define AIK_APPLEKEY_TO_NAME(k) \
(((k) >= AIK_APPLEKEY_MIN && (k) <= AIK_APPLEKEY_MAX && gAikAppleKeyToNameMap[(k) - AIK_APPLEKEY_MIN]) \
? gAikAppleKeyToNameMap[(k) - AIK_APPLEKEY_MIN] \
: "<aapl>")
enum {
AIK_RIGHT_SHIFT,
AIK_LEFT_SHIFT,
AIK_RIGHT_CONTROL,
AIK_LEFT_CONTROL,
AIK_RIGHT_ALT,
AIK_LEFT_ALT,
AIK_RIGHT_GUI,
AIK_LEFT_GUI,
AIK_MODIFIER_MAX
};
VOID
AIKTranslateConfigure (
VOID
);
VOID
AIKTranslate (
IN AMI_EFI_KEY_DATA *KeyData,
OUT APPLE_MODIFIER_MAP *Modifiers,
OUT APPLE_KEY_CODE *Key
);
#endif

View File

@ -0,0 +1,207 @@
AppleHidUsbKbUsageKeyA = 0x7004
AppleHidUsbKbUsageKeyB = 0x7005
AppleHidUsbKbUsageKeyC = 0x7006
AppleHidUsbKbUsageKeyD = 0x7007
AppleHidUsbKbUsageKeyE = 0x7008
AppleHidUsbKbUsageKeyF = 0x7009
AppleHidUsbKbUsageKeyG = 0x700A
AppleHidUsbKbUsageKeyH = 0x700B
AppleHidUsbKbUsageKeyI = 0x700C
AppleHidUsbKbUsageKeyJ = 0x700D
AppleHidUsbKbUsageKeyK = 0x700E
AppleHidUsbKbUsageKeyL = 0x700F
AppleHidUsbKbUsageKeyM = 0x7010
AppleHidUsbKbUsageKeyN = 0x7011
AppleHidUsbKbUsageKeyO = 0x7012
AppleHidUsbKbUsageKeyP = 0x7013
AppleHidUsbKbUsageKeyQ = 0x7014
AppleHidUsbKbUsageKeyR = 0x7015
AppleHidUsbKbUsageKeyS = 0x7016
AppleHidUsbKbUsageKeyT = 0x7017
AppleHidUsbKbUsageKeyU = 0x7018
AppleHidUsbKbUsageKeyV = 0x7019
AppleHidUsbKbUsageKeyW = 0x701A
AppleHidUsbKbUsageKeyX = 0x701B
AppleHidUsbKbUsageKeyY = 0x701C
AppleHidUsbKbUsageKeyZ = 0x701D
AppleHidUsbKbUsageKeyOne = 0x701E
AppleHidUsbKbUsageKeyTwo = 0x701F
AppleHidUsbKbUsageKeyThree = 0x7020
AppleHidUsbKbUsageKeyFour = 0x7021
AppleHidUsbKbUsageKeyFive = 0x7022
AppleHidUsbKbUsageKeySix = 0x7023
AppleHidUsbKbUsageKeySeven = 0x7024
AppleHidUsbKbUsageKeyEight = 0x7025
AppleHidUsbKbUsageKeyNine = 0x7026
AppleHidUsbKbUsageKeyZero = 0x7027
AppleHidUsbKbUsageKeyEnter = 0x7028
AppleHidUsbKbUsageKeyEscape = 0x7029
AppleHidUsbKbUsageKeyBackSpace = 0x702A
AppleHidUsbKbUsageKeyTab = 0x702B
AppleHidUsbKbUsageKeySpaceBar = 0x702C
AppleHidUsbKbUsageKeyMinus = 0x702D
AppleHidUsbKbUsageKeyEquals = 0x702E
AppleHidUsbKbUsageKeyLeftBracket = 0x702F
AppleHidUsbKbUsageKeyRightBracket = 0x7030
AppleHidUsbKbUsageKeyBackslash = 0x7031
AppleHidUsbKbUsageKeyNonUsHash = 0x7032
AppleHidUsbKbUsageKeySemicolon = 0x7033
AppleHidUsbKbUsageKeyQuotation = 0x7034
AppleHidUsbKbUsageKeyAcute = 0x7035
AppleHidUsbKbUsageKeyComma = 0x7036
AppleHidUsbKbUsageKeyPeriod = 0x7037
AppleHidUsbKbUsageKeySlash = 0x7038
AppleHidUsbKbUsageKeyCLock = 0x7039
AppleHidUsbKbUsageKeyF1 = 0x703A
AppleHidUsbKbUsageKeyF2 = 0x703B
AppleHidUsbKbUsageKeyF3 = 0x703C
AppleHidUsbKbUsageKeyF4 = 0x703D
AppleHidUsbKbUsageKeyF5 = 0x703E
AppleHidUsbKbUsageKeyF6 = 0x703F
AppleHidUsbKbUsageKeyF7 = 0x7040
AppleHidUsbKbUsageKeyF8 = 0x7041
AppleHidUsbKbUsageKeyF9 = 0x7042
AppleHidUsbKbUsageKeyF10 = 0x7043
AppleHidUsbKbUsageKeyF11 = 0x7044
AppleHidUsbKbUsageKeyF12 = 0x7045
AppleHidUsbKbUsageKeyPrint = 0x7046
AppleHidUsbKbUsageKeySLock = 0x7047
AppleHidUsbKbUsageKeyPause = 0x7048
AppleHidUsbKbUsageKeyIns = 0x7049
AppleHidUsbKbUsageKeyHome = 0x704A
AppleHidUsbKbUsageKeyPgUp = 0x704B
AppleHidUsbKbUsageKeyDel = 0x704C
AppleHidUsbKbUsageKeyEnd = 0x704D
AppleHidUsbKbUsageKeyPgDn = 0x704E
AppleHidUsbKbUsageKeyRightArrow = 0x704F
AppleHidUsbKbUsageKeyLeftArrow = 0x7050
AppleHidUsbKbUsageKeyDownArrow = 0x7051
AppleHidUsbKbUsageKeyUpArrow = 0x7052
AppleHidUsbKbUsageKeyPadNLck = 0x7053
AppleHidUsbKbUsageKeyPadSlash = 0x7054
AppleHidUsbKbUsageKeyPadAsterisk = 0x7055
AppleHidUsbKbUsageKeyPadMinus = 0x7056
AppleHidUsbKbUsageKeyPadPlus = 0x7057
AppleHidUsbKbUsageKeyPadEnter = 0x7058
AppleHidUsbKbUsageKeyPadOne = 0x7059
AppleHidUsbKbUsageKeyPadTwo = 0x705A
AppleHidUsbKbUsageKeyPadThree = 0x705B
AppleHidUsbKbUsageKeyPadFour = 0x705C
AppleHidUsbKbUsageKeyPadFive = 0x705D
AppleHidUsbKbUsageKeyPadSix = 0x705E
AppleHidUsbKbUsageKeyPadSeven = 0x705F
AppleHidUsbKbUsageKeyPadEight = 0x7060
AppleHidUsbKbUsageKeyPadNine = 0x7061
AppleHidUsbKbUsageKeyPadIns = 0x7062
AppleHidUsbKbUsageKeyPadDel = 0x7063
AppleHidUsbKbUsageKeyPadNonUsBackslash = 0x7064
AppleHidUsbKbUsageKeyPadApplication = 0x7065
AppleHidUsbKbUsageKeyPadPower = 0x7066
AppleHidUsbKbUsageKeyPadEquals = 0x7067
AppleHidUsbKbUsageKeyF13 = 0x7068
AppleHidUsbKbUsageKeyF14 = 0x7069
AppleHidUsbKbUsageKeyF15 = 0x706A
AppleHidUsbKbUsageKeyF16 = 0x706B
AppleHidUsbKbUsageKeyF17 = 0x706C
AppleHidUsbKbUsageKeyF18 = 0x706D
AppleHidUsbKbUsageKeyF19 = 0x706E
AppleHidUsbKbUsageKeyF20 = 0x706F
AppleHidUsbKbUsageKeyF21 = 0x7070
AppleHidUsbKbUsageKeyF22 = 0x7071
AppleHidUsbKbUsageKeyF23 = 0x7072
AppleHidUsbKbUsageKeyF24 = 0x7073
AppleHidUsbKbUsageKeyExecute = 0x7074
AppleHidUsbKbUsageKeyHelp = 0x7075
AppleHidUsbKbUsageKeyMenu = 0x7076
AppleHidUsbKbUsageKeySelect = 0x7077
AppleHidUsbKbUsageKeyStop = 0x7078
AppleHidUsbKbUsageKeyAgain = 0x7079
AppleHidUsbKbUsageKeyUndo = 0x707A
AppleHidUsbKbUsageKeyCut = 0x707B
AppleHidUsbKbUsageKeyCopy = 0x707C
AppleHidUsbKbUsageKeyPaste = 0x707D
AppleHidUsbKbUsageKeyFind = 0x707E
AppleHidUsbKbUsageKeyMute = 0x707F
AppleHidUsbKbUsageKeyVolumeUp = 0x7080
AppleHidUsbKbUsageKeyVolumeDown = 0x7081
AppleHidUsbKbUsageLockingKeyCLock = 0x7082
AppleHidUsbKbusageLockingKeyNLock = 0x7083
AppleHidUsbKbUsageLockingKeySLock = 0x7084
AppleHidUsbKbUsageKeyPadComma = 0x7085
AppleHidUsbKbUsageKeyPadEqualSign = 0x7086
AppleHidUsbKbUsageKeyInternational1 = 0x7087
AppleHidUsbKbUsageKeyInternational2 = 0x7088
AppleHidUsbKbUsageKeyInternational3 = 0x7089
AppleHidUsbKbUsageKeyInternational4 = 0x708A
AppleHidUsbKbUsageKeyInternational5 = 0x708B
AppleHidUsbKbUsageKeyInternational6 = 0x708C
AppleHidUsbKbUsageKeyInternational7 = 0x708D
AppleHidUsbKbUsageKeyInternational8 = 0x708E
AppleHidUsbKbUsageKeyInternational9 = 0x708F
AppleHidUsbKbUsageKeyLang1 = 0x7090
AppleHidUsbKbUsageKeyLang2 = 0x7091
AppleHidUsbKbUsageKeyLang3 = 0x7092
AppleHidUsbKbUsageKeyLang4 = 0x7093
AppleHidUsbKbUsageKeyLang5 = 0x7094
AppleHidUsbKbUsageKeyLang6 = 0x7095
AppleHidUsbKbUsageKeyLang7 = 0x7096
AppleHidUsbKbUsageKeyLang8 = 0x7097
AppleHidUsbKbUsageKeyLang9 = 0x7098
AppleHidUsbKbUsageKeyAlternateErase = 0x7099
AppleHidUsbKbUsageKeySysReq = 0x709A
AppleHidUsbKbUsageKeyCancel = 0x709B
AppleHidUsbKbUsageKeyClear = 0x709C
AppleHidUsbKbUsageKeyPrior = 0x709D
AppleHidUsbKbUsageKeyReturn = 0x709E
AppleHidUsbKbUsageKeySeparator = 0x709F
AppleHidUsbKbUsageKeyOut = 0x70A0
AppleHidUsbKbUsageKeyOper = 0x70A1
AppleHidUsbKbUsageKeyClearAgain = 0x70A2
AppleHidUsbKbUsageKeyCrSel = 0x70A3
AppleHidUsbKbUsageKeyExSel = 0x70A4
AppleHidUsbKbUsageKeyPadDoubleZero = 0x70B0
AppleHidUsbKbUsageKeyTrippleZero = 0x70B1
AppleHidUsbKbUsageKeyThousandsSeparator = 0x70B2
AppleHidUsbKbUsageKeyDecimalSeparator = 0x70B3
AppleHidUsbKbUsageKeyCurrencyUnit = 0x70B4
AppleHidUsbKbUsageKeyCurrencySubUnit = 0x70B5
AppleHidUsbKbUsageKeyPadLeftBracket = 0x70B6
AppleHidUsbKbUsageKeyPadRightBracket = 0x70B7
AppleHidUsbKbUsageKeyPadCurlyLeftBracket = 0x70B8
AppleHidUsbKbUsageKeyPadCurlyRightBracket = 0x70B9
AppleHidUsbKbUsageKeyPadTab = 0x70BA
AppleHidUsbKbUsageKeyPadBackspace = 0x70BB
AppleHidUsbKbUsageKeyPadA = 0x70BC
AppleHidUsbKbUsageKeyPadB = 0x70BD
AppleHidUsbKbUsageKeyPadC = 0x70BE
AppleHidUsbKbUsageKeyPadD = 0x70BF
AppleHidUsbKbUsageKeyPadE = 0x70C0
AppleHidUsbKbUsageKeyPadF = 0x70C1
AppleHidUsbKbUsageKeyPadXor = 0x70C2
AppleHidUsbKbUsageKeyPadCaret = 0x70C3
AppleHidUsbKbUsageKeyPadPercent = 0x70C4
AppleHidUsbKbUsageKeyPadLeftAngleBracket = 0x70C5
AppleHidUsbKbUsageKeyPadRightAngleBracket = 0x70C6
AppleHidUsbKbUsageKeyPadBitwiseAnd = 0x70C7
AppleHidUsbKbUsageKeyPadLogicalAnd = 0x70C8
AppleHidUsbKbUsageKeyPadBitwiseOr = 0x70C9
AppleHidUsbKbUsageKeyPadLogicalOr = 0x70CA
AppleHidUsbKbUsageKeyPadColon = 0x70CB
AppleHidUsbKbUsageKeyPadHash = 0x70CC
AppleHidUsbKbUsageKeyPadSpace = 0x70CD
AppleHidUsbKbUsageKeyPadAt = 0x70CE
AppleHidUsbKbUsageKeyPadExclamationMark = 0x70CF
AppleHidUsbKbUsageKeyPadMemoryStore = 0x70D0
AppleHidUsbKbUsageKeyPadMemoryRecall = 0x70D1
AppleHidUsbKbUsageKeyPadMemoryClear = 0x70D2
AppleHidUsbKbUsageKeyPadMemoryAdd = 0x70D3
AppleHidUsbKbUsageKeyPadMemorySubtract = 0x70D4
AppleHidUsbKbUsageKeyPadMemoryMultiply = 0x70D5
AppleHidUsbKbUsageKeyPadMemoryDivide = 0x70D6
AppleHidUsbKbUsageKeyPadSign = 0x70D7
AppleHidUsbKbUsageKeyPadClear = 0x70D8
AppleHidUsbKbUsageKeyPadClearEntry = 0x70D9
AppleHidUsbKbUsageKeyPadBinary = 0x70DA
AppleHidUsbKbUsageKeyPadOctal = 0x70DB
AppleHidUsbKbUsageKeyPadDecimal = 0x70DC
AppleHidUsbKbUsageKeyPadHexadecimal = 0x70DD

View File

@ -0,0 +1,86 @@
## @file
# Copyright (c) 2016, vit9696. All rights reserved.<BR>
#
# 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.
#
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = OcInputLib
FILE_GUID = F39652DB-3D7E-49CC-A66B-E99AC74F5D37
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = OcInputLib|DXE_CORE DXE_SMM_CORE UEFI_DRIVER UEFI_APPLICATION DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER
[Sources]
Keycode/AIK.h
Keycode/AIK.c
Keycode/AIKData.c
Keycode/AIKData.h
Keycode/AIKMap.c
Keycode/AIKShim.c
Keycode/AIKShim.h
Keycode/AIKSource.c
Keycode/AIKSource.h
Keycode/AIKTarget.c
Keycode/AIKTarget.h
Keycode/AIKTranslate.c
Keycode/AIKTranslate.h
Pointer/AIM.h
Pointer/AIM.c
Timer/AIT.c
[Packages]
EfiPkg/EfiPkg.dec
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
OcSupportPkg/OcSupportPkg.dec
[LibraryClasses]
BaseMemoryLib
DebugLib
HiiLib
MemoryAllocationLib
OcGuardLib
PcdLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiLib
UefiRuntimeServicesTableLib
UefiUsbLib
[Guids]
#
# Event registered to EFI_HII_SET_KEYBOARD_LAYOUT_EVENT_GUID group,
# which will be triggered by EFI_HII_DATABASE_PROTOCOL.SetKeyboardLayout().
#
gEfiHiiKeyBoardLayoutGuid ## SOMETIMES_CONSUMES ## Event
gUsbKeyboardLayoutPackageGuid ## SOMETIMES_CONSUMES ## HII
gUsbKeyboardLayoutKeyGuid ## SOMETIMES_PRODUCES ## UNDEFINED
gAppleKeyboardPlatformInfoGuid ## SOMETIMES_CONSUMES
[Protocols]
gEfiUsbIoProtocolGuid ## TO_START
gEfiDevicePathProtocolGuid ## TO_START
gEfiSimpleTextInProtocolGuid ## BY_START
gEfiSimpleTextInputExProtocolGuid ## BY_START
gEfiSimplePointerProtocolGuid ## BY_START
gEfiTimerArchProtocolGuid ## BY_START
#
# If HII Database Protocol exists, then keyboard layout from HII database is used.
# Otherwise, USB keyboard module tries to use its carried default layout.
#
gEfiHiiDatabaseProtocolGuid ## SOMETIMES_CONSUMES
gAppleKeyMapDatabaseProtocolGuid ## SOMETIMES_CONSUMES
gApplePlatformInfoDatabaseProtocolGuid ## SOMETMES_CONSUMES
gEfiKeyboardInfoProtocolGuid ## SOMETIMES_PRODUCES
gAmiEfiPointerProtocolGuid ## SOMETMES_CONSUMES
gAmiEfiKeycodeProtocolGuid ## SOMETMES_CONSUMES

View File

@ -0,0 +1,573 @@
/** @file
AmiEfiPointer to EfiPointer translator.
Copyright (c) 2016, vit9696. All rights reserved.<BR>
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 <Uefi.h>
#include "AIM.h"
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/OcInputLib.h>
#include <Library/UefiBootServicesTableLib.h>
STATIC AMI_SHIM_POINTER mAmiShimPointer;
STATIC UINT8 gIndex = 0;
STATIC UINT8 gXCounts[5] = {0, 0, 0, 0, 0};
STATIC UINT8 gYCounts[5] = {0, 0, 0, 0, 0};
UINT8
EFIAPI
Abs (
IN INT32 Value
)
{
return (UINT8)(Value < 0 ? -Value : Value);
}
INT32
EFIAPI
InternalClamp (
IN INT32 Value,
IN INT32 Min,
IN INT32 Max
)
{
if (Value > Max) {
return Max;
} else if (Value < Min) {
return Min;
}
return Value;
}
VOID
EFIAPI
AmiShimPointerFilterOut (
IN OUT UINT8 *AbsX,
IN OUT UINT8 *AbsY,
IN OUT INT32 *X,
IN OUT INT32 *Y
)
{
UINT8 Index;
if (*AbsX == 0) {
gXCounts[gIndex] = 1;
} else if (*AbsX <= 2) {
for (Index = 0; Index < 5; Index++) {
if (!gXCounts[Index])
break;
}
if (Index == 5) {
*AbsX = 0;
*X = 0;
}
gXCounts[gIndex] = 0;
}
if (*AbsY == 0) {
gYCounts[gIndex] = 1;
} else if (*AbsY <= 2) {
for (Index = 0; Index < 5; Index++) {
if (!gYCounts[Index])
break;
}
if (Index == 5) {
*AbsY = 0;
*Y = 0;
}
gYCounts[gIndex] = 0;
}
gIndex = gIndex < 4 ? gIndex + 1 : 0;
}
#ifdef AMI_SHIM_POINTER_AMI_SMOOTHING
STATIC UINT8 gAbsRange[8] = {42, 36, 30, 24, 18, 12, 6, 1};
STATIC INT32 gMultipliers[8] = {8, 7, 6, 5, 4, 3, 2, 1};
STATIC INT32 gIndices[8] = {2, 2, 2, 2, 2, 2, 2, 0};
INT32
AmiShimPointerScale (
IN INT32 Value,
IN UINT8 AbsValue
)
{
UINT8 TmpIndex;
for (TmpIndex = 0; TmpIndex < 8; TmpIndex++) {
if (AbsValue >= gAbsRange[TmpIndex]) {
break;
}
}
if (TmpIndex != 8) {
if (Value >= 0) {
Value = gIndices[TmpIndex] + Value * gMultipliers[TmpIndex];
} else {
Value = Value * gMultipliers[TmpIndex] - gIndices[TmpIndex];
}
}
return Value;
}
VOID
EFIAPI
AmiShimPointerSmooth (
IN OUT INT32 *X,
IN OUT INT32 *Y,
IN OUT INT32 *Z
)
{
UINT8 AbsX, AbsY;
*X = Clamp (*X, -16, 16);
*Y = Clamp (*Y, -16, 16);
// According to AMI it should not be reported
*Z = 0;
AbsX = Abs (*X);
AbsY = Abs (*Y);
if (*X == 0 && *Y == 0) {
return;
}
AmiShimPointerFilterOut (&AbsX, &AbsY, X, Y);
*X = AmiShimPointerScale(*X, AbsX);
*Y = AmiShimPointerScale(*Y, AbsY);
*X *= AIM_SCALE_FACTOR;
*Y *= AIM_SCALE_FACTOR;
}
#else
STATIC UINT8 gAbsRange[4] = {80, 64, 48, 1};
STATIC INT32 gMultipliers[4] = {4, 3, 2, 1};
VOID
EFIAPI
AmiShimPointerBoostValue (
IN OUT INT32 *Value,
IN INT32 AbsValue
)
{
UINTN Index;
for (Index = 0; Index < 4; Index++) {
if (gAbsRange[Index] > AbsValue) {
*Value *= gMultipliers[Index];
return;
}
}
}
VOID
EFIAPI
AmiShimPointerSmooth (
IN OUT INT32 *X,
IN OUT INT32 *Y,
IN OUT INT32 *Z
)
{
UINT8 AbsX, AbsY;
*X = InternalClamp(*X, -96, 96);
*Y = InternalClamp(*Y, -96, 96);
*Z = 0;
AbsX = Abs (*X);
AbsY = Abs (*Y);
if (*X == 0 && *Y == 0) {
return;
}
AmiShimPointerFilterOut (&AbsX, &AbsY, X, Y);
AmiShimPointerBoostValue(X, AbsX);
AmiShimPointerBoostValue(Y, AbsY);
}
#endif
VOID
EFIAPI
AmiShimPointerPositionHandler (
IN EFI_EVENT Event,
IN VOID *Context
)
{
UINTN Index;
AMI_SHIM_POINTER_INSTANCE *Pointer;
AMI_POINTER_POSITION_STATE_DATA PositionState;
// Do not poll until somebody actually starts using the mouse
// Otherwise first move will be quite random
if (!mAmiShimPointer.UsageStarted) {
return;
}
// This is important to do quickly and separately, because AMI stores positioning data in INT8.
// If we move the mouse quickly it will overflow and return invalid data.
for (Index = 0; Index < AIM_MAX_POINTERS; Index++) {
Pointer = &mAmiShimPointer.PointerMap[Index];
if (Pointer->DeviceHandle != NULL) {
PositionState.Changed = 0;
Pointer->EfiPointer->GetPositionState (Pointer->EfiPointer, &PositionState);
if (PositionState.Changed == 1) {
if (PositionState.Absolute == 0) {
DEBUG ((DEBUG_VERBOSE, "Position: %d %d %d %d\n",
PositionState.Changed, PositionState.PositionX, PositionState.PositionY, PositionState.PositionZ));
AmiShimPointerSmooth(&PositionState.PositionX, &PositionState.PositionY, &PositionState.PositionZ);
if (PositionState.PositionX != 0 || PositionState.PositionY != 0 || PositionState.PositionZ != 0) {
Pointer->PositionX += PositionState.PositionX;
Pointer->PositionY += PositionState.PositionY;
Pointer->PositionZ += PositionState.PositionZ;
Pointer->PositionChanged = TRUE;
}
} else {
//FIXME: Add support for devices with absolute positioning
}
}
}
}
}
EFI_STATUS
EFIAPI
AmiShimPointerUpdateState (
IN AMI_SHIM_POINTER_INSTANCE *Pointer,
OUT EFI_SIMPLE_POINTER_STATE *State
)
{
AMI_POINTER_BUTTON_STATE_DATA ButtonState;
if (!mAmiShimPointer.UsageStarted) {
mAmiShimPointer.UsageStarted = TRUE;
AmiShimPointerPositionHandler(NULL, NULL);
}
ButtonState.Changed = 0;
Pointer->EfiPointer->GetButtonState (Pointer->EfiPointer, &ButtonState);
if (ButtonState.Changed == 0 && Pointer->PositionChanged == 0) {
return EFI_NOT_READY;
}
DEBUG ((DEBUG_VERBOSE, "Button: %d %d %d %d, Position: %d %d %d %d\n",
ButtonState.Changed, ButtonState.LeftButton, ButtonState.MiddleButton, ButtonState.RightButton,
Pointer->PositionChanged, Pointer->PositionX, Pointer->PositionY, Pointer->PositionZ));
if (ButtonState.Changed) {
State->LeftButton = ButtonState.LeftButton;
State->RightButton = ButtonState.RightButton;
} else {
State->LeftButton = State->RightButton = FALSE;
}
if (Pointer->PositionChanged) {
State->RelativeMovementX = Pointer->PositionX;
State->RelativeMovementY = Pointer->PositionY;
State->RelativeMovementZ = Pointer->PositionZ;
} else {
State->RelativeMovementX = State->RelativeMovementY = State->RelativeMovementZ = 0;
}
Pointer->PositionChanged = 0;
Pointer->PositionX = Pointer->PositionY = Pointer->PositionZ = 0;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
AmiShimPointerGetState (
IN EFI_SIMPLE_POINTER_PROTOCOL *This,
IN OUT EFI_SIMPLE_POINTER_STATE *State
)
{
EFI_STATUS Status;
UINTN Index;
AMI_SHIM_POINTER_INSTANCE *Pointer;
if (This == NULL || State == NULL) {
return EFI_INVALID_PARAMETER;
}
for (Index = 0, Pointer = mAmiShimPointer.PointerMap; Index < AIM_MAX_POINTERS; Index++, Pointer++) {
if (Pointer->SimplePointer == This) {
break;
}
}
if (Index != AIM_MAX_POINTERS) {
Status = AmiShimPointerUpdateState (Pointer, State);
if (!EFI_ERROR (Status)) {
if (State->RelativeMovementX != 0 ||
State->RelativeMovementY != 0 ||
State->RelativeMovementZ != 0) {
DEBUG ((DEBUG_VERBOSE, "Received[%p] %d %d %d <%d, %d>\n", This, State->RelativeMovementX, State->RelativeMovementY, State->RelativeMovementZ,
State->LeftButton, State->RightButton));
} else {
DEBUG ((DEBUG_VERBOSE, "Received[%p] %d %d %d\n", This, State->RelativeMovementX, State->RelativeMovementY, State->RelativeMovementZ));
}
}
} else {
DEBUG ((DEBUG_VERBOSE, "Received unknown this %p\n", This));
Status = EFI_INVALID_PARAMETER;
}
return Status;
}
EFI_STATUS
EFIAPI
AmiShimPointerTimerSetup (
VOID
)
{
EFI_STATUS Status;
if (mAmiShimPointer.TimersInitialised) {
return EFI_ALREADY_STARTED;
}
Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_NOTIFY, AmiShimPointerPositionHandler, NULL, &mAmiShimPointer.PositionEvent);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AmiShimPointerPositionHandler event creation failed %d\n", Status));
return Status;
}
Status = gBS->SetTimer (mAmiShimPointer.PositionEvent, TimerPeriodic, AIM_POSITION_POLL_INTERVAL);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AmiShimPointerPositionHandler timer setting failed %d\n", Status));
gBS->CloseEvent (mAmiShimPointer.PositionEvent);
return Status;
}
mAmiShimPointer.TimersInitialised = TRUE;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
AmiShimPointerTimerUninstall (
VOID
)
{
EFI_STATUS Status;
if (!mAmiShimPointer.TimersInitialised) {
return EFI_SUCCESS;
}
if (mAmiShimPointer.PositionEvent != NULL) {
Status = gBS->SetTimer (mAmiShimPointer.PositionEvent, TimerCancel, 0);
if (!EFI_ERROR (Status)) {
gBS->CloseEvent (mAmiShimPointer.PositionEvent);
mAmiShimPointer.PositionEvent = NULL;
} else {
DEBUG((DEBUG_INFO, "AmiShimPointerPositionHandler timer unsetting failed %d\n", Status));
}
}
mAmiShimPointer.TimersInitialised = FALSE;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
AmiShimPointerInstallOnHandle (
IN EFI_HANDLE DeviceHandle,
IN AMI_EFIPOINTER_PROTOCOL *EfiPointer,
IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer
)
{
UINTN Index;
AMI_SHIM_POINTER_INSTANCE *Pointer;
AMI_SHIM_POINTER_INSTANCE *FreePointer;
FreePointer = NULL;
for (Index = 0; Index < AIM_MAX_POINTERS; Index++) {
Pointer = &mAmiShimPointer.PointerMap[Index];
if (Pointer->DeviceHandle == NULL && FreePointer == NULL) {
FreePointer = Pointer;
} else if (Pointer->DeviceHandle == DeviceHandle) {
return EFI_ALREADY_STARTED;
}
}
if (FreePointer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
DEBUG ((DEBUG_INFO, "Installed onto %X\n", DeviceHandle));
FreePointer->DeviceHandle = DeviceHandle;
FreePointer->EfiPointer = EfiPointer;
FreePointer->SimplePointer = SimplePointer;
if (FreePointer->SimplePointer->GetState == AmiShimPointerGetState) {
FreePointer->OriginalGetState = NULL;
DEBUG ((DEBUG_INFO, "Function is already hooked\n"));
} else {
FreePointer->OriginalGetState = FreePointer->SimplePointer->GetState;
FreePointer->SimplePointer->GetState = AmiShimPointerGetState;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
AmiShimPointerInstall (
VOID
)
{
EFI_STATUS Status;
UINTN NoHandles;
EFI_HANDLE *Handles;
UINTN Index;
BOOLEAN Installed;
AMI_EFIPOINTER_PROTOCOL *EfiPointer;
EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
Status = gBS->LocateHandleBuffer (ByProtocol, &gAmiEfiPointerProtocolGuid, NULL, &NoHandles, &Handles);
if (EFI_ERROR(Status)) {
return EFI_NOT_FOUND;
}
DEBUG ((DEBUG_INFO, "Found %d Handles located by protocol\n", NoHandles));
Installed = FALSE;
for (Index = 0; Index < NoHandles; Index++) {
Status = gBS->HandleProtocol (Handles[Index], &gAmiEfiPointerProtocolGuid, (VOID **)&EfiPointer);
if (EFI_ERROR(Status)) {
DEBUG ((DEBUG_INFO, "Handle %d has no AmiEfiPointerl %d\n", Index, Status));
continue;
}
Status = gBS->HandleProtocol (Handles[Index], &gEfiSimplePointerProtocolGuid, (VOID **)&SimplePointer);
if (EFI_ERROR(Status)) {
DEBUG ((DEBUG_INFO, "Handle %d has no EfiSimplePointer %d\n", Index, Status));
continue;
}
Status = AmiShimPointerInstallOnHandle (Handles[Index], EfiPointer, SimplePointer);
if (EFI_ERROR(Status)) {
DEBUG ((DEBUG_INFO, "Handle %d failed to get installed %d\n", Index, Status));
continue;
}
Installed = TRUE;
}
gBS->FreePool (Handles);
if (!Installed) {
return EFI_NOT_FOUND;
}
if (!mAmiShimPointer.TimersInitialised) {
return AmiShimPointerTimerSetup();
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
AmiShimPointerUninstall (
VOID
)
{
UINTN Index;
AMI_SHIM_POINTER_INSTANCE *Pointer;
AmiShimPointerTimerUninstall();
for (Index = 0; Index < AIM_MAX_POINTERS; Index++) {
Pointer = &mAmiShimPointer.PointerMap[Index];
if (Pointer->DeviceHandle != NULL) {
Pointer->SimplePointer->GetState = Pointer->OriginalGetState;
gBS->DisconnectController(Pointer->DeviceHandle, NULL, NULL);
Pointer->DeviceHandle = NULL;
}
}
return EFI_SUCCESS;
}
VOID
EFIAPI
AmiShimPointerArriveHandler (
IN EFI_EVENT Event,
IN VOID *Context
)
{
AmiShimPointerInstall();
}
EFI_STATUS
OcAppleGenericInputPointerInit (
IN OC_INPUT_POINTER_MODE Mode
)
{
EFI_STATUS Status;
VOID *Registration;
//
// Currently, ASUS is the only supported mode, hence it is not verified.
// The caller is required to pass a valid mode.
//
Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_NOTIFY, AmiShimPointerArriveHandler, NULL, &mAmiShimPointer.ProtocolArriveEvent);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AmiShimPointerArriveHandler event creation failed %d\n", Status));
return Status;
}
// EfiSimplePointer gets installed after AMI proprietary protocol
Status = gBS->RegisterProtocolNotify (&gEfiSimplePointerProtocolGuid, mAmiShimPointer.ProtocolArriveEvent, &Registration);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AmiShimProtocolArriveHandler protocol registration failed %d\n", Status));
gBS->CloseEvent (mAmiShimPointer.ProtocolArriveEvent);
return Status;
}
return AmiShimPointerInstall();
}
EFI_STATUS
OcAppleGenericInputPointerExit (
VOID
)
{
return AmiShimPointerUninstall();
}

View File

@ -0,0 +1,57 @@
/** @file
Header file for AmiEfiPointer to EfiPointer translator.
Copyright (c) 2016, vit9696. All rights reserved.<BR>
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.
**/
#ifndef AIM_SELF_H
#define AIM_SELF_H
#include <Library/UefiLib.h>
#include <Protocol/AmiPointer.h>
#include <Protocol/SimplePointer.h>
//
// Taken from APTIO IV Z87.
//
#define AIM_MAX_POINTERS 6
//
// APTIO IV Z87 has 66666 here.
// Slightly lower resolution results in sometimes overflowng mouse.
//
#define AIM_POSITION_POLL_INTERVAL 66666
//
// Position movement boost.
//
#define AIM_SCALE_FACTOR 1
typedef struct {
EFI_HANDLE DeviceHandle;
AMI_EFIPOINTER_PROTOCOL *EfiPointer;
EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer;
EFI_SIMPLE_POINTER_GET_STATE OriginalGetState;
BOOLEAN PositionChanged;
INT32 PositionX;
INT32 PositionY;
INT32 PositionZ;
} AMI_SHIM_POINTER_INSTANCE;
typedef struct {
BOOLEAN TimersInitialised;
BOOLEAN UsageStarted;
EFI_EVENT ProtocolArriveEvent;
EFI_EVENT PositionEvent;
AMI_SHIM_POINTER_INSTANCE PointerMap[AIM_MAX_POINTERS];
} AMI_SHIM_POINTER;
#endif

View File

@ -0,0 +1,88 @@
/** @file
Timer booster
Copyright (c) 2018, vit9696. All rights reserved.<BR>
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 <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Protocol/Timer.h>
STATIC UINTN mOriginalTimerPeriod;
STATIC EFI_TIMER_ARCH_PROTOCOL *mTimerProtocol;
EFI_STATUS
OcAppleGenericInputTimerQuirkInit (
IN UINT32 TimerResolution
)
{
EFI_STATUS Status;
//
// Refresh rate needs to be increased to poll mouse and keyboard frequently enough
//
Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **)&mTimerProtocol);
if (!EFI_ERROR (Status)) {
Status = mTimerProtocol->GetTimerPeriod (mTimerProtocol, &mOriginalTimerPeriod);
if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AIFTimerBoostInit Current timer is %u\n", mOriginalTimerPeriod));
if (mOriginalTimerPeriod > TimerResolution) {
Status = mTimerProtocol->SetTimerPeriod (mTimerProtocol, TimerResolution);
if (!EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "AIFTimerBoostInit changed period %d to %d\n",
mOriginalTimerPeriod, TimerResolution));
} else {
DEBUG ((DEBUG_INFO, "AIFTimerBoostInit failed to change period %d to %d, error - %r\n",
mOriginalTimerPeriod, TimerResolution, Status));
mTimerProtocol = NULL;
}
} else {
mTimerProtocol = NULL;
}
} else {
DEBUG ((DEBUG_INFO, "AIFTimerBoostInit failed to obtain previous period - %r\n", Status));
}
} else {
DEBUG ((DEBUG_INFO, "AIFTimerBoostInit gEfiTimerArchProtocolGuid not found - %r\n", Status));
}
return Status;
}
EFI_STATUS
OcAppleGenericInputTimerQuirkExit (
VOID
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
if (mTimerProtocol != NULL) {
//
// You are not allowed to call this on APTIO IV, as it results in an interrupt with 0x0 pointer
// handler during XNU boot.
//
// Status = mTimerProtocol->SetTimerPeriod (mTimerProtocol, mOriginalTimerPeriod);
// if (!EFI_ERROR (Status)) {
// DEBUG ((DEBUG_INFO, "AmiShimTimerBoostExit changed period %d to %d\n",
// AIT_TIMER_PERIOD, mOriginalTimerPeriod));
// } else {
// DEBUG ((DEBUG_INFO, "AmiShimTimerBoostExit failed to change period %d to %d, error - %r\n",
// AIT_TIMER_PERIOD, mOriginalTimerPeriod, Status));
// }
mTimerProtocol = NULL;
}
return Status;
}

View File

@ -53,6 +53,13 @@
## Include/Protocol/FirmwareVolume.h
gEfiFirmwareVolumeProtocolGuid = { 0x389F751F, 0x1838, 0x4388, { 0x83, 0x90, 0xcd, 0x81, 0x54, 0xbd, 0x27, 0xf8 }}
## Include/Protocol/AmiPointer.h
gAmiEfiPointerProtocolGuid = { 0x15A10CE7, 0xEAB5, 0x43BF, { 0x90, 0x42, 0x74, 0x43, 0x2E, 0x69, 0x63, 0x77 } }
## Include/Protocol/AmiKeycode.h
gAmiEfiKeycodeProtocolGuid = { 0x0ADFB62D, 0xFF74, 0x484C, { 0x89, 0x44, 0xF8, 0x5C, 0x4B, 0xEA, 0x87, 0xA8 } }
[PcdsFeatureFlag]
## Indicates if Apple Thunderbolt NHI protocol is called during device property export.<BR><BR>
# TRUE - Apple Thunderbolt NHI protocol will be called.<BR>

View File

@ -57,6 +57,7 @@
OcAppleDerLib|OcSupportPkg/Library/OcAppleDerLib/OcAppleDerLib.inf
OcAppleDiskImageLib|OcSupportPkg/Library/OcAppleDiskImageLib/OcAppleDiskImageLib.inf
OcAppleEventLib|OcSupportPkg/Library/OcAppleEventLib/OcAppleEventLib.inf
OcInputLib|OcSupportPkg/Library/OcInputLib/OcInputLib.inf
OcAppleImageConversionLib|OcSupportPkg/Library/OcAppleImageConversionLib/OcAppleImageConversionLib.inf
OcAppleImageVerificationLib|OcSupportPkg/Library/OcAppleImageVerificationLib/OcAppleImageVerificationLib.inf
OcAppleKernelLib|OcSupportPkg/Library/OcAppleKernelLib/OcAppleKernelLib.inf
@ -102,6 +103,7 @@
OcSupportPkg/Library/OcAppleDerLib/OcAppleDerLib.inf
OcSupportPkg/Library/OcAppleDiskImageLib/OcAppleDiskImageLib.inf
OcSupportPkg/Library/OcAppleEventLib/OcAppleEventLib.inf
OcSupportPkg/Library/OcInputLib/OcInputLib.inf
OcSupportPkg/Library/OcAppleImageConversionLib/OcAppleImageConversionLib.inf
OcSupportPkg/Library/OcAppleImageVerificationLib/OcAppleImageVerificationLib.inf
OcSupportPkg/Library/OcAppleKernelLib/OcAppleKernelLib.inf