diff options
| author | B. Watson <urchlay@slackware.uk> | 2026-01-06 21:54:09 -0500 |
|---|---|---|
| committer | B. Watson <urchlay@slackware.uk> | 2026-01-06 21:54:09 -0500 |
| commit | 4a0c54f0bad4a853e5bec7b9ad7ad5c6e1e32bd2 (patch) | |
| tree | 465dce77e1a65e7bf14ea154126c284c6083f409 | |
| parent | d565dd895c8029b8dd6afcf9bd41ea7c77a69ae9 (diff) | |
| download | marsond-4a0c54f0bad4a853e5bec7b9ad7ad5c6e1e32bd2.tar.gz | |
Handle left and right shift, allow shift+enter.
| -rw-r--r-- | marsond.8 | 41 | ||||
| -rw-r--r-- | marsond.c | 77 | ||||
| -rw-r--r-- | marsond.rst | 41 | ||||
| -rw-r--r-- | usage.c | 1 |
4 files changed, 110 insertions, 50 deletions
@@ -27,9 +27,9 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. -.TH "MARSOND" 8 "2026-01-05" "0.4.0" "Urchlay's Stuff" +.TH "MARSOND" 8 "2026-01-06" "0.4.0" "Urchlay's Stuff" .SH NAME -marsond \- Fix Enter key timing on Marson/USBLink/MT606-1 PS/2-USB adaptors +marsond \- Fix Enter/Shift key timings on Marson/USBLink/MT606-1 PS/2-USB adaptors .SH SYNOPSIS .sp marsond [\fB\-d\fP \fIdelay\-ms\fP] [\fB\-f\fP] [\fB\-k\fP \fIkeyboard\-device\fP] [\fB\-p\fP \fIpause_ms\fP [\fB\-v\fP] | [\fB\-\-help\fP] | [\fB\-\-version\fP] | [\fB\-V\fP] @@ -43,9 +43,10 @@ In games and emulators, the Enter key only works sometimes. This is caused by the firmware in the adaptor sending the keypress and release events only 8 milliseconds apart. .IP \(bu 2 -In normal use, pressing and releasing the right Shift key and Enter +In normal use, pressing either Shift key and Enter key simultaneously causes the shift key to get "stuck" and act like -it\(aqs still being held down. +it\(aqs still being held down. You have to press and release Shift again +to get it to "unstick". .UNINDENT .sp See the \fBNOTES\fP section for full details. @@ -67,8 +68,10 @@ Options can be "bundled": \fB\-vf\fP is the same as \fB\-v\fP \fB\-f\fP\&. .INDENT 0.0 .TP .BI \-d \ delay\-ms -Amount of time in milliseconds to delay the Enter key release events. -Minimum 1, default 30 (unless changed at compile time; see \fB\-\-help\fP). +Amount of time in milliseconds to delay the Enter key release +events. Also, the Shift key threshold is this times 4, unless set +with the \fB\-s\fP option. Minimum 1, default 30 (unless changed at +compile time; see \fB\-\-help\fP). .UNINDENT .\" delay time for Enter key release. . @@ -111,6 +114,16 @@ if started manually. Minimum 0, default 0. . .INDENT 0.0 .TP +.BI \-s \ thresh\-ms +Threshold for Shift key. If Enter is pressed within \fBthresh\-ms\fP of +either Shift key, a Shift key release will be sent before the Enter +keypress. This avoids the "stuck shift key" problem. Default is +120, or 4 times the \fB\-d\fP delay if set. +.UNINDENT +.\" threshold in ms for shift key followed by enter (default 30 or -d * 3). +. +.INDENT 0.0 +.TP .B \-v Verbose debugging mode. Prints copious trace information to \fBstderr\fP\&. Debugging mode is turned off when \fBmarsond\fP forks itself into the @@ -153,11 +166,13 @@ The Enter key dropped keystroke problem happens with any SDL application (SDL1 or SDL2), as well as other graphics libraries. It happens regardless of what PS/2 keyboard you have plugged in, what computer you have the adaptor plugged into, or what OS that computer -is running. +is running. The firmware in the adaptor sends an Enter keypress, then +8 microseconds later sends an Enter key release. There is no way to +change this. .sp The problem where Shift/Enter causes the Shift key to act "stuck" happens in any application. It\(aqs particularly annoying because I\(aqm an -inaccurate typist, and I hit Shift+Enter about 5% of the time when I\(aqm +inaccurate typist, and I hit right Shift+Enter about 5% of the time when I\(aqm just trying to press Enter. .sp The specific hardware that has the problems for me is USB @@ -213,10 +228,12 @@ the real keyboard to the virtual one. When it sees the key release event for the Enter key, it simply pauses for a few milliseconds before delivering it. .sp -It also keeps track of whether the last keypress was the right Shift -key, and when it sees an Enter keypress while right Shift is held -down, it sends a right Shift key release event before the Enter press -event. +It also keeps track of the last timestamp of the left and right Shift +keys, and if Enter is pressed too soon after Shift, it sends a key +release for the Shift key(s). It\(aqs still possible to type Shift+Enter +on purpose, but there must be a delay (default 120ms) between the two +keypresses. Most people, even fast typists, won\(aqt press them that +close together. .sp This should work with everything that uses the keyboard. It definitely does, with SDL 1 and 2 running under X (and SDL 1 on the console, @@ -8,6 +8,7 @@ #include <errno.h> #include <stdarg.h> #include <sys/types.h> +#include <sys/time.h> #include <pwd.h> #include <grp.h> #include <signal.h> @@ -44,6 +45,7 @@ int debugging = 0; /* -v */ int foreground = 0; /* -v */ const char *keyboard_dev = DEFAULT_KBD; /* -k */ int delay_ms = DEFAULT_DELAY_MS; /* -d */ +int shift_ms = 0; /* -s, -d */ int pause_ms = 0; /* -p */ int infd = -1, outfd = -1; @@ -64,6 +66,7 @@ void logmsg(const char *prefix, const char *fmt, ...) { #define warn(fmt, ...) { logmsg("warning", fmt, ##__VA_ARGS__); }; #define info(fmt, ...) { logmsg("info", fmt, ##__VA_ARGS__); }; #define debug(fmt, ...) { if(debugging) logmsg("debug", fmt, ##__VA_ARGS__); }; +#define debug_fg(fmt, ...) { if(debugging && foreground) logmsg("debug", fmt, ##__VA_ARGS__); }; void set_self(const char *argv0) { char *p; @@ -120,9 +123,10 @@ void parse_args(int argc, char **argv) { } } - while( (opt = getopt(argc, argv, ":d:hfk:p:vV")) != -1) { + while( (opt = getopt(argc, argv, ":d:s:hfk:p:vV")) != -1) { switch(opt) { case 'd': delay_ms = parse_num(optarg, 'd', 1); break; + case 's': shift_ms = parse_num(optarg, 's', 1); break; case 'f': foreground++; break; case 'h': print_help(); exit(0); break; case 'k': keyboard_dev = optarg; break; @@ -137,6 +141,8 @@ void parse_args(int argc, char **argv) { if(optind < argc) { die("unknown argument: %s", argv[optind]); } + + if(!shift_ms) shift_ms = delay_ms * 4; } /* cleanup() gets called by die() and sighandler() */ @@ -329,10 +335,28 @@ void write_event(struct input_event *ev) { } } +long long gettime_millis(void) { + struct timeval tv; + + gettimeofday(&tv, 0); + return(tv.tv_sec * 1000 + tv.tv_usec / 1000); +} + +void release_key(int code) { + struct input_event ev; + + ev.type = EV_KEY; + ev.code = code; + ev.value = 0; + + write_event(&ev); +} + int main(int argc, char **argv) { - int i, was_shift = 0; + int i; + long long last_l_shift = 0, last_r_shift = 0; struct uinput_user_dev dev; - struct input_event ev, shift_release; + struct input_event ev; set_self(argv[0]); @@ -429,35 +453,38 @@ int main(int argc, char **argv) { } } - if(foreground) { - debug("got event: type %d, code 0x%02x, value %d", - ev.type, ev.code, ev.value); - } + debug_fg("got event: type %d, code 0x%02x, value %d", + ev.type, ev.code, ev.value); - if(ev.type == EV_KEY && ev.code == KEY_RIGHTSHIFT) { - was_shift = ev.value; + if(ev.type == EV_KEY && ev.value == 1) { + if(ev.code == KEY_RIGHTSHIFT) { + last_r_shift = (ev.value ? gettime_millis() : 0); + debug_fg("last_r_shift %lld", last_r_shift); + } else if(ev.code == KEY_LEFTSHIFT) { + last_l_shift = (ev.value ? gettime_millis() : 0); + debug_fg("last_l_shift %lld", last_l_shift); + } } - if(ev.type == EV_KEY && ev.code == KEY_ENTER && ev.value == 1) { - if(was_shift) { - if(foreground) { - debug("!!! got Enter keypress with was_shift==1, sending " - "Shift key release before Enter keypress"); + /* ev.value: 0 == release, 1 == initial press, 2 == repeat */ + if(ev.type == EV_KEY) { + if(ev.code == KEY_ENTER && ev.value == 1) { + if(last_r_shift && (gettime_millis() < (last_r_shift + shift_ms))) { + debug_fg("!!! Enter pressed; last right shift press < %dms ago, sending right shift release", shift_ms); + release_key(KEY_RIGHTSHIFT); + last_r_shift = 0; + } + if(last_l_shift && (gettime_millis() < (last_l_shift + shift_ms))) { + debug_fg("!!! Enter pressed; last left shift press < %dms ago, sending left shift release", shift_ms); + release_key(KEY_LEFTSHIFT); + last_l_shift = 0; } - memcpy(&shift_release, &ev, sizeof(ev)); - shift_release.code = KEY_RIGHTSHIFT; - shift_release.value = 0; - write_event(&shift_release); - was_shift = 0; } - } - /* value == 0 means key release (a 1 would be a press) */ - if(ev.type == EV_KEY && ev.code == KEY_ENTER && ev.value == 0) { - if(foreground) { - debug("!!! got Enter key release, delaying %d ms", delay_ms); + if(ev.code == KEY_ENTER && ev.value == 0) { + debug_fg("!!! got Enter key release, delaying %dms", delay_ms); + usleep(delay_ms * 1000); } - usleep(delay_ms * 1000); } write_event(&ev); diff --git a/marsond.rst b/marsond.rst index ad41577..accc03f 100644 --- a/marsond.rst +++ b/marsond.rst @@ -6,9 +6,9 @@ marsond ======= ----------------------------------------------------------------- -Fix Enter key timing on Marson/USBLink/MT606-1 PS/2-USB adaptors ----------------------------------------------------------------- +----------------------------------------------------------------------- +Fix Enter/Shift key timings on Marson/USBLink/MT606-1 PS/2-USB adaptors +----------------------------------------------------------------------- :Manual section: 8 :Manual group: Urchlay's Stuff @@ -30,9 +30,10 @@ keyboard adaptor. The symptoms: caused by the firmware in the adaptor sending the keypress and release events only 8 milliseconds apart. -- In normal use, pressing and releasing the right Shift key and Enter +- In normal use, pressing either Shift key and Enter key simultaneously causes the shift key to get "stuck" and act like - it's still being held down. + it's still being held down. You have to press and release Shift again + to get it to "unstick". See the **NOTES** section for full details. @@ -51,8 +52,10 @@ OPTIONS Options can be "bundled": **-vf** is the same as **-v** **-f**. -d delay-ms - Amount of time in milliseconds to delay the Enter key release events. - Minimum 1, default 30 (unless changed at compile time; see **--help**). + Amount of time in milliseconds to delay the Enter key release + events. Also, the Shift key threshold is this times 4, unless set + with the **-s** option. Minimum 1, default 30 (unless changed at + compile time; see **--help**). .. delay time for Enter key release. @@ -79,6 +82,14 @@ Options can be "bundled": **-vf** is the same as **-v** **-f**. .. pause before opening keyboard/uinput devs (default 0). +-s thresh-ms + Threshold for Shift key. If Enter is pressed within **thresh-ms** of + either Shift key, a Shift key release will be sent before the Enter + keypress. This avoids the "stuck shift key" problem. Default is + 120, or 4 times the **-d** delay if set. + +.. threshold in ms for shift key followed by enter (default 30 or -d * 3). + -v Verbose debugging mode. Prints copious trace information to **stderr**. Debugging mode is turned off when **marsond** forks itself into the @@ -120,11 +131,13 @@ The Enter key dropped keystroke problem happens with any SDL application (SDL1 or SDL2), as well as other graphics libraries. It happens regardless of what PS/2 keyboard you have plugged in, what computer you have the adaptor plugged into, or what OS that computer -is running. +is running. The firmware in the adaptor sends an Enter keypress, then +8 microseconds later sends an Enter key release. There is no way to +change this. The problem where Shift/Enter causes the Shift key to act "stuck" happens in any application. It's particularly annoying because I'm an -inaccurate typist, and I hit Shift+Enter about 5% of the time when I'm +inaccurate typist, and I hit right Shift+Enter about 5% of the time when I'm just trying to press Enter. The specific hardware that has the problems for me is USB @@ -163,10 +176,12 @@ the real keyboard to the virtual one. When it sees the key release event for the Enter key, it simply pauses for a few milliseconds before delivering it. -It also keeps track of whether the last keypress was the right Shift -key, and when it sees an Enter keypress while right Shift is held -down, it sends a right Shift key release event before the Enter press -event. +It also keeps track of the last timestamp of the left and right Shift +keys, and if Enter is pressed too soon after Shift, it sends a key +release for the Shift key(s). It's still possible to type Shift+Enter +on purpose, but there must be a delay (default 120ms) between the two +keypresses. Most people, even fast typists, won't press them that +close together. This should work with everything that uses the keyboard. It definitely does, with SDL 1 and 2 running under X (and SDL 1 on the console, @@ -3,6 +3,7 @@ const char *helptext[] = { " -f: run in foreground, not as a daemon.", " -k keyboard-device: keyboard device (usually under /dev/input/by-id/).", " -p pause-ms: pause before opening keyboard/uinput devs (default 0).", + " -s thresh-ms: threshold in ms for shift key followed by enter (default 30 or -d * 3).", " -v: verbose debugging.", " -h, --help: this help text.", " -V, --version: show version number.", |
