UEFI的鼠标事件

UEFI的鼠标事件

        鼠标属于Pointer设备,UEFI的SPEC中使用Pointer设备的Protocols为Simple Pointer Protocol和Absolute Pointer Protocol,本文使用Simple Pointer Protocol来实现UEFI鼠标事件,并打印鼠标的状态(XYZ轴位置、left键、中轴键)。

        步骤如下:

        1:使用LocateProtocol找出Protocol的第一个实例。

        2:打开鼠标指针协议(参考 EFI_SIMPLE_POINTER_PROTOCOL)

        3:无线循环监听鼠标事件,在循环中使用gBS->WaitEvent等待事件,然后获取鼠标的状态(参考 EFI_SIMPLE_POINTER_PROTOCOL),如果获取到之后打印鼠标的状态。

            对应的Protocol如下图1所示:

图1 Protocol

        本文在EmulatorPkg/Application/Foundation3/下创建Foundation3.c和Foundation3.inf文件。其中Foundation3.c如下所示。注意!!!!(RightButton不是右键而是中间的键)。

#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/SimplePointer.h>

EFI_STATUS
EFIAPI
UefiMain(
  IN EFI_HANDLE ImageHandle,
  IN EFI_SYSTEM_TABLE *SystemTable)
{
    EFI_STATUS Status;
    EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol;

    //找到对应的Protocol实例
    Status = gBS->LocateProtocol(&gEfiSimplePointerProtocolGuid, NULL, (VOID **)&SimplePointerProtocol);

    if (EFI_ERROR(Status))
    {
        Print(L"无法定位鼠标协议!\n");
        return Status;
    }

    // 打开鼠标指针协议,验证是否可以用
    Status = SimplePointerProtocol->Reset(SimplePointerProtocol, FALSE);
    if (EFI_ERROR(Status))
    {
        Print(L"鼠标初始化失败!\n");
        return Status;
    }

    // 无限循环监听鼠标事件
    while (TRUE)
    {
        EFI_EVENT WaitEvent = SimplePointerProtocol->WaitForInput;
        UINTN EventIndex;
        gBS->WaitForEvent(1, &WaitEvent, &EventIndex);

        // 获取鼠标状态
        EFI_SIMPLE_POINTER_STATE State;
        Status = SimplePointerProtocol->GetState(SimplePointerProtocol, &State);
        if (EFI_ERROR(Status))
        {
            Print(L"无法获取鼠标状态!\n");
            continue;
        }
        // 打印鼠标状态,经过实验。RightButton不是右键而是中间的键
        Print(L"X:%d Y:%d Z:%d L:%d R:%d\n",
              State.RelativeMovementX,
              State.RelativeMovementY,
              State.RelativeMovementZ,
              State.LeftButton,
              State.RightButton);
    }

    return EFI_SUCCESS;
}

        根据上述步骤,先使用gBS->LocateProtocol,LocateProtocol参考图2,第一个参数为带查询的Protocol,第二个参数为是可选的此处填NULL,第三个参数为对应的Protocol实例,先EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol,由于是VOID**类型的指针,所以要加&后强制类型转换,因此最终为Status = gBS>LocateProtocol(&gEfiSimplePointerProtocolGuid, NULL, (VOID **)&SimplePointerProtocol);

图2 LocateProtocol

        上面找到第一个Protocol实例之后,打开Protocol,使用内部的Reset方法先重置一下,并且判断是否可用,即Status = SimplePointerProtocol->Reset(SimplePointerProtocol, FALSE)。

        重置完之后,在循环中不断的获取鼠标的状态,因此先在循环里创建一个鼠标事件,即鼠标等待事件EFI_EVENT WaitEvent = SimplePointerProtocol->WaitForInput,然后使用gBS->WaitForEvent(1, &WaitEvent, &EventIndex);等待事件的发生,如果检测到有设备输入的时候,使用Status = SimplePointerProtocol->GetState(SimplePointerProtocol, &State)获取鼠标的状态,其中GetState函数的定义如下图3所示,GetState的State的定义又如下图4所示。

图3 GetState函数定义

图4 State

之后将状态打印出来。

        相关的工程文件如下所示。

[Defines]
  INF_VERSION                    = 0x0001000b
  BASE_NAME                      = MyProject
  FILE_GUID                      = 01234567-89AB-CDEF-0123-456789ABCDEF
  MODULE_TYPE                    = UEFI_APPLICATION
  VERSION_STRING                 = 1.0
  ENTRY_POINT                    = UefiMain

[Sources]
  Foundation3.c
:
[Packages]
  MdePkg/MdePkg.dec

[LibraryClasses]
  UefiApplicationEntryPoint
  UefiLib
  UefiBootServicesTableLib
  PrintLib

[Protocols]
  gEfiSimplePointerProtocolGuid

编译运行之后运行结果如下图5所示。

图5 运行结果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值