shithub: evdump

ref: 4aab52143cce6e8105b4fd50311b21628c61cb3f
dir: /kbfind.c/

View raw version
#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);
}