| @@ -0,0 +1,159 @@ |
| | 1 | #include <u.h> |
| | 2 | #include <libc.h> |
| | 3 | #include <bio.h> |
| | 4 | #include <keyboard.h> |
| | 5 | |
| | 6 | typedef struct { |
| | 7 | int e; |
| | 8 | int c; |
| | 9 | int r; |
| | 10 | }K; |
| | 11 | |
| | 12 | static K k[1280]; |
| | 13 | static int nk, kbmap, kbd; |
| | 14 | static int k0, ke; |
| | 15 | static int ak0, ake; |
| | 16 | static int nohits, left; |
| | 17 | |
| | 18 | enum { |
| | 19 | Kunmapped = 0xf789, |
| | 20 | }; |
| | 21 | |
| | 22 | static void |
| | 23 | mapto(Rune r) |
| | 24 | { |
| | 25 | int i; |
| | 26 | |
| | 27 | /* disable the range */ |
| | 28 | for(i = k0; i <= ke; i++) |
| | 29 | fprint(kbmap, "%d\t%d\t%d\n", k[i].e, k[i].c, r); |
| | 30 | } |
| | 31 | |
| | 32 | static void |
| | 33 | revert(void) |
| | 34 | { |
| | 35 | mapto(0); |
| | 36 | } |
| | 37 | |
| | 38 | static void |
| | 39 | hit(int unmapped) |
| | 40 | { |
| | 41 | char kbup[32]; |
| | 42 | |
| | 43 | /* disable mapping */ |
| | 44 | mapto(0); |
| | 45 | |
| | 46 | if(unmapped){ |
| | 47 | nohits = 0; |
| | 48 | /* got a hit */ |
| | 49 | if(k0 == ke){ |
| | 50 | /* only one left */ |
| | 51 | print("%d\t%d\t0\n", k[k0].e, k[k0].c); |
| | 52 | /* skip key up so there isn't garbage printed out */ |
| | 53 | read(kbd, kbup, sizeof(kbup)); |
| | 54 | exits(nil); |
| | 55 | } |
| | 56 | /* reduce */ |
| | 57 | ake = ke; |
| | 58 | ke = k0 + (ke-k0)/2; |
| | 59 | ak0 = ke+1; |
| | 60 | }else if(++nohits > 1){ |
| | 61 | nohits = 0; |
| | 62 | if(k0 == ak0 && ke == ake){ |
| | 63 | /* give up */ |
| | 64 | fprint(2, "key doesn't work\n"); |
| | 65 | exits(nil); |
| | 66 | } |
| | 67 | /* try a different half */ |
| | 68 | k0 = ak0; |
| | 69 | ke = ake; |
| | 70 | } |
| | 71 | if(left != ke-k0+1){ |
| | 72 | left = ke-k0+1; |
| | 73 | fprint(2, "%d possible left\n", left); |
| | 74 | } |
| | 75 | |
| | 76 | /* enable the new range */ |
| | 77 | mapto(Kunmapped); |
| | 78 | } |
| | 79 | |
| | 80 | void |
| | 81 | main(int argc, char **argv) |
| | 82 | { |
| | 83 | Biobuf *b; |
| | 84 | char *s, buf[128], buf2[128]; |
| | 85 | int n; |
| | 86 | Rune r; |
| | 87 | |
| | 88 | USED(argc); USED(argv); |
| | 89 | |
| | 90 | if((b = Bopen("/dev/kbmap", OREAD)) == nil) |
| | 91 | sysfatal("%r"); |
| | 92 | for(nk = 0; nk < nelem(k);){ |
| | 93 | if((s = Brdline(b, '\n')) == nil) |
| | 94 | break; |
| | 95 | k[nk].e = strtol(s, &s, 10); |
| | 96 | k[nk].c = strtol(s, &s, 10); |
| | 97 | k[nk].r = strtol(s, &s, 10); |
| | 98 | if(k[nk].r == 0) |
| | 99 | nk++; |
| | 100 | } |
| | 101 | if(nk < 1) |
| | 102 | sysfatal("no keys to map"); |
| | 103 | Bterm(b); |
| | 104 | fprint(2, "there are %d unmapped keys\n", nk); |
| | 105 | ke = nk-1; |
| | 106 | |
| | 107 | kbd = -1; |
| | 108 | if((kbmap = open("/dev/kbmap", OWRITE)) < 0 || (kbd = open("/dev/kbd", OREAD)) < 0) |
| | 109 | sysfatal("%r"); |
| | 110 | mapto(Kunmapped); |
| | 111 | |
| | 112 | buf2[0] = 0; |
| | 113 | buf2[1] = 0; |
| | 114 | buf[0] = 0; |
| | 115 | for(;;){ |
| | 116 | if(buf[0] != 0){ |
| | 117 | n = strlen(buf)+1; |
| | 118 | memmove(buf, buf+n, sizeof(buf)-n); |
| | 119 | } |
| | 120 | if(buf[0] == 0){ |
| | 121 | n = read(kbd, buf, sizeof(buf)-1); |
| | 122 | if(n <= 0) |
| | 123 | break; |
| | 124 | buf[n-1] = 0; |
| | 125 | } |
| | 126 | |
| | 127 | switch(buf[0]){ |
| | 128 | case 'k': |
| | 129 | s = buf+1; |
| | 130 | while(*s){ |
| | 131 | s += chartorune(&r, s); |
| | 132 | if(utfrune(buf2+1, r) == nil){ |
| | 133 | if(r == Kdel) |
| | 134 | goto end; |
| | 135 | if(r == Kshift || r == Kalt || r == Kctl){ |
| | 136 | fprint(2, "please don't press shift/alt/ctl\n"); |
| | 137 | continue; |
| | 138 | } |
| | 139 | hit(r == Kunmapped); |
| | 140 | } |
| | 141 | } |
| | 142 | break; |
| | 143 | |
| | 144 | case 'K': |
| | 145 | s = buf2+1; |
| | 146 | while(*s) |
| | 147 | s += chartorune(&r, s); |
| | 148 | break; |
| | 149 | |
| | 150 | default: |
| | 151 | continue; |
| | 152 | } |
| | 153 | |
| | 154 | strcpy(buf2, buf); |
| | 155 | } |
| | 156 | |
| | 157 | end: |
| | 158 | exits(nil); |
| | 159 | } |