UEFI开发学习5 – 获取键盘输入
简述
UEFI中提供了两个Protocol可用于获取键盘输入,分别是EFI_SIMPLE_TEXT_INPUT_PROTOCOL和EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL,后者功能更加强大,但使用方法都差不多,这里说的是后者。
定义
typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL{ EFI_INPUT_RESET_EX Reset; EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx; EFI_EVENT WaitForKeyEx; EFI_SET_STATE SetState; EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify; EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify; } EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
参数:
Reset | 用于复位输入设备 |
ReadKeyStrokeEx | 读取输入的字符,每次只能读取一个 |
WaitForKeyEx | 需要配合WaitForEvent() 函数使用,用于等待字符的输入 |
SetState | 设置按键的切换状态,如是否启用NumLock、CapsLock等 |
RegisterKeyNotify | 注册按键通知事件 |
UnregisterKeyNotify | 取消注册按键通知事件 |
实例
1.获取从键盘输入的字符串
#include <Library/UefiLib.h> #include <Library/UefiBootServicesTableLib.h> #include <Library/UefiRuntimeServicesTableLib.h> #define UNICODE_CHAR_ENTER 0x0D int main( IN int Argc, IN char **Argv ) { EFI_STATUS Status; UINTN EventIndex; EFI_KEY_DATA Key; EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *InputEx; CHAR16 StrBuf[100] = {0}; UINTN StrLen = 0; Status = gBS->LocateProtocol(&gEfiSimpleTextInputExProtocolGuid , NULL, (VOID **) &InputEx); if (EFI_ERROR(Status)) { Print(L"Unsupported.\n\r"); return EFI_UNSUPPORTED; } while(1) { /* Wait for enter a char */ Status = gBS->WaitForEvent(1, &InputEx->WaitForKeyEx, &EventIndex); if (EFI_ERROR(Status)){ Print(L"Unsupported.\n\r"); return EFI_UNSUPPORTED; } /* Read a char */ Status = InputEx->ReadKeyStrokeEx(InputEx, &Key); if (EFI_ERROR(Status)) { Print(L"Unsupported.\n\r"); return EFI_UNSUPPORTED; } /* End loop when read a 'enter' */ if(Key.Key.UnicodeChar == UNICODE_CHAR_ENTER) { Print(L"\n\r"); break; } /* Store char */ StrBuf[StrLen++] = Key.Key.UnicodeChar; /* Show input */ Print(L"%c", Key.Key.UnicodeChar); } /* Print the string input */ Print(L"Input string: %s\n\r", StrBuf); }
运行结果:
NOTE:这段程序会获取所有的键盘输入,包括方向键等,实际应用还需要做一些判断,排除些字符。
2.注册一个按键输入
#include <Library/UefiLib.h> #include <Library/UefiBootServicesTableLib.h> #include <Library/UefiRuntimeServicesTableLib.h> #define SCANCODE_DELETE 0x08 BOOLEAN IsEnterNotify = FALSE; EFI_STATUS EFIAPI KeyNotifyFunction(IN EFI_KEY_DATA *KeyData) { Print(L"Welcome to come to key notify function.\n\r"); IsEnterNotify = TRUE; return EFI_SUCCESS; } int main( IN int Argc, IN char **Argv ) { EFI_STATUS Status; EFI_KEY_DATA Key; EFI_HANDLE NotifyHandle; EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *InputEx; UINTN s; Status = gBS->LocateProtocol(&gEfiSimpleTextInputExProtocolGuid , NULL, (VOID **) &InputEx); if (EFI_ERROR(Status)) { Print(L"Unsupported.\n\r"); return EFI_UNSUPPORTED; } Key.KeyState.KeyToggleState = 0; Key.Key.ScanCode = 0; Key.KeyState.KeyShiftState = 0; Key.Key.ScanCode = SCANCODE_DELETE; Status = InputEx->RegisterKeyNotify(InputEx, &Key, KeyNotifyFunction, &NotifyHandle); for (s = 0; s < 5; s++) { gBS->Stall(1000 * 1000); if (IsEnterNotify) break; Print(L"Press [Delete] to enter notify function %d\n\r", 5 - s); } Status = InputEx->UnregisterKeyNotify(InputEx, NotifyHandle); Print(L"Program Exit\n\r"); }
运行结果:
punster
ayun@punster
lu90
Ay123@lu90