2021-11-26 07:18:08 +03:00
|
|
|
/**
|
|
|
|
* @brief Keyboard reading functions.
|
|
|
|
*
|
|
|
|
* Abstracts away the differences between our EFI and BIOS
|
|
|
|
* environments to provide consistent scancode feedback for
|
|
|
|
* the menus and command line editor.
|
|
|
|
*
|
|
|
|
* For EFI, we use the WaitForKey and ReadKeyStroke interfaces.
|
|
|
|
*
|
|
|
|
* For BIOS, we have a bad PS/2 driver, which should be fine if
|
|
|
|
* you're booting with BIOS?
|
|
|
|
*
|
|
|
|
* @copyright
|
|
|
|
* This file is part of ToaruOS and is released under the terms
|
|
|
|
* of the NCSA / University of Illinois License - see LICENSE.md
|
|
|
|
* Copyright (C) 2021 K. Lange
|
|
|
|
*/
|
2021-06-14 05:11:37 +03:00
|
|
|
#include "kbd.h"
|
|
|
|
#include "util.h"
|
2021-09-07 05:45:58 +03:00
|
|
|
#include "text.h"
|
|
|
|
|
|
|
|
#ifdef EFI_PLATFORM
|
|
|
|
#include <efi.h>
|
|
|
|
extern EFI_SYSTEM_TABLE *ST;
|
|
|
|
|
|
|
|
#define KBD_SCAN_DOWN 0x50
|
|
|
|
#define KBD_SCAN_UP 0x48
|
|
|
|
#define KBD_SCAN_LEFT 0x4B
|
|
|
|
#define KBD_SCAN_RIGHT 0x4D
|
|
|
|
#define KBD_SCAN_ENTER 0x1C
|
|
|
|
#define KBD_SCAN_1 2
|
|
|
|
#define KBD_SCAN_9 10
|
|
|
|
|
|
|
|
int read_scancode(int timeout) {
|
|
|
|
EFI_INPUT_KEY Key;
|
|
|
|
unsigned long int index;
|
|
|
|
if (timeout) {
|
|
|
|
EFI_EVENT events[] = {ST->ConIn->WaitForKey, 0};
|
|
|
|
uefi_call_wrapper(ST->BootServices->CreateEvent, 5, EVT_TIMER, 0, NULL, NULL, &events[1]);
|
|
|
|
uefi_call_wrapper(ST->BootServices->SetTimer, 3, events[1], TimerRelative, 10000000UL);
|
|
|
|
uefi_call_wrapper(ST->BootServices->WaitForEvent, 3, 2, events, &index);
|
|
|
|
} else {
|
|
|
|
uefi_call_wrapper(ST->BootServices->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
|
|
|
|
}
|
|
|
|
EFI_STATUS result = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &Key);
|
|
|
|
|
|
|
|
if (result == EFI_NOT_READY) return -1;
|
|
|
|
switch (Key.ScanCode) {
|
|
|
|
case 0:
|
|
|
|
switch (Key.UnicodeChar) {
|
|
|
|
case L'\r':
|
|
|
|
return KBD_SCAN_ENTER;
|
|
|
|
case L'1':
|
|
|
|
case L'2':
|
|
|
|
case L'3':
|
|
|
|
case L'4':
|
|
|
|
case L'5':
|
|
|
|
case L'6':
|
|
|
|
case L'7':
|
|
|
|
case L'8':
|
|
|
|
case L'9':
|
|
|
|
return Key.UnicodeChar - L'1' + KBD_SCAN_1;
|
|
|
|
case L'e':
|
|
|
|
return 0x12;
|
|
|
|
default:
|
|
|
|
return 0xFF;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x01: return KBD_SCAN_UP;
|
|
|
|
case 0x02: return KBD_SCAN_DOWN;
|
|
|
|
case 0x03: return KBD_SCAN_RIGHT;
|
|
|
|
case 0x04: return KBD_SCAN_LEFT;
|
|
|
|
default:
|
|
|
|
return 0xFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-04 12:59:35 +03:00
|
|
|
int read_key(int * c) {
|
2021-09-07 05:45:58 +03:00
|
|
|
EFI_INPUT_KEY Key;
|
|
|
|
unsigned long int index;
|
|
|
|
uefi_call_wrapper(ST->BootServices->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
|
|
|
|
uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &Key);
|
|
|
|
|
|
|
|
if (Key.ScanCode == 0) {
|
|
|
|
*c = Key.UnicodeChar;
|
|
|
|
if (*c == '\r') *c = '\n';
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (Key.ScanCode) {
|
|
|
|
case 0x03: return 3;
|
|
|
|
case 0x04: return 2;
|
|
|
|
case 0x09: return 4;
|
|
|
|
case 0x0a: return 5;
|
|
|
|
case 0x17: *c = 27; return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
2021-06-14 05:11:37 +03:00
|
|
|
|
2021-07-08 07:51:03 +03:00
|
|
|
int read_cmos_seconds(void) {
|
|
|
|
outportb(0x70,0);
|
|
|
|
return inportb(0x71);
|
|
|
|
}
|
|
|
|
|
2021-08-21 01:55:48 +03:00
|
|
|
static char kbd_us[128] = {
|
|
|
|
0, 27, '1','2','3','4','5','6','7','8','9','0',
|
|
|
|
'-','=','\b', '\t', 'q','w','e','r','t','y','u','i','o','p','[',']','\n',
|
|
|
|
0, 'a','s','d','f','g','h','j','k','l',';','\'', '`',
|
|
|
|
0, '\\','z','x','c','v','b','n','m',',','.','/',
|
|
|
|
0, '*', 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
'-', 0, 0, 0, '+', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
static char kbd_us_l2[128] = {
|
|
|
|
0, 27, '!','@','#','$','%','^','&','*','(',')',
|
|
|
|
'_','+','\b', '\t', 'Q','W','E','R','T','Y','U','I','O','P','{','}','\n',
|
|
|
|
0, 'A','S','D','F','G','H','J','K','L',':','"', '~',
|
|
|
|
0, '|','Z','X','C','V','B','N','M','<','>','?',
|
2021-08-21 09:12:04 +03:00
|
|
|
0, '*', 0, '\037', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
2021-08-21 01:55:48 +03:00
|
|
|
'-', 0, 0, 0, '+', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
};
|
|
|
|
|
2021-11-04 12:59:35 +03:00
|
|
|
int read_key(int * c) {
|
2021-08-21 01:55:48 +03:00
|
|
|
static int shift_state = 0;
|
|
|
|
|
|
|
|
int sc = read_scancode(0);
|
|
|
|
|
2021-11-04 12:59:35 +03:00
|
|
|
if (sc == 0xe0) {
|
|
|
|
*c = 0xe0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*c == 0xe0) {
|
|
|
|
*c = 0;
|
|
|
|
switch (sc) {
|
|
|
|
/* Keft left and right */
|
|
|
|
case 0x4B:
|
|
|
|
return shift_state ? 4 : 2;
|
|
|
|
case 0x4D:
|
|
|
|
return shift_state ? 5 : 3;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-08-21 01:55:48 +03:00
|
|
|
switch (sc) {
|
|
|
|
/* Shift down */
|
|
|
|
case 0x2A:
|
|
|
|
case 0x36:
|
|
|
|
shift_state = 1;
|
|
|
|
return 1;
|
|
|
|
/* Shift up */
|
|
|
|
case 0xAA:
|
|
|
|
case 0xB6:
|
|
|
|
shift_state = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(sc & 0x80)) {
|
|
|
|
*c = shift_state ? kbd_us_l2[sc] : kbd_us[sc];
|
|
|
|
return *c == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-07-08 07:51:03 +03:00
|
|
|
int read_scancode(int timeout) {
|
|
|
|
if (timeout) {
|
|
|
|
int start_s = read_cmos_seconds();
|
|
|
|
while (!(inportb(0x64) & 1)) {
|
|
|
|
int now_s = read_cmos_seconds();
|
|
|
|
if (now_s != start_s) return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while (!(inportb(0x64) & 1));
|
|
|
|
}
|
2021-11-04 12:59:35 +03:00
|
|
|
return inportb(0x60);
|
2021-06-14 05:11:37 +03:00
|
|
|
}
|
2021-09-07 05:45:58 +03:00
|
|
|
#endif
|