From e484d703f728afeb7fd960bebf03efd6bb0c7775 Mon Sep 17 00:00:00 2001 From: That One Seong Date: Wed, 5 Feb 2025 13:07:13 +0000 Subject: [PATCH] input: Add support for OpenFIRE lightguns (#964) * Add OpenFIRE lightguns to guns whitelist * Add preliminary OpenFIRE support Guns are detected as light guns based on static VID and OpenFIRE name prefix, as the PID can be any number of different values depending on the user. Because OpenFIRE guns can be polled through serial devices, a basic (read: hacky) heuristic is used to poll for serial port paths and send a signal to compatible guns to enable their MiSTer compatible mode. * Tabbbbbs * Directly open and write to file rather than rely on system echo --- input.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 67 insertions(+), 11 deletions(-) diff --git a/input.cpp b/input.cpp index d8fcbb3..3778e11 100644 --- a/input.cpp +++ b/input.cpp @@ -4191,6 +4191,43 @@ static int vcs_proc(int dev, input_event *ev) return 1; } +void openfire_signal() +{ + for (int i = 0; i < NUMDEV; i++) + { + if (input[i].vid == 0xf143 && strstr(input[i].name, "OpenFIRE ") && + strstr(input[i].devname, "mouse") == NULL) + { + // OF generates 3 devices, so just focus on the one actual gamepad slot. + char *nameInit = input[i].name; + if (memcmp(nameInit+strlen(input[i].name)-5, "Mouse", 5) != 0 && memcmp(nameInit+strlen(input[i].name)-8, "Keyboard", 8) != 0) + { + char mname[strlen(input[i].name)]; + strcpy(mname, input[i].name); + + // Cleanup mname to replace offending characters not used in device filepath. + char *p; + while ((p = strchr(mname, '/'))) *p = '_'; + while ((p = strchr(mname, ' '))) *p = '_'; + while ((p = strchr(mname, '*'))) *p = '_'; + while ((p = strchr(mname, ':'))) *p = '_'; + + char devicePath[29+strlen(mname)+strlen(strrchr(input[i].id, '/')+1)]; + sprintf(devicePath, "/dev/serial/by-id/usb-%s_%s-if00", mname, strrchr(input[i].id, '/')+1); + + FILE *deviceFile = fopen(devicePath, "r+"); + if(deviceFile == NULL) { + printf("Failed to send command to %s: device path doesn't exist?\n", input[i].name); + } else { + fprintf(deviceFile, "M0x9"); + printf("%s (device no. %i) set to MiSTer-compatible mode.\n", input[i].name, i); + fclose(deviceFile); + } + } + } + } +} + void check_joycon() { while (1) @@ -4890,17 +4927,35 @@ int input_test(int getchar) input_lightgun_load(n); } - //Blamcon Lightgun - if (input[n].vid == 0x3673 && ((input[n].pid >= 0x0100 && input[n].pid <= 0x0103) || (input[n].pid >= 0x0200 && input[n].pid <= 0x0203))) - { - input[n].quirk = QUIRK_LIGHTGUN; - input[n].lightgun = 1; - input[n].guncal[0] = 0; - input[n].guncal[1] = 32767; - input[n].guncal[2] = 0; - input[n].guncal[3] = 32767; - input_lightgun_load(n); - } + //OpenFIRE Lightgun + //!Note that OF has a user-configurable PID, but the VID is reserved and every device name has the prefix "OpenFIRE" + if (input[n].vid == 0xf143 && strstr(input[n].name, "OpenFIRE ")) + { + // OF generates 3 devices, so just focus on the one actual gamepad slot. + char *nameInit = input[n].name; + if(memcmp(nameInit+strlen(input[n].name)-5, "Mouse", 5) != 0 && memcmp(nameInit+strlen(input[n].name)-8, "Keyboard", 8) != 0) + { + input[n].quirk = QUIRK_LIGHTGUN; + input[n].lightgun = 1; + input[n].guncal[0] = -32767; + input[n].guncal[1] = 32767; + input[n].guncal[2] = -32767; + input[n].guncal[3] = 32767; + input_lightgun_load(n); + } + } + + //Blamcon Lightgun + if (input[n].vid == 0x3673 && ((input[n].pid >= 0x0100 && input[n].pid <= 0x0103) || (input[n].pid >= 0x0200 && input[n].pid <= 0x0203))) + { + input[n].quirk = QUIRK_LIGHTGUN; + input[n].lightgun = 1; + input[n].guncal[0] = 0; + input[n].guncal[1] = 32767; + input[n].guncal[2] = 0; + input[n].guncal[3] = 32767; + input_lightgun_load(n); + } //Retroshooter if (input[n].vid == 0x0483 && input[n].pid >= 0x5750 && input[n].pid <= 0x5753) @@ -4991,6 +5046,7 @@ int input_test(int getchar) mergedevs(); check_joycon(); + openfire_signal(); setup_wheels(); for (int i = 0; i < n; i++) {