ref: 4aab52143cce6e8105b4fd50311b21628c61cb3f
dir: /kbfind.c/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <keyboard.h>
typedef struct {
int e;
int c;
int r;
}K;
static K k[1280];
static int nk, kbmap, kbd;
static int k0, ke;
static int ak0, ake;
static int nohits, left;
enum {
Kunmapped = 0xf789,
};
static void
mapto(Rune r)
{
int i;
/* disable the range */
for(i = k0; i <= ke; i++)
fprint(kbmap, "%d\t%d\t%d\n", k[i].e, k[i].c, r);
}
static void
revert(void)
{
mapto(0);
}
static void
hit(int unmapped)
{
char kbup[32];
/* disable mapping */
mapto(0);
if(unmapped){
nohits = 0;
/* got a hit */
if(k0 == ke){
/* only one left */
print("%d\t%d\t0\n", k[k0].e, k[k0].c);
/* skip key up so there isn't garbage printed out */
read(kbd, kbup, sizeof(kbup));
exits(nil);
}
/* reduce */
ake = ke;
ke = k0 + (ke-k0)/2;
ak0 = ke+1;
}else if(++nohits > 1){
nohits = 0;
if(k0 == ak0 && ke == ake){
/* give up */
fprint(2, "key doesn't work\n");
exits(nil);
}
/* try a different half */
k0 = ak0;
ke = ake;
}
if(left != ke-k0+1){
left = ke-k0+1;
fprint(2, "%d possible left\n", left);
}
/* enable the new range */
mapto(Kunmapped);
}
void
main(int argc, char **argv)
{
Biobuf *b;
char *s, buf[128], buf2[128];
int n;
Rune r;
USED(argc); USED(argv);
if((b = Bopen("/dev/kbmap", OREAD)) == nil)
sysfatal("%r");
for(nk = 0; nk < nelem(k);){
if((s = Brdline(b, '\n')) == nil)
break;
k[nk].e = strtol(s, &s, 10);
k[nk].c = strtol(s, &s, 10);
k[nk].r = strtol(s, &s, 10);
if(k[nk].r == 0)
nk++;
}
if(nk < 1)
sysfatal("no keys to map");
Bterm(b);
fprint(2, "there are %d unmapped keys\n", nk);
ke = nk-1;
kbd = -1;
if((kbmap = open("/dev/kbmap", OWRITE)) < 0 || (kbd = open("/dev/kbd", OREAD)) < 0)
sysfatal("%r");
mapto(Kunmapped);
buf2[0] = 0;
buf2[1] = 0;
buf[0] = 0;
for(;;){
if(buf[0] != 0){
n = strlen(buf)+1;
memmove(buf, buf+n, sizeof(buf)-n);
}
if(buf[0] == 0){
n = read(kbd, buf, sizeof(buf)-1);
if(n <= 0)
break;
buf[n-1] = 0;
}
switch(buf[0]){
case 'k':
s = buf+1;
while(*s){
s += chartorune(&r, s);
if(utfrune(buf2+1, r) == nil){
if(r == Kdel)
goto end;
if(r == Kshift || r == Kalt || r == Kctl){
fprint(2, "please don't press shift/alt/ctl\n");
continue;
}
hit(r == Kunmapped);
}
}
break;
case 'K':
s = buf2+1;
while(*s)
s += chartorune(&r, s);
break;
default:
continue;
}
strcpy(buf2, buf);
}
end:
exits(nil);
}