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);