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

This commit is contained in:
Sigrid 2020-03-28 15:37:48 +01:00
parent 47e3c088c9
commit 9014360921
2 changed files with 48 additions and 7 deletions

View file

@ -7,15 +7,17 @@ kbd \- pc keyboard driver
.B /dev/scancode
.B /dev/leds
.B /dev/repeat
.fi
.SH DESCRIPTION
.PP
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,14 +31,27 @@ file can be only opened once by the hostowner.
.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)
.SH SOURCE

View file

@ -40,12 +40,14 @@ enum {
Qdir,
Qscancode,
Qleds,
Qrepeat,
};
static Dirtab kbdtab[] = {
".", {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 @@ setleds(int leds)
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,16 +381,18 @@ kbdwrite(Chan *c, void *a, long n, vlong)
{
char tmp[8+1], *p;
if(c->qid.path != Qleds)
error(Egreg);
p = tmp + n;
if(n >= sizeof(tmp))
p = tmp + sizeof(tmp)-1;
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;
}