497 lines
13 KiB
C
497 lines
13 KiB
C
//
|
|
// This file contains a 'Sample Driver' and is licensed as such
|
|
// under the terms of your license agreement with Intel or your
|
|
// vendor. This file may be modified by the user, subject to
|
|
// the additional terms of the license agreement
|
|
//
|
|
/** @file
|
|
The HID Keyboard Driver is used to manage all HID KB devices.
|
|
|
|
Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
This software and associated documentation (if any) is furnished
|
|
under a license and may only be used or copied in accordance
|
|
with the terms of the license. Except as permitted by such
|
|
license, no part of this software or documentation may be
|
|
reproduced, stored in a retrieval system, or transmitted in any
|
|
form or by any means without the express written consent of
|
|
Intel Corporation.
|
|
|
|
**/
|
|
|
|
#include "HidKbDxe.h"
|
|
#include "KeyBoard.h"
|
|
|
|
EFI_DRIVER_BINDING_PROTOCOL gHidKbDriverBinding = {
|
|
HidKbDriverBindingSupported,
|
|
HidKbDriverBindingStart,
|
|
HidKbDriverBindingStop,
|
|
0xa,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
EFI_SIMPLE_TEXT_INPUT_PROTOCOL mSimpleTextIn = {
|
|
HidKbReset,
|
|
HidKbReadKeyStroke,
|
|
NULL,
|
|
};
|
|
|
|
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL mSimpleTextInEx = {
|
|
HidKbResetEx,
|
|
HidKbReadKeyStrokeEx,
|
|
NULL,
|
|
HidKbSetState,
|
|
HidKbRegisterKeyNotify,
|
|
HidKbUnregisterKeyNotify,
|
|
};
|
|
|
|
/**
|
|
Entrypoint of HID KB Driver.
|
|
|
|
This function is the entrypoint of HID KB Driver. It installs Driver Binding
|
|
Protocols together with Component Name Protocols.
|
|
|
|
@param ImageHandle The firmware allocated handle for the EFI image.
|
|
@param SystemTable A pointer to the EFI System Table.
|
|
|
|
@retval EFI_SUCCESS The entry point is executed successfully.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
HidKbDriverBindingEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = EfiLibInstallDriverBindingComponentName2 (
|
|
ImageHandle,
|
|
SystemTable,
|
|
&gHidKbDriverBinding,
|
|
ImageHandle,
|
|
&gHidKbComponentName,
|
|
&gHidKbComponentName2
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Check whether HID KB driver supports this device.
|
|
|
|
@param This The HID KB driver binding protocol.
|
|
@param Controller The controller handle to check.
|
|
@param RemainingDevicePath The remaining device path.
|
|
|
|
@retval EFI_SUCCESS The driver supports this controller.
|
|
@retval other This device isn't supported.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
HidKbDriverBindingSupported (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EDKII_HID_PROTOCOL *Hid;
|
|
EDKII_HID_INFO HidInfo;
|
|
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEdkiiHidProtocolGuid,
|
|
(VOID **) &Hid,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Use the HID Protocol interface to check whether Controller is
|
|
// a HID KB device that can be managed by this driver.
|
|
//
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
HidInfo.HidType = HidTypeMax;
|
|
#endif
|
|
Status = Hid->GetDeviceInfo (Hid, &HidInfo);
|
|
|
|
gBS->CloseProtocol (
|
|
Controller,
|
|
&gEdkiiHidProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
if (!(HidInfo.HidType & HidTypeKeyBoard)) {
|
|
DEBUG ((EFI_D_ERROR, "HidKbDriverBindingSupported: Not a KB\n"));
|
|
#else
|
|
if (HidInfo.HidType != HidTypeKeyBoard) {
|
|
#endif
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
DEBUG ((EFI_D_ERROR, "HidKbDriverBindingSupported: %r\n", Status));
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Starts the HID KB device with this driver.
|
|
|
|
This function consumes Hid I/O Portocol, intializes HID KB device,
|
|
installs SimpleTextIn Protocol.
|
|
|
|
@param This The HID KB driver binding instance.
|
|
@param Controller Handle of device to bind driver to.
|
|
@param RemainingDevicePath Optional parameter use to pick a specific child
|
|
device to start.
|
|
|
|
@retval EFI_SUCCESS This driver supports this device.
|
|
@retval EFI_UNSUPPORTED This driver does not support this device.
|
|
@retval EFI_DEVICE_ERROR This driver cannot be started due to device Error.
|
|
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
|
|
@retval EFI_ALREADY_STARTED This driver has been started.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
HidKbDriverBindingStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EDKII_HID_PROTOCOL *Hid;
|
|
HID_KB_DEV *HidKbDev;
|
|
EFI_DEVICE_PATH *DevicePath;
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
EDKII_HID_INFO HidInfo;
|
|
#endif
|
|
|
|
|
|
DEBUG ((EFI_D_ERROR, "HidKbDriverBindingStart: Enter\n"));
|
|
|
|
HidKbDev = NULL;
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
HidInfo.HidType = HidTypeKeyBoard;
|
|
#endif
|
|
|
|
//
|
|
// Open Hid I/O Protocol
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEdkiiHidProtocolGuid,
|
|
(VOID **) &Hid,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit1;
|
|
}
|
|
|
|
//
|
|
// Get the Device Path Protocol on Controller's handle
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &DevicePath,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
|
|
HidKbDev = AllocateZeroPool (sizeof (HID_KB_DEV));
|
|
if (HidKbDev == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
HidKbDev->Signature = HID_KB_DEV_SIGNATURE;
|
|
HidKbDev->Hid = Hid;
|
|
CopyMem (&HidKbDev->SimpleTextIn, &mSimpleTextIn, sizeof(mSimpleTextIn));
|
|
CopyMem (&HidKbDev->SimpleTextInEx, &mSimpleTextInEx, sizeof(mSimpleTextInEx));
|
|
HidKbDev->ControllerHandle = Controller;
|
|
|
|
InitializeListHead (&HidKbDev->NotifyList);
|
|
|
|
#ifdef UEFI_COMBO_DEVICE_SUPPORTED
|
|
Status = Hid->Start (Hid, NULL, NULL, KeyboardHandler, HidKbDev, HidInfo);
|
|
#else
|
|
Status = Hid->Start (Hid, NULL, NULL, KeyboardHandler, HidKbDev);
|
|
#endif
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
|
|
Status = gBS->CreateEvent (
|
|
EVT_TIMER | EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
HidKbTimerHandler,
|
|
HidKbDev,
|
|
&HidKbDev->TimerEvent
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = gBS->SetTimer (HidKbDev->TimerEvent, TimerPeriodic, KEYBOARD_TIMER_INTERVAL);
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_WAIT,
|
|
TPL_NOTIFY,
|
|
HidKbWaitForKey,
|
|
HidKbDev,
|
|
&(HidKbDev->SimpleTextInEx.WaitForKeyEx)
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_WAIT,
|
|
TPL_NOTIFY,
|
|
HidKbWaitForKey,
|
|
HidKbDev,
|
|
&(HidKbDev->SimpleTextIn.WaitForKey)
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&Controller,
|
|
&gEfiSimpleTextInProtocolGuid,
|
|
&HidKbDev->SimpleTextIn,
|
|
&gEfiSimpleTextInputExProtocolGuid,
|
|
&HidKbDev->SimpleTextInEx,
|
|
NULL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ErrorExit;
|
|
}
|
|
|
|
Status = InitKeyboardLayout (HidKbDev);
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
Controller,
|
|
&gEfiSimpleTextInProtocolGuid,
|
|
&HidKbDev->SimpleTextIn,
|
|
&gEfiSimpleTextInputExProtocolGuid,
|
|
&HidKbDev->SimpleTextInEx,
|
|
NULL
|
|
);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Reset HID Keyboard Device exhaustively.
|
|
//
|
|
Status = HidKbDev->SimpleTextInEx.Reset (
|
|
&HidKbDev->SimpleTextInEx,
|
|
TRUE
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
Controller,
|
|
&gEfiSimpleTextInProtocolGuid,
|
|
&HidKbDev->SimpleTextIn,
|
|
&gEfiSimpleTextInputExProtocolGuid,
|
|
&HidKbDev->SimpleTextInEx,
|
|
NULL
|
|
);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Open For Child Device
|
|
//
|
|
|
|
HidKbDev->ControllerNameTable = NULL;
|
|
AddUnicodeString2 (
|
|
"eng",
|
|
gHidKbComponentName.SupportedLanguages,
|
|
&HidKbDev->ControllerNameTable,
|
|
L"Generic Hid Keyboard",
|
|
TRUE
|
|
);
|
|
AddUnicodeString2 (
|
|
"en",
|
|
gHidKbComponentName2.SupportedLanguages,
|
|
&HidKbDev->ControllerNameTable,
|
|
L"Generic Hid Keyboard",
|
|
FALSE
|
|
);
|
|
|
|
// gBS->RestoreTPL (OldTpl);
|
|
|
|
DEBUG ((EFI_D_ERROR, "HidKbDriverBindingStart: Exit\n"));
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
//
|
|
// Error handler
|
|
//
|
|
ErrorExit:
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->CloseProtocol (
|
|
Controller,
|
|
&gEdkiiHidProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
|
|
if (HidKbDev != NULL) {
|
|
if (HidKbDev->TimerEvent != NULL) {
|
|
gBS->CloseEvent (HidKbDev->TimerEvent);
|
|
}
|
|
if (HidKbDev->SimpleTextIn.WaitForKey != NULL) {
|
|
gBS->CloseEvent (HidKbDev->SimpleTextIn.WaitForKey);
|
|
}
|
|
if (HidKbDev->SimpleTextInEx.WaitForKeyEx != NULL) {
|
|
gBS->CloseEvent (HidKbDev->SimpleTextInEx.WaitForKeyEx);
|
|
}
|
|
if (HidKbDev->KeyboardLayoutEvent != NULL) {
|
|
ReleaseKeyboardLayoutResources (HidKbDev);
|
|
gBS->CloseEvent (HidKbDev->KeyboardLayoutEvent);
|
|
}
|
|
FreePool (HidKbDev);
|
|
HidKbDev = NULL;
|
|
}
|
|
}
|
|
|
|
ErrorExit1:
|
|
// gBS->RestoreTPL (OldTpl);
|
|
|
|
DEBUG ((EFI_D_ERROR, "HidKbDriverBindingStart: Exit - %r\n", Status));
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Stop the HID KB device handled by this driver.
|
|
|
|
@param This The HID KB driver binding protocol.
|
|
@param Controller The controller to release.
|
|
@param NumberOfChildren The number of handles in ChildHandleBuffer.
|
|
@param ChildHandleBuffer The array of child handle.
|
|
|
|
@retval EFI_SUCCESS The device was stopped.
|
|
@retval EFI_UNSUPPORTED SimpleTextIn Protocol is not installed on Controller.
|
|
@retval Others Fail to uninstall protocols attached on the device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
HidKbDriverBindingStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE Controller,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
HID_KB_DEV *HidKbDev;
|
|
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn;
|
|
|
|
DEBUG ((DEBUG_INFO, "%a: Enter\n", __FUNCTION__));
|
|
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiSimpleTextInProtocolGuid,
|
|
(VOID **) &SimpleTextIn,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiSimpleTextInputExProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
HidKbDev = HID_KB_DEV_FROM_SIMPLE_TEXT_IN_PROTOCOL (SimpleTextIn);
|
|
|
|
Status = gBS->UninstallMultipleProtocolInterfaces (
|
|
Controller,
|
|
&gEfiSimpleTextInProtocolGuid,
|
|
&HidKbDev->SimpleTextIn,
|
|
&gEfiSimpleTextInputExProtocolGuid,
|
|
&HidKbDev->SimpleTextInEx,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
gBS->CloseProtocol (
|
|
Controller,
|
|
&gEdkiiHidProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
//
|
|
// Free all resources.
|
|
//
|
|
gBS->CloseEvent (HidKbDev->TimerEvent);
|
|
gBS->CloseEvent (HidKbDev->RepeatTimer);
|
|
gBS->CloseEvent (HidKbDev->SimpleTextIn.WaitForKey);
|
|
gBS->CloseEvent (HidKbDev->SimpleTextInEx.WaitForKeyEx);
|
|
KbdFreeNotifyList (&HidKbDev->NotifyList);
|
|
|
|
ReleaseKeyboardLayoutResources (HidKbDev);
|
|
gBS->CloseEvent (HidKbDev->KeyboardLayoutEvent);
|
|
|
|
if (HidKbDev->ControllerNameTable != NULL) {
|
|
FreeUnicodeStringTable (HidKbDev->ControllerNameTable);
|
|
}
|
|
|
|
DestroyQueue (&HidKbDev->HidKeyQueue);
|
|
DestroyQueue (&HidKbDev->EfiKeyQueue);
|
|
|
|
FreePool (HidKbDev);
|
|
|
|
DEBUG ((DEBUG_INFO, "%a: Exit\n", __FUNCTION__));
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|