From 5fa4ab5cf46215514feabdeb6133b15ef8b6906a Mon Sep 17 00:00:00 2001 From: just nine Date: Wed, 14 Apr 2021 22:29:41 +0100 Subject: [PATCH] support stealing the keyboard from the input layer this change uses an ioctl to disconnect the keyboard event device from the input layer, meaning input no longer affects the pi and will entirely be consumed by the pistorm emulator process. --- config_file/config_file.c | 6 ++++-- config_file/config_file.h | 2 +- default.cfg | 4 +++- emulator.c | 42 ++++++++++++++++++++++++++------------- input/input.c | 13 ++++++++++++ input/input.h | 2 ++ 6 files changed, 51 insertions(+), 18 deletions(-) diff --git a/config_file/config_file.c b/config_file/config_file.c index 2436ffd..0a1821b 100644 --- a/config_file/config_file.c +++ b/config_file/config_file.c @@ -355,9 +355,11 @@ struct emulator_config *load_config_file(char *filename) { break; case CONFITEM_KEYBOARD: get_next_string(parse_line, cur_cmd, &str_pos, ' '); - cfg->keyboard_file = (char *)calloc(1, strlen(cur_cmd) + 1); cfg->keyboard_toggle_key = cur_cmd[0]; - printf("Enabled keyboard event forwarding, toggle key %c.\n", cfg->keyboard_toggle_key); + get_next_string(parse_line, cur_cmd, &str_pos, ' '); + cfg->keyboard_grab = (strcmp(cur_cmd, "grab") == 0) ? 1 : 0; + printf("Enabled keyboard event forwarding, toggle key %c, %slocking from host.\n", + cfg->keyboard_toggle_key, cfg->keyboard_grab ? "" : "not "); break; case CONFITEM_KBFILE: get_next_string(parse_line, cur_cmd, &str_pos, ' '); diff --git a/config_file/config_file.h b/config_file/config_file.h index b9fe438..3af4758 100644 --- a/config_file/config_file.h +++ b/config_file/config_file.h @@ -68,7 +68,7 @@ struct emulator_config { char *mouse_file, *keyboard_file; char mouse_toggle_key, keyboard_toggle_key; - unsigned char mouse_enabled, keyboard_enabled; + unsigned char mouse_enabled, keyboard_enabled, keyboard_grab; unsigned int loop_cycles; unsigned int mapped_low, mapped_high; diff --git a/default.cfg b/default.cfg index 0d66add..bec305a 100644 --- a/default.cfg +++ b/default.cfg @@ -46,7 +46,9 @@ platform amiga # Syntax is mouse [device] [toggle key] #mouse /dev/input/mouse0 m # Forward keyboard events to host system, defaults to off unless toggle key is pressed, toggled off using F12. -#keyboard k +# Add the keyword "grab" to steal the keyboard from the Pi, so Amiga input does not appear on the console or in X11. +# (also helps prevent sending any ctrl-alt-del to the Amiga from resetting the Pi) +keyboard k grab # Select a specific filename for the keyboard event source. # This is typically /dev/input/event1 or event0, but it may be event3 with for instance a wireless keyboard. # Use ls /dev/input/event* to check which event files are available and try until you find the one that works. diff --git a/emulator.c b/emulator.c index 157cb64..ba4dcf1 100644 --- a/emulator.c +++ b/emulator.c @@ -263,39 +263,53 @@ cpu_loop: } void *keyboard_task() { - struct pollfd kbdfd[1]; - int kpoll; + struct pollfd kbdpoll[1]; + int kpollrc; + char grab_message[] = "[KBD] Grabbing keyboard from input layer\n", + ungrab_message[] = "[KBD] Ungrabbing keyboard\n"; printf("[KBD] Keyboard thread started\n"); - kbdfd[0].fd = keyboard_fd; - kbdfd[0].events = POLLIN; + // because we permit the keyboard to be grabbed on startup, quickly check if we need to grab it + if (kb_hook_enabled && cfg->keyboard_grab) { + printf(grab_message); + grab_device(keyboard_fd); + } + + kbdpoll[0].fd = keyboard_fd; + kbdpoll[0].events = POLLIN; key_loop: - kpoll = poll(kbdfd, 1, KEY_POLL_INTERVAL_MSEC); - if ((kpoll > 0) && (kbdfd[0].revents & POLLHUP)) { + kpollrc = poll(kbdpoll, 1, KEY_POLL_INTERVAL_MSEC); + if ((kpollrc > 0) && (kbdpoll[0].revents & POLLHUP)) { // in the event that a keyboard is unplugged, keyboard_task will whiz up to 100% utilisation // this is undesired, so if the keyboard HUPs, end the thread without ending the emulation printf("[KBD] Keyboard node returned HUP (unplugged?)\n"); goto key_end; } - // if kpoll > 0 then it contains number of events to pull, also check if POLLIN is set in revents - if ((kpoll <= 0) || !(kbdfd[0].revents & POLLIN)) { + // if kpollrc > 0 then it contains number of events to pull, also check if POLLIN is set in revents + if ((kpollrc <= 0) || !(kbdpoll[0].revents & POLLIN)) { goto key_loop; } while (get_key_char(&c, &c_code, &c_type)) { if (c && c == cfg->keyboard_toggle_key && !kb_hook_enabled) { kb_hook_enabled = 1; - printf("Keyboard hook enabled.\n"); - } - else if (kb_hook_enabled) { + printf("[KBD] Keyboard hook enabled.\n"); + if (cfg->keyboard_grab) { + grab_device(keyboard_fd); + printf(grab_message); + } + } else if (kb_hook_enabled) { if (c == 0x1B && c_type) { kb_hook_enabled = 0; - printf("Keyboard hook disabled.\n"); - } - else { + printf("[KBD] Keyboard hook disabled.\n"); + if (cfg->keyboard_grab) { + release_device(keyboard_fd); + printf(ungrab_message); + } + } else { if (queue_keypress(c_code, c_type, cfg->platform->id) && int2_enabled && last_irq != 2) { //last_irq = 0; //M68K_SET_IRQ(2); diff --git a/input/input.c b/input/input.c index bc59607..c9201f9 100644 --- a/input/input.c +++ b/input/input.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -211,3 +212,15 @@ void pop_queued_key(uint8_t *c, uint8_t *t) { queued_keypresses--; return; } + +int grab_device(int fd) { + int rc = 0; + rc = ioctl(fd, EVIOCGRAB, (void *)1); + return rc; +} + +int release_device(int fd) { + int rc = 0; + rc = ioctl(fd, EVIOCGRAB, (void *)0); + return rc; +} diff --git a/input/input.h b/input/input.h index a785534..87384e7 100644 --- a/input/input.h +++ b/input/input.h @@ -11,3 +11,5 @@ int get_key_char(char *c, char *code, char *event_type); int queue_keypress(uint8_t keycode, uint8_t event_type, uint8_t platform); int get_num_kb_queued(); void pop_queued_key(uint8_t *c, uint8_t *t); +int grab_device(int fd); +int release_device(int fd); -- 2.39.2