[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MiNT] Keyboard repeat bug



Vincent Rivière wrote:
It is probably wiser to wait after the release for fixing that bug safely ?

I have dug again into that problem.

With some TOS versions (to be defined) and EmuTOS, things are simple: simulating any key release will clear the key repeat flag and solve the problem.

With TOS 4.04, things are more complicated: a key release clears the key repeat flag only if it is the key that is currently repeating. The new problem is: which key is repeating, if any ? As a workaround, I have tried to simulate a key press (scancode 0 for example) followed by a key release. And it works. Unfortunately, that simulated key goes into the IOREC buffer which is reused by MiNT. As a result, when MiNT startups, this fake keystroke attains the OS, and of course this is not desirable. It can be easily seen when booting into MiS (the MiNT Shell), there is an initial ^@ on the command line. But no key repeat problem.

For memory and comments, I post this new patch. It is cleaner than the previous, but it has the drawbacks I have explained above.
Please don't apply it to CVS, it is experimental.

I'm sad to say it will be more sensible to wait after the release to work on this problem and make the required tests.

NB: A dirty but definitive solution would be to test the TOS version and use the undocumented address of the keyboard repeat flag.

--
Vincent Rivière
diff -aurN freemint-CVS-20101214.orig/sys/arch/init_intr.c freemint-CVS-20101214/sys/arch/init_intr.c
--- freemint-CVS-20101214.orig/sys/arch/init_intr.c	2010-12-14 19:36:38.546875000 +0100
+++ freemint-CVS-20101214/sys/arch/init_intr.c	2010-12-14 23:00:29.649686100 +0100
@@ -98,6 +98,46 @@
 	{
 #ifndef MILAN
 		savesr = splhigh();
+
+		/*
+		 * If a key is currently down, the TOS is currently using the system
+		 * timer for the key repeat feature. If we replace the IKBD handler
+		 * now without taking care, the TOS will never catch the key release
+		 * event and will continue repeating the key infinitely.
+		 * A workaround is to simulate a key release event right now to stop
+		 * the potential key repeat, just before replacing the IKBD handler.
+		 */
+		{
+			/* Get the TOS version */
+			unsigned short* posheader = *(unsigned short**)0x4f2;
+			unsigned short osversion = posheader[1];
+
+			/* The additional vector "kbdvec" is only present on TOS >= 2.x */
+			if (osversion >= 0x0200)
+			{
+				/* The kbdvec vector is located just before the KBDVEC structure */
+				void** vectors = (void**)syskey;
+				void* kbdvec = vectors[-1];
+				void* ikbdiorec = TRAP_Iorec(1);
+
+				/* Simulate a key release */
+				__asm__ volatile
+				(
+					"moveq	#0,d0\n\t"	/* Press scancode 0 */
+					"move.l	%1,a0\n\t"
+					"move.l	%0,a1\n\t"
+					"jsr	(a1)\n\t"
+					"move.w	#0x80,d0\n\t"	/* Release scancode 0 */
+					"move.l	%1,a0\n\t"
+					"move.l	%0,a1\n\t"
+					"jsr	(a1)"
+				:					/* outputs */
+				: "g"(kbdvec), "g"(ikbdiorec)		/* inputs  */
+				: "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */
+				);
+			}
+		}
+
 		syskey->ikbdsys = (long)ikbdsys_handler;
 #ifndef M68000
 		cpush(&syskey->ikbdsys, sizeof(long));