aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2026-01-06 21:54:09 -0500
committerB. Watson <urchlay@slackware.uk>2026-01-06 21:54:09 -0500
commit4a0c54f0bad4a853e5bec7b9ad7ad5c6e1e32bd2 (patch)
tree465dce77e1a65e7bf14ea154126c284c6083f409
parentd565dd895c8029b8dd6afcf9bd41ea7c77a69ae9 (diff)
downloadmarsond-4a0c54f0bad4a853e5bec7b9ad7ad5c6e1e32bd2.tar.gz
Handle left and right shift, allow shift+enter.
-rw-r--r--marsond.841
-rw-r--r--marsond.c77
-rw-r--r--marsond.rst41
-rw-r--r--usage.c1
4 files changed, 110 insertions, 50 deletions
diff --git a/marsond.8 b/marsond.8
index a5c8db1..73df335 100644
--- a/marsond.8
+++ b/marsond.8
@@ -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,
diff --git a/marsond.c b/marsond.c
index 7aeb52d..d936569 100644
--- a/marsond.c
+++ b/marsond.c
@@ -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,
diff --git a/usage.c b/usage.c
index 847cc76..b9d3d93 100644
--- a/usage.c
+++ b/usage.c
@@ -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.",