boot: Handle shift and logo keys too
Some firmware supports sending input events for shift and logo keys. Previously, we would suppress these with EFI_NOT_READY unless some other key was pressed alongside, but it is really the job of the caller to decide how to handle these. Note that for keys that already have a printable shift representation the reported input event will not have the shift key bits set (Shift+a is reported as A). Should some firmware turn out to violate the spec here we can always remove that part.
This commit is contained in:
+10
-12
@@ -124,29 +124,27 @@ EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec) {
|
||||
* The two may be out of sync on some firmware, giving us double input. */
|
||||
if (conInEx) {
|
||||
EFI_KEY_DATA keydata;
|
||||
UINT64 keypress;
|
||||
UINT32 shift = 0;
|
||||
|
||||
err = conInEx->ReadKeyStrokeEx(conInEx, &keydata);
|
||||
if (EFI_ERROR(err))
|
||||
return err;
|
||||
|
||||
/* do not distinguish between left and right keys */
|
||||
if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
|
||||
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED))
|
||||
if (FLAGS_SET(keydata.KeyState.KeyShiftState, EFI_SHIFT_STATE_VALID)) {
|
||||
/* Do not distinguish between left and right keys (set both flags). */
|
||||
if (keydata.KeyState.KeyShiftState & EFI_SHIFT_PRESSED)
|
||||
shift |= EFI_SHIFT_PRESSED;
|
||||
if (keydata.KeyState.KeyShiftState & EFI_CONTROL_PRESSED)
|
||||
shift |= EFI_CONTROL_PRESSED;
|
||||
if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED))
|
||||
if (keydata.KeyState.KeyShiftState & EFI_ALT_PRESSED)
|
||||
shift |= EFI_ALT_PRESSED;
|
||||
if (keydata.KeyState.KeyShiftState & EFI_LOGO_PRESSED)
|
||||
shift |= EFI_LOGO_PRESSED;
|
||||
}
|
||||
|
||||
/* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
|
||||
keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
|
||||
if (keypress > 0) {
|
||||
*key = keypress;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
return EFI_NOT_READY;
|
||||
*key = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
|
||||
return EFI_SUCCESS;
|
||||
} else if (!EFI_ERROR(BS->CheckEvent(ST->ConIn->WaitForKey))) {
|
||||
EFI_INPUT_KEY k;
|
||||
|
||||
|
||||
@@ -3,10 +3,15 @@
|
||||
|
||||
#include "missing_efi.h"
|
||||
|
||||
#define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED)
|
||||
#define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED)
|
||||
enum {
|
||||
EFI_SHIFT_PRESSED = EFI_RIGHT_SHIFT_PRESSED|EFI_LEFT_SHIFT_PRESSED,
|
||||
EFI_CONTROL_PRESSED = EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED,
|
||||
EFI_ALT_PRESSED = EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED,
|
||||
EFI_LOGO_PRESSED = EFI_RIGHT_LOGO_PRESSED|EFI_LEFT_LOGO_PRESSED,
|
||||
};
|
||||
|
||||
#define KEYPRESS(keys, scan, uni) ((((UINT64)keys) << 32) | (((UINT64)scan) << 16) | (uni))
|
||||
#define KEYCHAR(k) ((k) & 0xffff)
|
||||
#define KEYCHAR(k) ((CHAR16)(k))
|
||||
#define CHAR_CTRL(c) ((c) - 'a' + 1)
|
||||
|
||||
enum {
|
||||
|
||||
@@ -13,10 +13,14 @@
|
||||
#define SimpleTextInputExProtocol ((EFI_GUID)EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID)
|
||||
|
||||
#define EFI_SHIFT_STATE_VALID 0x80000000
|
||||
#define EFI_RIGHT_SHIFT_PRESSED 0x00000001
|
||||
#define EFI_LEFT_SHIFT_PRESSED 0x00000002
|
||||
#define EFI_RIGHT_CONTROL_PRESSED 0x00000004
|
||||
#define EFI_LEFT_CONTROL_PRESSED 0x00000008
|
||||
#define EFI_RIGHT_ALT_PRESSED 0x00000010
|
||||
#define EFI_LEFT_ALT_PRESSED 0x00000020
|
||||
#define EFI_RIGHT_LOGO_PRESSED 0x00000040
|
||||
#define EFI_LEFT_LOGO_PRESSED 0x00000080
|
||||
|
||||
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user