]> git.sesse.net Git - pistorm/commitdiff
Merge pull request #7 from borb/feature/fixes-and-keyb-mouse-autoconnect-and-grab
authorbeeanyew <beeanyew@gmail.com>
Thu, 15 Apr 2021 03:17:03 +0000 (05:17 +0200)
committerGitHub <noreply@github.com>
Thu, 15 Apr 2021 03:17:03 +0000 (05:17 +0200)
Fixes; keyboard and mouse autoconnect and keyboard grab (steal from the Pi).

config_file/config_file.c
config_file/config_file.h
default.cfg
emulator.c
input/input.c
input/input.h

index 2436ffd492cf54fbe1ef3f666096ece63e8d1a24..69ef9f0cbf9c3e9f6a4bf15fcdcb5e7cef738201 100644 (file)
@@ -61,12 +61,12 @@ int get_config_item_type(char *cmd) {
 unsigned int get_m68k_cpu_type(char *name) {
   for (int i = 0; i < M68K_CPU_TYPES; i++) {
     if (strcmp(name, cpu_types[i]) == 0) {
-      printf("Set CPU type to %s.\n", cpu_types[i]);
+      printf("[CFG] Set CPU type to %s.\n", cpu_types[i]);
       return i + 1;
     }
   }
 
-  printf ("Invalid CPU type %s specified, defaulting to 68000.\n", name);
+  printf("[CFG] Invalid CPU type %s specified, defaulting to 68000.\n", name);
   return M68K_CPU_TYPE_68000;
 }
 
@@ -119,7 +119,7 @@ unsigned int get_int(char *str) {
           case 'M': ret_int = ret_int * SIZE_MEGA; break;
           case 'G': ret_int = ret_int * SIZE_GIGA; break;
           default:
-            printf("Unknown character %c in hex value.\n", str[i]);
+            printf("[CFG] Unknown character %c in hex value.\n", str[i]);
             break;
         }
       }
@@ -179,7 +179,7 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
     index++;
   }
   if (index == MAX_NUM_MAPPED_ITEMS) {
-    printf("Unable to map item, only %d items can be mapped with current binary.\n", MAX_NUM_MAPPED_ITEMS);
+    printf("[CFG] Unable to map item, only %d items can be mapped with current binary.\n", MAX_NUM_MAPPED_ITEMS);
     return;
   }
 
@@ -195,10 +195,10 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
 
   switch(type) {
     case MAPTYPE_RAM:
-      printf("Allocating %d bytes for RAM mapping (%d MB)...\n", size, size / 1024 / 1024);
+      printf("[CFG] Allocating %d bytes for RAM mapping (%d MB)...\n", size, size / 1024 / 1024);
       cfg->map_data[index] = (unsigned char *)malloc(size);
       if (!cfg->map_data[index]) {
-        printf("ERROR: Unable to allocate memory for mapped RAM!\n");
+        printf("[CFG] ERROR: Unable to allocate memory for mapped RAM!\n");
         goto mapping_failed;
       }
       memset(cfg->map_data[index], 0x00, size);
@@ -206,7 +206,7 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
     case MAPTYPE_ROM:
       in = fopen(filename, "rb");
       if (!in) {
-        printf("Failed to open file %s for ROM mapping.\n", filename);
+        printf("[CFG] Failed to open file %s for ROM mapping.\n", filename);
         goto mapping_failed;
       }
       fseek(in, 0, SEEK_END);
@@ -219,7 +219,7 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
       cfg->map_data[index] = (unsigned char *)calloc(1, cfg->map_size[index]);
       cfg->rom_size[index] = (cfg->map_size[index] <= file_size) ? cfg->map_size[index] : file_size;
       if (!cfg->map_data[index]) {
-        printf("ERROR: Unable to allocate memory for mapped ROM!\n");
+        printf("[CFG] ERROR: Unable to allocate memory for mapped ROM!\n");
         goto mapping_failed;
       }
       memset(cfg->map_data[index], 0x00, cfg->map_size[index]);
@@ -231,7 +231,7 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
       break;
   }
 
-  printf("[MAP %d] Added %s mapping for range %.8lX-%.8lX ID: %s\n", index, map_type_names[type], cfg->map_offset[index], cfg->map_high[index] - 1, cfg->map_id[index] ? cfg->map_id[index] : "None");
+  printf("[CFG] [MAP %d] Added %s mapping for range %.8lX-%.8lX ID: %s\n", index, map_type_names[type], cfg->map_offset[index], cfg->map_high[index] - 1, cfg->map_id[index] ? cfg->map_id[index] : "None");
   if (cfg->map_size[index] == cfg->rom_size[index])
     m68k_add_rom_range(cfg->map_offset[index], cfg->map_high[index], cfg->map_data[index]);
 
@@ -246,7 +246,7 @@ void add_mapping(struct emulator_config *cfg, unsigned int type, unsigned int ad
 struct emulator_config *load_config_file(char *filename) {
   FILE *in = fopen(filename, "rb");
   if (in == NULL) {
-    printf("Failed to open config file %s for reading.\n", filename);
+    printf("[CFG] Failed to open config file %s for reading.\n", filename);
     return NULL;
   }
 
@@ -257,12 +257,12 @@ struct emulator_config *load_config_file(char *filename) {
 
   parse_line = (char *)calloc(1, 512);
   if (!parse_line) {
-    printf("Failed to allocate memory for config file line buffer.\n");
+    printf("[CFG] Failed to allocate memory for config file line buffer.\n");
     return NULL;
   }
   cfg = (struct emulator_config *)calloc(1, sizeof(struct emulator_config));
   if (!cfg) {
-    printf("Failed to allocate memory for temporary emulator config.\n");
+    printf("[CFG] Failed to allocate memory for temporary emulator config.\n");
     goto load_failed;
   }
 
@@ -332,7 +332,7 @@ struct emulator_config *load_config_file(char *filename) {
               mirraddr = get_int(cur_cmd);
               break;
             default:
-              printf("Unknown/unhandled map argument %s on line %d.\n", cur_cmd, cur_line);
+              printf("[CFG] Unknown/unhandled map argument %s on line %d.\n", cur_cmd, cur_line);
               break;
           }
         }
@@ -342,7 +342,7 @@ struct emulator_config *load_config_file(char *filename) {
       }
       case CONFITEM_LOOPCYCLES:
         cfg->loop_cycles = get_int(parse_line + str_pos);
-        printf("Set CPU loop cycles to %d.\n", cfg->loop_cycles);
+        printf("[CFG] Set CPU loop cycles to %d.\n", cfg->loop_cycles);
         break;
       case CONFITEM_MOUSE:
         get_next_string(parse_line, cur_cmd, &str_pos, ' ');
@@ -350,27 +350,37 @@ struct emulator_config *load_config_file(char *filename) {
         strcpy(cfg->mouse_file, cur_cmd);
         get_next_string(parse_line, cur_cmd, &str_pos, ' ');
         cfg->mouse_toggle_key = cur_cmd[0];
+        get_next_string(parse_line, cur_cmd, &str_pos, ' ');
+        cfg->mouse_autoconnect = (strcmp(cur_cmd, "autoconnect") == 0) ? 1 : 0;
         cfg->mouse_enabled = 1;
-        printf("Enabled mouse event forwarding from file %s, toggle key %c.\n", cfg->mouse_file, cfg->mouse_toggle_key);
+        printf("[CFG] Enabled mouse event forwarding from file %s, toggle key %c.\n", cfg->mouse_file, cfg->mouse_toggle_key);
         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;
+        get_next_string(parse_line, cur_cmd, &str_pos, ' ');
+        cfg->keyboard_autoconnect = (strcmp(cur_cmd, "autoconnect") == 0) ? 1 : 0;
+        printf("[CFG] Enabled keyboard event forwarding, toggle key %c", cfg->keyboard_toggle_key);
+        if (cfg->keyboard_grab)
+          printf(", locking from host when connected");
+        if (cfg->keyboard_autoconnect)
+          printf(", connected to guest at startup");
+        printf(".\n");
         break;
       case CONFITEM_KBFILE:
         get_next_string(parse_line, cur_cmd, &str_pos, ' ');
         cfg->keyboard_file = (char *)calloc(1, strlen(cur_cmd) + 1);
         strcpy(cfg->keyboard_file, cur_cmd);
-        printf("Set keyboard event source file to %s.\n", cfg->keyboard_file);
+        printf("[CFG] Set keyboard event source file to %s.\n", cfg->keyboard_file);
         break;
       case CONFITEM_PLATFORM: {
         char platform_name[128], platform_sub[128];
         memset(platform_name, 0x00, 128);
         memset(platform_sub, 0x00, 128);
         get_next_string(parse_line, platform_name, &str_pos, ' ');
-        printf("Setting platform to %s", platform_name);
+        printf("[CFG] Setting platform to %s", platform_name);
         get_next_string(parse_line, platform_sub, &str_pos, ' ');
         if (strlen(platform_sub))
           printf(" (sub: %s)", platform_sub);
@@ -380,7 +390,7 @@ struct emulator_config *load_config_file(char *filename) {
       }
       case CONFITEM_SETVAR: {
         if (!cfg->platform) {
-          printf("Warning: esetvar used in config file with no platform specified.\n");
+          printf("[CFG] Warning: setvar used in config file with no platform specified.\n");
           break;
         }
 
@@ -395,11 +405,11 @@ struct emulator_config *load_config_file(char *filename) {
       }
       case CONFITEM_NONE:
       default:
-        printf("Unknown config item %s on line %d.\n", cur_cmd, cur_line);
+        printf("[CFG] Unknown config item %s on line %d.\n", cur_cmd, cur_line);
         break;
     }
 
-    skip_line:;
+  skip_line:
     cur_line++;
   }
   goto load_successful;
index b9fe43876fb2a2eb03224e07b0c6b77ce5a64233..54931aece0cb27357bb73105a28defc72ecf2762 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, mouse_autoconnect, keyboard_enabled, keyboard_grab, keyboard_autoconnect;
 
   unsigned int loop_cycles;
   unsigned int mapped_low, mapped_high;
index 0d66addf04b67d83eb854a5be61dc8680f4fddb5..76d49e01156de2fa2f81b3b66615c2507c942a24 100644 (file)
@@ -42,12 +42,18 @@ platform amiga
 # Uncomment this line to enable the (currently non-working) Pi-Net interface.
 #setvar pi-net
 
-# Forward mouse events to host system, defaults to off unless toggle key is pressed on the Pi.
-# 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
+# Syntax: keyboard [grab key] [grab|nograb] [autoconnect|noautoconnect]
+#   "grab" steals the keyboard from the Pi so Amiga/etc. input is not sent to the Pi
+#   (also helps prevent sending any ctrl-alt-del to the Amiga from resetting the Pi)
+#
+#   "autoconnect" connects the keyboard to the Amiga/etc. on startup
+keyboard k nograb noautoconnect
 # 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.
 #kbfile /dev/input/event1
+# Forward mouse events to host system, defaults to off unless toggle key is pressed on the Pi.
+# Syntax is mouse [device] [toggle key] [autoconnect|noautoconnect]
+# (see "keyboard" above for autoconnect description)
+mouse /dev/input/mice m noautoconnect
index 157cb64660d002059202752b61dda5f590bffd27..9c9af66117abeed3ae1d58b1df2075489648626f 100644 (file)
@@ -59,9 +59,10 @@ extern volatile uint16_t srdata;
 extern uint8_t realtime_graphics_debug;
 uint8_t realtime_disassembly, int2_enabled = 0;
 uint32_t do_disasm = 0, old_level;
-char c = 0, c_code = 0, c_type = 0; // @todo temporary main/cpu_task scope workaround until input moved to a thread
 uint32_t last_irq = 8, last_last_irq = 8;
 
+uint8_t end_signal = 0;
+
 char disasm_buf[4096];
 
 #define KICKBASE 0xF80000
@@ -239,7 +240,6 @@ cpu_loop:
 //    printf("CPU emulation reset.\n");
   }
 
-
   if (mouse_hook_enabled && (mouse_extra != 0x00)) {
     // mouse wheel events have occurred; unlike l/m/r buttons, these are queued as keypresses, so add to end of buffer
     switch (mouse_extra) {
@@ -256,46 +256,66 @@ cpu_loop:
     // dampen the scroll wheel until next while loop iteration
     mouse_extra = 0x00;
   }
+
+  if (end_signal)
+         goto stop_cpu_emulation;
+
   goto cpu_loop;
 
-//stop_cpu_emulation:
+stop_cpu_emulation:
   printf("[CPU] End of CPU thread\n");
+  return (void *)NULL;
 }
 
 void *keyboard_task() {
-  struct pollfd kbdfd[1];
-  int kpoll;
+  struct pollfd kbdpoll[1];
+  int kpollrc;
+  char c = 0, c_code = 0, c_type = 0;
+  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);
@@ -328,11 +348,11 @@ key_loop:
         //m68k_pulse_reset();
         printf("CPU emulation reset.\n");
       }
-      // @todo work out how to signal the main process that we want to quit
-      // if (c == 'q') {
-      //   printf("Quitting and exiting emulator.\n");
-      //   goto stop_cpu_emulation;
-      // }
+      if (c == 'q') {
+        printf("Quitting and exiting emulator.\n");
+             end_signal = 1;
+        goto key_end;
+      }
       if (c == 'd') {
         realtime_disassembly ^= 1;
         do_disasm = 1;
@@ -360,6 +380,10 @@ key_loop:
 
 key_end:
   printf("[KBD] Keyboard thread ending\n");
+  if (cfg->keyboard_grab) {
+    printf(ungrab_message);
+    release_device(keyboard_fd);
+  }
   return (void*)NULL;
 }
 
@@ -496,6 +520,12 @@ int main(int argc, char *argv[]) {
     printf("Failed to open keyboard event source.\n");
   }
 
+  if (cfg->mouse_autoconnect)
+    mouse_hook_enabled = 1;
+
+  if (cfg->keyboard_autoconnect)
+    kb_hook_enabled = 1;
+
   InitGayle();
 
   signal(SIGINT, sigint_handler);
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);