NJU-ProjectN/nemu eb63cf3568dbf4e0c3c6ef462e6ec685550fabbc Merge pull request #76 from rijuyuezhu/master
101 lines
3.2 KiB
C
101 lines
3.2 KiB
C
/***************************************************************************************
|
|
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
|
*
|
|
* NEMU is licensed under Mulan PSL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
* You may obtain a copy of Mulan PSL v2 at:
|
|
* http://license.coscl.org.cn/MulanPSL2
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* See the Mulan PSL v2 for more details.
|
|
***************************************************************************************/
|
|
|
|
#include <device/map.h>
|
|
#include <utils.h>
|
|
|
|
#define KEYDOWN_MASK 0x8000
|
|
|
|
#ifndef CONFIG_TARGET_AM
|
|
#include <SDL2/SDL.h>
|
|
|
|
// Note that this is not the standard
|
|
#define NEMU_KEYS(f) \
|
|
f(ESCAPE) f(F1) f(F2) f(F3) f(F4) f(F5) f(F6) f(F7) f(F8) f(F9) f(F10) f(F11) f(F12) \
|
|
f(GRAVE) f(1) f(2) f(3) f(4) f(5) f(6) f(7) f(8) f(9) f(0) f(MINUS) f(EQUALS) f(BACKSPACE) \
|
|
f(TAB) f(Q) f(W) f(E) f(R) f(T) f(Y) f(U) f(I) f(O) f(P) f(LEFTBRACKET) f(RIGHTBRACKET) f(BACKSLASH) \
|
|
f(CAPSLOCK) f(A) f(S) f(D) f(F) f(G) f(H) f(J) f(K) f(L) f(SEMICOLON) f(APOSTROPHE) f(RETURN) \
|
|
f(LSHIFT) f(Z) f(X) f(C) f(V) f(B) f(N) f(M) f(COMMA) f(PERIOD) f(SLASH) f(RSHIFT) \
|
|
f(LCTRL) f(APPLICATION) f(LALT) f(SPACE) f(RALT) f(RCTRL) \
|
|
f(UP) f(DOWN) f(LEFT) f(RIGHT) f(INSERT) f(DELETE) f(HOME) f(END) f(PAGEUP) f(PAGEDOWN)
|
|
|
|
#define NEMU_KEY_NAME(k) NEMU_KEY_ ## k,
|
|
|
|
enum {
|
|
NEMU_KEY_NONE = 0,
|
|
MAP(NEMU_KEYS, NEMU_KEY_NAME)
|
|
};
|
|
|
|
#define SDL_KEYMAP(k) keymap[SDL_SCANCODE_ ## k] = NEMU_KEY_ ## k;
|
|
static uint32_t keymap[256] = {};
|
|
|
|
static void init_keymap() {
|
|
MAP(NEMU_KEYS, SDL_KEYMAP)
|
|
}
|
|
|
|
#define KEY_QUEUE_LEN 1024
|
|
static int key_queue[KEY_QUEUE_LEN] = {};
|
|
static int key_f = 0, key_r = 0;
|
|
|
|
static void key_enqueue(uint32_t am_scancode) {
|
|
key_queue[key_r] = am_scancode;
|
|
key_r = (key_r + 1) % KEY_QUEUE_LEN;
|
|
Assert(key_r != key_f, "key queue overflow!");
|
|
}
|
|
|
|
static uint32_t key_dequeue() {
|
|
uint32_t key = NEMU_KEY_NONE;
|
|
if (key_f != key_r) {
|
|
key = key_queue[key_f];
|
|
key_f = (key_f + 1) % KEY_QUEUE_LEN;
|
|
}
|
|
return key;
|
|
}
|
|
|
|
void send_key(uint8_t scancode, bool is_keydown) {
|
|
if (nemu_state.state == NEMU_RUNNING && keymap[scancode] != NEMU_KEY_NONE) {
|
|
uint32_t am_scancode = keymap[scancode] | (is_keydown ? KEYDOWN_MASK : 0);
|
|
key_enqueue(am_scancode);
|
|
}
|
|
}
|
|
#else // !CONFIG_TARGET_AM
|
|
#define NEMU_KEY_NONE 0
|
|
|
|
static uint32_t key_dequeue() {
|
|
AM_INPUT_KEYBRD_T ev = io_read(AM_INPUT_KEYBRD);
|
|
uint32_t am_scancode = ev.keycode | (ev.keydown ? KEYDOWN_MASK : 0);
|
|
return am_scancode;
|
|
}
|
|
#endif
|
|
|
|
static uint32_t *i8042_data_port_base = NULL;
|
|
|
|
static void i8042_data_io_handler(uint32_t offset, int len, bool is_write) {
|
|
assert(!is_write);
|
|
assert(offset == 0);
|
|
i8042_data_port_base[0] = key_dequeue();
|
|
}
|
|
|
|
void init_i8042() {
|
|
i8042_data_port_base = (uint32_t *)new_space(4);
|
|
i8042_data_port_base[0] = NEMU_KEY_NONE;
|
|
#ifdef CONFIG_HAS_PORT_IO
|
|
add_pio_map ("keyboard", CONFIG_I8042_DATA_PORT, i8042_data_port_base, 4, i8042_data_io_handler);
|
|
#else
|
|
add_mmio_map("keyboard", CONFIG_I8042_DATA_MMIO, i8042_data_port_base, 4, i8042_data_io_handler);
|
|
#endif
|
|
IFNDEF(CONFIG_TARGET_AM, init_keymap());
|
|
}
|