shithub: riscv

Download patch

ref: 90143609212ed4500409a64d26f6b12d097b13ed
parent: 47e3c088c90944e49041c8b210dd7169479738da
author: Sigrid <[email protected]>
date: Sat Mar 28 11:37:48 EDT 2020

kbd: add "repeat" file to set typematic repeat rate/delay on PS/2 keyboards

--- a/sys/man/3/kbd
+++ b/sys/man/3/kbd
@@ -7,6 +7,7 @@
 
 .B /dev/scancode
 .B /dev/leds
+.B /dev/repeat
 .fi
 .SH DESCRIPTION
 .PP
@@ -13,9 +14,10 @@
 The
 .I kbd
 device serves a one-level directory containing the files
-.BR scancode
+.BR scancode ,
+.BR leds
 and
-.BR leds .
+.BR repeat .
 .PP
 Reading the
 .BR scancode
@@ -29,13 +31,26 @@
 .PP
 Writing a number to the write-only 
 .BR leds
-file changes the status leds on the keyboard. the value of the
+file changes the status leds on the keyboard. The value of the
 number is the addition of 1, 2 and 4 representing activated
 Scroll, Num and Caps leds.
+.PP
+The
+.BR repeat
+file sets typematic rate and delay.  The value of the number is a
+bitmask where first 5 bits set the repeat rate (ranging from 0b00000
+for 30Hz to 0b11111 for 2Hz).  Bits 6 and 7 set the delay before the
+first repeat is activated (ranging from 0b00 for 250Hz to 0b11 for
+1000Hz).
 .SH EXAMPLE 
 Set the Scroll and Caps leds:
 .EX
 echo 5 >/dev/leds
+.EE
+.PP
+Enable fast repeat rate and the least delay:
+.EX
+echo 0 >/dev/repeat
 .EE
 .SH "SEE ALSO"
 .IR kbdfs (8)
--- a/sys/src/9/pc/devkbd.c
+++ b/sys/src/9/pc/devkbd.c
@@ -40,6 +40,7 @@
 	Qdir,
 	Qscancode,
 	Qleds,
+	Qrepeat,
 };
 
 static Dirtab kbdtab[] = {
@@ -46,6 +47,7 @@
 	".",		{Qdir, 0, QTDIR},	0,	0555,
 	"scancode",	{Qscancode, 0},		0,	0440,
 	"leds",		{Qleds, 0},		0,	0220,
+	"repeat",	{Qrepeat, 0},		0,	0220,
 };
 
 static Lock i8042lock;
@@ -193,6 +195,28 @@
 	iunlock(&i8042lock);
 }
 
+static void
+setrepeat(int repeat)
+{
+	if(nokbd)
+		return;
+
+	repeat &= 0x7f;
+	ilock(&i8042lock);
+	for(;;){
+		if(outready() < 0)
+			break;
+		outb(Data, 0xf3);		/* `set typematic rate and delay' */
+		if(outready() < 0)
+			break;
+		outb(Data, repeat);
+		if(outready() < 0)
+			break;
+		break;
+	}
+	iunlock(&i8042lock);
+}
+
 /*
  *  keyboard interrupt
  */
@@ -357,9 +381,6 @@
 {
 	char tmp[8+1], *p;
 
-	if(c->qid.path != Qleds)
-		error(Egreg);
-
 	p = tmp + n;
 	if(n >= sizeof(tmp))
 		p = tmp + sizeof(tmp)-1;
@@ -366,7 +387,12 @@
 	memmove(tmp, a, p - tmp);
 	*p = 0;
 
-	setleds(atoi(tmp));
+	if(c->qid.path == Qleds)
+		setleds(atoi(tmp));
+	else if(c->qid.path == Qrepeat)
+		setrepeat(atoi(tmp));
+	else
+		error(Egreg);
 
 	return n;
 }