ref: 92425f089e4966c8ed400041ef3a80098d746956
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Wed Sep 2 09:06:00 EDT 2020
first
--- /dev/null
+++ b/.gitignore
@@ -1,0 +1,2 @@
+[a0125678vqki].out
+*.[o0125678vqki]
--- /dev/null
+++ b/README.md
@@ -1,0 +1,28 @@
+# aux/kbfind
+
+Finds the correct `/dev/kbmap` entry for a non-working key on your
+keyboard, in 9front.
+
+## Process
+
+1) after installing (`mk install`) run `aux/kbfind`.
+2) press the non-working key _once_
+3) press any other _working_ key _once_ (or Delete to exit)
+4) go to step 2
+
+If the key was not mapped before and is producing scancodes,
+eventually the program will print out the needed entry that needs to
+be put into `/dev/kbmap` for the key to work. Replace the last `0` of
+that entry to whichever Rune you want your key to produce, converted
+to a number, see `/sys/include/keyboard.h` for some of the existing
+"special" keys.
+
+## How does this work
+
+Unmapped entries in `/dev/kbmap` have the Rune (third number) set to
+0. `aux/kbfind` sets those entries to a custom Rune and awaits for
+key presses to be available on `/dev/kbd`. If the custom Rune was
+found the entries currently enabled are cut into half to see whether
+the key would still produce the rune. If not, the other half is
+enabled instead and the process is repeated, cutting the number of
+keys to test in half every time.
--- /dev/null
+++ b/kbfind.c
@@ -1,0 +1,159 @@
+#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);
+}
--- /dev/null
+++ b/mkfile
@@ -1,0 +1,6 @@
+</$objtype/mkfile
+BIN=/$objtype/bin/aux
+TARG=kbfind
+OFILES=kbfind.$O
+default:V: all
+</sys/src/cmd/mkone