]> git.sesse.net Git - pistorm/commitdiff
support stealing the keyboard from the input layer
authorjust nine <nine@aphlor.org>
Wed, 14 Apr 2021 21:29:41 +0000 (22:29 +0100)
committerjust nine <nine@aphlor.org>
Wed, 14 Apr 2021 21:29:41 +0000 (22:29 +0100)
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
config_file/config_file.h
default.cfg
emulator.c
input/input.c
input/input.h

index 2436ffd492cf54fbe1ef3f666096ece63e8d1a24..0a1821b1735e4b989dc73ed0bd5b4adba679e11a 100644 (file)
@@ -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, ' ');
index b9fe43876fb2a2eb03224e07b0c6b77ce5a64233..3af4758bc477b5369a79dbd57c150e7cef98bc8b 100644 (file)
@@ -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;
index 0d66addf04b67d83eb854a5be61dc8680f4fddb5..bec305a265203459b119ca04d30ceddd02dc1912 100644 (file)
@@ -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.
index 157cb64660d002059202752b61dda5f590bffd27..ba4dcf1caf68f809bfa219fa2970e6f42163c7f2 100644 (file)
@@ -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);
index bc596073676bfb6060d1b25266b13ec9ba4334aa..c9201f98540b936d0dd46573ce75716c4358b71e 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/input.h>
+#include <sys/ioctl.h>
 #include <pthread.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -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;
+}
index a7855342cb6a6c5eb78f2e9d12263a749dddc294..87384e726bc5daf797125162199021edc59ef963 100644 (file)
@@ -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);